Version 2.17.0-69.1.beta

Merge '2.17.0-69.0.dev' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 284ed91..e47664f 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -1,6 +1,6 @@
 {
   "copyright": [
-    "Copyright (c) 2021, the Dart project authors. Please see the AUTHORS ",
+    "Copyright (c) 2022, the Dart project authors. Please see the AUTHORS ",
     "file for 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,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-12-10T17:31:54.553345",
+  "generated": "2022-01-12T18:16:46.198227",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -244,13 +244,13 @@
       "name": "dartdev",
       "rootUri": "../pkg/dartdev",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.12"
     },
     {
       "name": "dartdoc",
       "rootUri": "../third_party/pkg/dartdoc",
       "packageUri": "lib/",
-      "languageVersion": "2.11"
+      "languageVersion": "2.14"
     },
     {
       "name": "dds",
@@ -259,6 +259,12 @@
       "languageVersion": "2.13"
     },
     {
+      "name": "dds_service_extensions",
+      "rootUri": "../pkg/dds_service_extensions",
+      "packageUri": "lib/",
+      "languageVersion": "2.13"
+    },
+    {
       "name": "dev_compiler",
       "rootUri": "../pkg/dev_compiler",
       "packageUri": "lib/",
@@ -310,7 +316,7 @@
       "name": "fixnum",
       "rootUri": "../third_party/pkg/fixnum",
       "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "languageVersion": "2.12"
     },
     {
       "name": "front_end",
@@ -629,7 +635,7 @@
       "name": "source_span",
       "rootUri": "../third_party/pkg/source_span",
       "packageUri": "lib/",
-      "languageVersion": "2.12"
+      "languageVersion": "2.14"
     },
     {
       "name": "sourcemap_testing",
@@ -778,7 +784,7 @@
       "name": "watcher",
       "rootUri": "../third_party/pkg/watcher",
       "packageUri": "lib/",
-      "languageVersion": "2.12"
+      "languageVersion": "2.14"
     },
     {
       "name": "web_components",
@@ -817,4 +823,4 @@
       "languageVersion": "2.12"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/.packages b/.packages
index f5ea5bc..e8855d6 100644
--- a/.packages
+++ b/.packages
@@ -38,6 +38,7 @@
 dartdev:pkg/dartdev/lib
 dartdoc:third_party/pkg/dartdoc/lib
 dds:pkg/dds/lib
+dds_service_extensions:pkg/dds_service_extensions/lib
 dev_compiler:pkg/dev_compiler/lib
 devtools_server:third_party/devtools/devtools_server/lib
 devtools_shared:third_party/devtools/devtools_shared/lib
diff --git a/AUTHORS b/AUTHORS
index b3a3ac6..5879a77 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,3 +35,4 @@
 K. Alex Gann <k.alexgann@gmail.com>
 Kenneth Endfinger <kaendfinger@gmail.com>
 Cristian Almstrand <cristian.almstrand@gmail.com>
+Ryan Macnak <rmacnak@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4c038a..8ddc529 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,19 +1,69 @@
+## 2.17.0
+
+### Core libraries
+
+#### `dart:core`
+
+- Add `Finalizer` and `WeakReference` which can potentially detect when
+  objects are "garbage collected".
+
+#### `dart:ffi`
+
+- Add `ref=` and `[]=` methods to the `StructPointer` and `UnionPointer`
+  extensions. They copy a compound instance into a native memory region.
+
+#### `dart:indexed_db`
+
+- `IdbFactory.supportsDatabaseNames` has been deprecated. It will always return
+  `false`.
+
+#### `dart:io`
+
+- **Breaking Change** [#45410](https://github.com/dart-lang/sdk/issues/45410):
+  `HttpClient` no longer transmits some headers (i.e. `authorization`,
+  `www-authenticate`, `cookie`, `cookie2`) when processing redirects to
+  a different domain.
+
+### Tools
+
+#### Dart command line
+
+- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+  The standalone `dart2js` tool has been
+  marked deprecated as previously announced.
+  Its replacement is the `dart compile js` command.
+  Should you find any issues, or missing features, in the replacement
+  command, kindly file [an issue](https://github.com/dart-lang/sdk/issues/new).
+
+- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+  The standalone `dartdevc` tool has been marked deprecated as previously
+  announced and will be deleted in a future Dart stable relase.  This tool
+  was intended for use only by build systems like bazel, `build_web_compilers`
+  and `flutter_tools`. The functionality remains available for those systems,
+  but it is no longer exposed as a command-line tool in the SDK.
+  Please share any concerns in the 
+  [breaking change tracking issue](https://github.com/dart-lang/sdk/issues/46100).
+
+- **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+  The standalone `dartdoc` tool has been removed as
+  previously announced. Its replacement is the `dart doc` command.
+
 ## 2.16.0
 
 ### Core libraries
 
 #### `dart:core`
 
-- **Breaking Change** [#47653](https://github.com/dart-lang/sdk/issues/47653):
-  On Windows, `Directory.rename` will no longer delete a directory if
-  `newPath` specifies one. Instead, a `FileSystemException` will be thrown.
-
 - Add `Error.throwWithStackTrace` which can `throw` an
   error with an existing stack trace, instead of creating
   a new stack trace.
 
 #### `dart:io`
 
+- **Breaking Change** [#47653](https://github.com/dart-lang/sdk/issues/47653):
+On Windows, `Directory.rename` will no longer delete a directory if
+`newPath` specifies one. Instead, a `FileSystemException` will be thrown.
+
 - **Breaking Change** [#47769](https://github.com/dart-lang/sdk/issues/47769):
 The `Platform.packageRoot` API has been removed. It had been marked deprecated
 in 2018, as it doesn't work with any Dart 2.x release.
@@ -52,9 +102,29 @@
 
 [an issue]: https://github.com/dart-lang/sdk/issues/new
 
+#### Pub
+
+- Fixed race conditions in `dart pub get`, `dart run` and `dart pub global run`.
+  It should now be safe to run these concurrently.
+- If (when) Pub crashes it will save a verbose log in
+  `$PUB_CACHE/log/pub_log.txt` This can be used for filing issues to the issue
+  tracker.
+
+  `dart --verbose pub [command]` will also cause the log file to be written.
+- `dart pub add` can now add multiple packages in one command.
+
 #### Linter
 
-Updated the Linter to `1.17.1`, which includes changes that
+Updated the Linter to `1.18.0`, which includes changes that
+
+- extends `camel_case_types` to cover enums.
+- fixes `no_leading_underscores_for_local_identifiers` to not 
+  mis-flag field formal parameters with default values.
+- fixes `prefer_function_declarations_over_variables` to not
+  mis-flag non-final fields.
+- improves performance for `prefer_contains`.
+- updates `exhaustive_cases` to skip deprecated values that
+  redirect to other values.
 - adds new lint: `unnecessary_late`.
 - improves docs for `prefer_initializing_formals`.
 - updates `secure_pubspec_urls` to check `issue_tracker` and
diff --git a/DEPS b/DEPS
index 60bf931..56ed123 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "a4144628905e0d3326b2549c9a1425bfca06c681",
+  "co19_rev": "1247f4096b835f31465e8f71dece427e95b51534",
   # This line prevents conflicts when both packages are rolled simultaneously.
   "co19_2_rev": "995745937abffe9fc3a6441f9f0db27b2d706e4c",
 
@@ -59,6 +59,8 @@
   # Checkout extra javascript engines for testing or benchmarking.
   # d8, the V8 shell, is always checked out.
   "checkout_javascript_engines": False,
+  "d8_tag": "version:9.9.3",
+  "jsshell_tag": "version:95.0",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
   # should be kept up to date with the revisions pulled by the Flutter engine.
@@ -105,34 +107,33 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "08b0294d0a500d5c02168ef57dcb8868d0c3cb48",
+  "dart_style_rev": "6f894c0ca33686122be9085f06e5b9bf6ad55262",
 
-  "dartdoc_rev" : "11c4b3c9723bfa7155efcf0fef02329233a6381d",
-  "devtools_rev" : "013958fbd45351e5975068756b7b9114465a7f98",
-  "jsshell_tag": "version:88.0",
+  "dartdoc_rev" : "f9cfab1b84176873c80b89e7c8b54c669344f9ed",
+  "devtools_rev" : "f265c3028d5ed9a454762532bed144fa36b2e4d5",
   "ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
-  "fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
+  "fixnum_rev": "848341f061359ef7ddc0cad472c2ecbb036b28ac",
   "file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
   "glob_rev": "a62acf590598f458d3198d9f2930c1c9dd4b1379",
   "html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev": "de1b312164c24a1690b46c6e97bd47eff40c4649",
   "http_parser_rev": "202391286ddc13c4c3c284ac5b511f04697250ed",
-  "http_rev": "f35d1e1467092f6a5edb2abf7071c4a99e8c737a",
+  "http_rev": "1e42ffa181b263f7790f276a5465832bff7ce615",
   "icu_rev" : "81d656878ec611cb0b42d52c82e9dae93920d9ba",
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
-  "linter_tag": "1.17.1",
+  "linter_tag": "1.18.0",
   "lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
   "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "7479783f0493f6717e1d7ae31cb37d39a91026b2",
-  "matcher_rev": "6ba4a6d68bdfacff3d572c9ea98333dfc66fd6bf",
+  "matcher_rev": "07595a7739d47a8315caba5a8e58fb9ae3d81261",
   "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
-  "package_config_rev": "fb736aa12316dd2d882b202a438a6946a4b4bea0",
+  "package_config_rev": "8731bf10b5375542792a32a0f7c8a6f370583d96",
   "path_rev": "baedce9d2ca11ea2cdf54395a74eb038087777a4",
   "pedantic_rev": "66f2f6c27581c7936482e83be80b27be2719901c",
   "platform_rev": "1ffad63428bbd1b3ecaa15926bacfb724023648c",
@@ -140,7 +141,7 @@
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
   "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
-  "pub_rev": "dcb6abac2d7d43258c03b348be42bf4aab9529b1",
+  "pub_rev": "8f5ab7b1aba3b9f66b56246d77e167990339d317",
   "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
@@ -152,7 +153,7 @@
   "source_map_stack_trace_rev": "1c3026f69d9771acf2f8c176a1ab750463309cce",
   "source_maps-0.9.4_rev": "38524",
   "source_maps_rev": "6499ee3adac8d469e2953e2e8ba4bdb4c2fbef90",
-  "source_span_rev": "1be3c44045a06dff840d2ed3a13e6082d7a03a23",
+  "source_span_rev": "dc189b455d823e2919667f6c5dcb41ab7483bce0",
   "sse_rev": "9084339389eb441d0c0518cddac211a097e78657",
   "stack_trace_rev": "5220580872625ddee41e9ca9a5f3364789b2f0f6",
   "stream_channel_rev": "3fa3e40c75c210d617b8b943b9b8f580e9866a89",
@@ -166,7 +167,7 @@
   "typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
   "usage_rev": "f0cb8f7cce8b675255c81488dbab8cf9f2f56404",
   "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
-  "watcher_rev": "3924194385fb215cef483193ed2879a618a3d69c",
+  "watcher_rev": "f76997ab0c857dc5537ac0975a9ada92b54ef949",
   "webdriver_rev": "ff5ccb1522edf4bed578ead4d65e0cbc1f2c4f02",
   "web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
   "web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
@@ -213,7 +214,7 @@
   Var("dart_root") + "/third_party/d8": {
       "packages": [{
           "package": "dart/d8",
-          "version": "version:9.1.269",
+          "version": Var("d8_tag"),
       }],
       "dep_type": "cipd",
   },
@@ -225,15 +226,6 @@
       "condition": "checkout_javascript_engines",
       "dep_type": "cipd",
   },
-  # TODO(b/186078239): remove this copy to the old location
-  Var("dart_root") + "/third_party/firefox_jsshell/linux/jsshell": {
-      "packages": [{
-          "package": "dart/third_party/jsshell/linux-amd64",
-          "version": Var("jsshell_tag"),
-      }],
-      "condition": "checkout_javascript_engines",
-      "dep_type": "cipd",
-  },
   Var("dart_root") + "/third_party/devtools": {
       "packages": [{
           "package": "dart/third_party/flutter/devtools",
diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart
index 686d6bd..6178f24 100644
--- a/benchmarks/FfiMemory/dart/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart/FfiMemory.dart
@@ -15,34 +15,6 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
-/// Represents a native unsigned pointer-sized integer in C.
-///
-/// [UintPtr] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint64(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint64(),
-})
-class UintPtr extends AbiSpecificInteger {
-  const UintPtr();
-}
-
 //
 // Pointer store.
 //
diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart
index a170aaa..b3a6cf9 100644
--- a/benchmarks/FfiMemory/dart2/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart2/FfiMemory.dart
@@ -17,34 +17,6 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
-/// Represents a native unsigned pointer-sized integer in C.
-///
-/// [UintPtr] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint64(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint64(),
-})
-class UintPtr extends AbiSpecificInteger {
-  const UintPtr();
-}
-
 //
 // Pointer store.
 //
diff --git a/benchmarks/MapCopy/dart/MapCopy.dart b/benchmarks/MapCopy/dart/MapCopy.dart
new file mode 100644
index 0000000..2009c80
--- /dev/null
+++ b/benchmarks/MapCopy/dart/MapCopy.dart
@@ -0,0 +1,367 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:benchmark_harness/benchmark_harness.dart';
+
+// Benchmark for polymorphic map copying.
+//
+// The set of benchmarks compares the cost of copying default Maps
+// (LinkedHashMaps) and HashMaps, for small and large maps.
+//
+// The maps have a key type `Object?`, since we want to use Strings, ints and
+// user-defined types.  The class `Thing` is a used-defined type with an
+// inexpensive hashCode operation. String keys are interesting because they are
+// quite common, and are special-cased in the JavaScript runtime.
+//
+// Benchmarks have names following this pattern:
+//
+//     MapCopy.{Map,HashMap}.{String,Thing}.of.{Map,HashMap}.{N}
+//     MapCopy.{Map,HashMap}.{String,Thing}.copyOf.{Map,HashMap}.{N}
+//     MapCopy.{Map,HashMap}.{String,Thing}.fromEntries.{Map,HashMap}.{N}
+//
+// For example, MapCopy.Map.String.of.HashMap.2 would call
+//
+//     Map<Object, Object>.of(m)
+//
+// where `m` is a `HashMap<String, Object>` with 2 entries.
+//
+// The `copyOf` variant creates an empty map and populates it using `forEach`,
+// so MapCopy.HashMap.Thing.copyOf.HashMap.100 would call:
+//
+//    HashMap<Object, Object> result = HashMap();
+//    m.forEach((key, value) { result[key] = value; });
+//
+// where `m` is a `HashMap<Thing, Object>` with 100 entries.
+//
+// The `fromEntries` variant creates a map via `Map.fromEntries(other.entries)`.
+//
+// Benchmarks are run for small maps (e.g. 2 entries, names ending in `.2`) and
+// 'large' maps (100 entries or `.100`). The benchmarks are normalized on the
+// number of elements to make benchmarks with different input sizes more
+// comparable.
+
+abstract class Benchmark<K> extends BenchmarkBase {
+  final String targetKind; // 'Map' or 'HashMap'.
+  late final String keyKind = _keyKind(K); // 'String' or 'Thing' or 'int'.
+  final String methodKind; // 'of' or 'copyOf' or 'fromEntries'.
+  final String sourceKind; // 'Map' or 'HashMap'.
+  final int length;
+  final List<Map<Object?, Object>> inputs = [];
+
+  Benchmark(this.targetKind, this.methodKind, this.sourceKind, this.length)
+      : super('MapCopy.$targetKind.${_keyKind(K)}.$methodKind.$sourceKind'
+            '.$length');
+
+  static String _keyKind(Type type) {
+    if (type == String) return 'String';
+    if (type == int) return 'int';
+    if (type == Thing) return 'Thing';
+    throw UnsupportedError('Unsupported type $type');
+  }
+
+  /// Override this method with one that will copy [input] to [output].
+  void copy();
+
+  @override
+  void setup() {
+    // Ensure setup() is idempotent.
+    if (inputs.isNotEmpty) return;
+
+    const totalEntries = 1000;
+
+    int totalLength = 0;
+    while (totalLength < totalEntries) {
+      final sample = makeSample();
+      inputs.add(sample);
+      totalLength += sample.length;
+    }
+
+    // Sanity checks.
+    for (var sample in inputs) {
+      if (sample.length != length) throw 'Wrong length: $length $sample';
+    }
+    if (totalLength != totalEntries) {
+      throw 'totalLength $totalLength != expected $totalEntries';
+    }
+  }
+
+  int _sequence = 0;
+
+  Map<Object?, Object> makeSample() {
+    late final Map<K, Object> sample;
+    if (sourceKind == 'Map') sample = {};
+    if (sourceKind == 'HashMap') sample = HashMap();
+    for (int i = 1; i <= length; i++) {
+      _sequence = (_sequence + 119) & 0x1ffffff;
+      final K key = makeKey(_sequence);
+      sample[key] = i;
+    }
+    return sample;
+  }
+
+  K makeKey(int i) {
+    if (keyKind == 'String') return 'key-$i' as K;
+    if (keyKind == 'int') return i as K;
+    if (keyKind == 'Thing') return Thing() as K;
+    throw UnsupportedError('Unsupported type $K');
+  }
+
+  @override
+  void run() {
+    for (var sample in inputs) {
+      input = sample;
+      copy();
+    }
+    if (output.length != inputs.first.length) throw 'Bad result: $output';
+  }
+}
+
+class Thing {
+  static int _counter = 0;
+  final int _index;
+  Thing() : _index = ++_counter;
+
+  @override
+  bool operator ==(Object other) => other is Thing && _index == other._index;
+
+  @override
+  int get hashCode => _index;
+}
+
+// All the 'copy' methods use [input] and [output] rather than a parameter and
+// return value to avoid the possibility of a parametric covariance type check
+// in the call sequence.
+Map<Object?, Object> input = {};
+var output;
+
+class BaselineBenchmark extends Benchmark<String> {
+  BaselineBenchmark(int length) : super('Map', 'baseline', 'Map', length);
+
+  @override
+  void copy() {
+    // Dummy 'copy' to measure overhead of benchmarking loops.
+    output = input;
+  }
+}
+
+class MapOfBenchmark<K> extends Benchmark<K> {
+  MapOfBenchmark(String sourceKind, int length)
+      : super('Map', 'of', sourceKind, length);
+
+  @override
+  void copy() {
+    output = Map<Object?, Object>.of(input);
+  }
+}
+
+class HashMapOfBenchmark<K> extends Benchmark<K> {
+  HashMapOfBenchmark(String sourceKind, int length)
+      : super('HashMap', 'of', sourceKind, length);
+
+  @override
+  void copy() {
+    output = HashMap<Object?, Object>.of(input);
+  }
+}
+
+class MapCopyOfBenchmark<K> extends Benchmark<K> {
+  MapCopyOfBenchmark(String sourceKind, int length)
+      : super('Map', 'copyOf', sourceKind, length);
+
+  @override
+  void copy() {
+    final map = <Object?, Object>{};
+    input.forEach((k, v) {
+      map[k] = v;
+    });
+    output = map;
+  }
+}
+
+class HashMapCopyOfBenchmark<K> extends Benchmark<K> {
+  HashMapCopyOfBenchmark(String sourceKind, int length)
+      : super('HashMap', 'copyOf', sourceKind, length);
+
+  @override
+  void copy() {
+    final map = HashMap<Object?, Object>();
+    input.forEach((k, v) {
+      map[k] = v;
+    });
+    output = map;
+  }
+}
+
+class MapFromEntriesBenchmark<K> extends Benchmark<K> {
+  MapFromEntriesBenchmark(String sourceKind, int length)
+      : super('Map', 'fromEntries', sourceKind, length);
+
+  @override
+  void copy() {
+    output = Map<Object?, Object>.fromEntries(input.entries);
+  }
+}
+
+class HashMapFromEntriesBenchmark<K> extends Benchmark<K> {
+  HashMapFromEntriesBenchmark(String sourceKind, int length)
+      : super('HashMap', 'fromEntries', sourceKind, length);
+
+  @override
+  void copy() {
+    output = HashMap<Object?, Object>.fromEntries(input.entries);
+  }
+}
+
+/// Use the common methods for many different kinds of Map to make the calls in
+/// the runtime implementation polymorphic.
+void pollute() {
+  final Map<String, Object> m1 = Map.of({'hello': 66});
+  final Map<String, Object> m2 = HashMap.of(m1);
+  final Map<int, Object> m3 = Map.of({1: 66});
+  final Map<int, Object> m4 = HashMap.of({1: 66});
+  final Map<Object, Object> m5 = Map.identity()
+    ..[Thing()] = 1
+    ..[Thing()] = 2;
+  final Map<Object, Object> m6 = HashMap.identity()
+    ..[Thing()] = 1
+    ..[Thing()] = 2;
+  final Map<Object, Object> m7 = UnmodifiableMapView(m1);
+  final Map<Object, Object> m8 = UnmodifiableMapView(m2);
+  final Map<Object, Object> m9 = UnmodifiableMapView(m3);
+  final Map<Object, Object> m10 = UnmodifiableMapView(m4);
+
+  int c = 0;
+  for (final m in [m1, m2, m3, m4, m5, m6, m7, m8, m9, m10]) {
+    final Map<Object, Object> d1 = Map.of(m);
+    final Map<Object, Object> d2 = HashMap.of(m);
+    // ignore: prefer_collection_literals
+    final Map<Object, Object> d3 = Map()..addAll(m);
+    final Map<Object, Object> d4 = {...m, ...m};
+    final Map<Object, Object> d5 = HashMap()..addAll(m);
+    final Map<Object, Object> d6 = Map.identity()..addAll(m);
+    final Map<Object, Object> d7 = HashMap.identity()..addAll(m);
+    final Map<Object, Object> d8 = Map.fromEntries(m.entries);
+    final Map<Object, Object> d9 = HashMap.fromEntries(m.entries);
+    for (final z in [d1, d2, d3, d4, d5, d6, d7, d8, d9]) {
+      z.forEach((k, v) {
+        c++;
+      });
+    }
+  }
+  const totalElements = 108;
+  if (c != totalElements) throw StateError('c: $c != $totalElements');
+}
+
+/// Command-line arguments:
+///
+/// `--baseline`: Run additional benchmarks to measure the benchmarking loop
+/// component.
+///
+/// `--cross`: Run additional benchmarks for copying between Map and
+/// HashMap.
+///
+/// `--int`: Run additional benchmarks with `int` keys.
+///
+/// `--1`: Run additional benchmarks for singleton maps.
+///
+/// `--all`: Run all benchmark variants.
+void main(List<String> commandLineArguments) {
+  final arguments = [...commandLineArguments];
+
+  bool includeBaseline = false;
+  final Set<String> kinds = {'same'};
+  final Set<String> types = {'String', 'Thing'};
+  final Set<int> sizes = {2, 100};
+
+  if (arguments.remove('--reset')) {
+    kinds.clear();
+    types.clear();
+    sizes.clear();
+  }
+
+  if (arguments.remove('--baseline')) includeBaseline = true;
+  if (arguments.remove('--cross')) kinds.add('cross');
+
+  if (arguments.remove('--string')) types.add('String');
+  if (arguments.remove('--thing')) types.add('Thing');
+  if (arguments.remove('--int')) types.add('int');
+
+  if (arguments.remove('--1')) sizes.add(1);
+  if (arguments.remove('--2')) sizes.add(2);
+  if (arguments.remove('--100')) sizes.add(100);
+
+  if (arguments.remove('--all')) {
+    kinds.addAll(['baseline', 'same', 'cross']);
+    types.addAll(['String', 'Thing', 'int']);
+    sizes.addAll([1, 2, 100]);
+  }
+
+  if (arguments.isNotEmpty) {
+    throw ArgumentError('Unused command line arguments: $arguments');
+  }
+
+  if (kinds.isEmpty) kinds.add('same');
+  if (types.isEmpty) types.add('String');
+  if (sizes.isEmpty) sizes.add(2);
+
+  List<Benchmark> makeBenchmarks<K>(int length) {
+    return [
+      // Map from Map
+      if (kinds.contains('same')) ...[
+        MapOfBenchmark<K>('Map', length),
+        MapCopyOfBenchmark<K>('Map', length),
+        MapFromEntriesBenchmark<K>('Map', length),
+      ],
+      // Map from HashMap
+      if (kinds.contains('cross')) ...[
+        MapOfBenchmark<K>('HashMap', length),
+        MapCopyOfBenchmark<K>('HashMap', length),
+        MapFromEntriesBenchmark<K>('HashMap', length),
+      ],
+      // HashMap from HashMap
+      if (kinds.contains('same')) ...[
+        HashMapOfBenchmark<K>('HashMap', length),
+        HashMapCopyOfBenchmark<K>('HashMap', length),
+        HashMapFromEntriesBenchmark<K>('HashMap', length),
+      ],
+      // HashMap from Map
+      if (kinds.contains('cross')) ...[
+        HashMapOfBenchmark<K>('Map', length),
+        HashMapCopyOfBenchmark<K>('Map', length),
+        HashMapFromEntriesBenchmark<K>('Map', length),
+      ],
+    ];
+  }
+
+  List<Benchmark> makeBenchmarksForLength(int length) {
+    return [
+      if (includeBaseline) BaselineBenchmark(length),
+      if (types.contains('String')) ...makeBenchmarks<String>(length),
+      if (types.contains('Thing')) ...makeBenchmarks<Thing>(length),
+      if (types.contains('int')) ...makeBenchmarks<int>(length),
+    ];
+  }
+
+  final benchmarks = [
+    for (final length in sizes) ...makeBenchmarksForLength(length),
+  ];
+
+  // Warmup all benchmarks to ensure JIT compilers see full polymorphism.
+  for (var benchmark in benchmarks) {
+    pollute();
+    benchmark.setup();
+  }
+
+  for (var benchmark in benchmarks) {
+    pollute();
+    benchmark.warmup();
+  }
+
+  for (var benchmark in benchmarks) {
+    // `report` calls `setup`, but `setup` is idempotent.
+    benchmark.report();
+  }
+}
diff --git a/benchmarks/MapCopy/dart2/MapCopy.dart b/benchmarks/MapCopy/dart2/MapCopy.dart
new file mode 100644
index 0000000..3f7c000
--- /dev/null
+++ b/benchmarks/MapCopy/dart2/MapCopy.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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=2.9
+
+import '../dart/MapCopy.dart' as benchmark;
+
+void main(List<String> arguments) {
+  benchmark.main(arguments);
+}
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index b7c18d1..733b711 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -23,7 +23,6 @@
   'dartanalyzer',
   'dartdev',
   'dartdevc',
-  'dartdoc',
   'dds',
   'frontend_server',
   'gen_kernel',
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index a4614c2..b38dc18 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -258,6 +258,12 @@
       } else if (current_cpu == "arm64") {
         cflags += [ "--target=aarch64-linux-gnu" ]
         ldflags += [ "--target=aarch64-linux-gnu" ]
+      } else if (current_cpu == "riscv32") {
+        cflags += [ "--target=riscv32-linux-gnu" ]
+        ldflags += [ "--target=riscv32-linux-gnu" ]
+      } else if (current_cpu == "riscv64") {
+        cflags += [ "--target=riscv64-linux-gnu" ]
+        ldflags += [ "--target=riscv64-linux-gnu" ]
       } else if (current_cpu == "x86") {
         cflags += [ "--target=i386-linux-gnu" ]
         ldflags += [ "--target=i386-linux-gnu" ]
@@ -554,7 +560,7 @@
   if (is_clang) {
     default_warning_flags += [
       "-Wno-tautological-constant-compare",
-      "-Wno-unused-but-set-variable", # icu
+      "-Wno-unused-but-set-variable",  # icu
     ]
   } else {
     default_warning_flags +=
@@ -700,6 +706,7 @@
   common_optimize_on_ldflags = [
     # Linker GC.
     "/OPT:REF",
+
     # Identical code folding to reduce size.
     # Warning: This changes C/C++ semantics of function pointer comparison.
     "/OPT:ICF",
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index 4692784..5f9bc32 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -156,3 +156,75 @@
   toolchain_os = "linux"
   is_clang = false
 }
+
+gcc_toolchain("riscv32") {
+  prefix = "riscv32-linux-gnu-"
+  if (toolchain_prefix != "") {
+    prefix = toolchain_prefix
+  }
+
+  cc = "${compiler_prefix}${prefix}gcc"
+  cxx = "${compiler_prefix}${prefix}g++"
+
+  ar = "${prefix}ar"
+  ld = cxx
+  readelf = "${prefix}readelf"
+  nm = "${prefix}nm"
+  strip = "${prefix}strip"
+
+  toolchain_cpu = "riscv32"
+  toolchain_os = "linux"
+  is_clang = false
+}
+
+gcc_toolchain("clang_riscv32") {
+  prefix = rebase_path("//buildtools/linux-x64/clang/bin", root_build_dir)
+  cc = "${compiler_prefix}${prefix}/clang"
+  cxx = "${compiler_prefix}${prefix}/clang++"
+
+  readelf = "readelf"
+  nm = "${prefix}/llvm-nm"
+  ar = "${prefix}/llvm-ar"
+  ld = cxx
+  llvm_objcopy = "${prefix}/llvm-objcopy"
+
+  toolchain_cpu = "riscv32"
+  toolchain_os = "linux"
+  is_clang = true
+}
+
+gcc_toolchain("riscv64") {
+  prefix = "riscv64-linux-gnu-"
+  if (toolchain_prefix != "") {
+    prefix = toolchain_prefix
+  }
+
+  cc = "${compiler_prefix}${prefix}gcc"
+  cxx = "${compiler_prefix}${prefix}g++"
+
+  ar = "${prefix}ar"
+  ld = cxx
+  readelf = "${prefix}readelf"
+  nm = "${prefix}nm"
+  strip = "${prefix}strip"
+
+  toolchain_cpu = "riscv64"
+  toolchain_os = "linux"
+  is_clang = false
+}
+
+gcc_toolchain("clang_riscv64") {
+  prefix = rebase_path("//buildtools/linux-x64/clang/bin", root_build_dir)
+  cc = "${compiler_prefix}${prefix}/clang"
+  cxx = "${compiler_prefix}${prefix}/clang++"
+
+  readelf = "readelf"
+  nm = "${prefix}/llvm-nm"
+  ar = "${prefix}/llvm-ar"
+  ld = cxx
+  llvm_objcopy = "${prefix}/llvm-objcopy"
+
+  toolchain_cpu = "riscv64"
+  toolchain_os = "linux"
+  is_clang = true
+}
diff --git a/compile_output.txt b/compile_output.txt
new file mode 100644
index 0000000..c3420dd
--- /dev/null
+++ b/compile_output.txt
@@ -0,0 +1,8 @@
+Info: The --categories flag is deprecated, see the usage for details.
+Info: Compiling with sound null safety
+Error: Error when reading 'benchmarks-internal/DeltaBlueBase/dart2/deltablue.dart': Error reading 'benchmarks-internal/DeltaBlueBase/dart2/deltablue.dart'  (No such file or directory)
+Error: No 'main' method found.
+Error: Compilation failed.
+real 1.14
+user 0.59
+sys 0.84
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 55b94a9..9a0d773 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -44,6 +44,9 @@
   final Set<AssignedVariablesNodeInfo<Variable>> _deferredInfos =
       new Set<AssignedVariablesNodeInfo<Variable>>.identity();
 
+  /// Keeps track of whether [finish] has been called.
+  bool _isFinished = false;
+
   /// This method should be called during pre-traversal, to mark the start of a
   /// loop statement, switch statement, try statement, loop collection element,
   /// local function, closure, or late variable initializer which might need to
@@ -56,6 +59,7 @@
   /// statement, the body of the switch statement should be covered, but the
   /// switch expression should not.
   void beginNode() {
+    assert(!_isFinished);
     _stack.add(new AssignedVariablesNodeInfo<Variable>());
   }
 
@@ -65,7 +69,9 @@
   /// It is not required for the declaration to be seen prior to its use (this
   /// is to allow for error recovery in the analyzer).
   void declare(Variable variable) {
+    assert(!_isFinished);
     _stack.last._declared.add(variable);
+    _anywhere._declared.add(variable);
   }
 
   /// This method may be called during pre-traversal, to mark the end of a
@@ -83,6 +89,7 @@
   /// See [beginNode] for more details.
   AssignedVariablesNodeInfo<Variable> deferNode(
       {bool isClosureOrLateVariableInitializer: false}) {
+    assert(!_isFinished);
     AssignedVariablesNodeInfo<Variable> info = _stack.removeLast();
     info._read.removeAll(info._declared);
     info._written.removeAll(info._declared);
@@ -116,6 +123,7 @@
   /// needed, use [discardNode] to discard the effects of one of the [beginNode]
   /// calls.
   void discardNode() {
+    assert(!_isFinished);
     AssignedVariablesNodeInfo<Variable> discarded = _stack.removeLast();
     AssignedVariablesNodeInfo<Variable> last = _stack.last;
     last._declared.addAll(discarded._declared);
@@ -138,6 +146,7 @@
   ///
   /// See [beginNode] for more details.
   void endNode(Node node, {bool isClosureOrLateVariableInitializer: false}) {
+    assert(!_isFinished);
     storeInfo(
         node,
         deferNode(
@@ -148,6 +157,7 @@
   /// Call this after visiting the code to be analyzed, to check invariants.
   void finish() {
     assert(() {
+      assert(!_isFinished);
       assert(
           _deferredInfos.isEmpty, "Deferred infos not stored: $_deferredInfos");
       assert(_stack.length == 1, "Unexpected stack: $_stack");
@@ -164,6 +174,7 @@
           'Variables captured but not declared: $undeclaredCaptures');
       return true;
     }());
+    _isFinished = true;
   }
 
   /// Call this method between calls to [beginNode] and [endNode]/[deferNode],
@@ -174,15 +185,18 @@
   /// and sets; their initializers are partially built after building their
   /// loop conditions but before completely building their bodies.
   AssignedVariablesNodeInfo<Variable> popNode() {
+    assert(!_isFinished);
     return _stack.removeLast();
   }
 
   /// Call this method to un-do the effect of [popNode].
   void pushNode(AssignedVariablesNodeInfo<Variable> node) {
+    assert(!_isFinished);
     _stack.add(node);
   }
 
   void read(Variable variable) {
+    assert(!_isFinished);
     _stack.last._read.add(variable);
     _anywhere._read.add(variable);
   }
@@ -205,6 +219,7 @@
   /// This method may be called at any time between a call to [deferNode] and
   /// the call to [finish], to store assigned variable info for the node.
   void storeInfo(Node node, AssignedVariablesNodeInfo<Variable> info) {
+    assert(!_isFinished);
     // Caller should not try to store the same piece of info more than once.
     assert(_deferredInfos.remove(info));
     _info[node] = info;
@@ -221,6 +236,7 @@
   /// This method should be called during pre-traversal, to mark a write to a
   /// variable.
   void write(Variable variable) {
+    assert(!_isFinished);
     _stack.last._written.add(variable);
     _anywhere._written.add(variable);
   }
@@ -1722,7 +1738,8 @@
     Map<Variable?, VariableModel<Variable, Type>>? newVariableInfo;
 
     for (Variable variable in writtenVariables) {
-      VariableModel<Variable, Type> info = infoFor(variable);
+      VariableModel<Variable, Type>? info = variableInfo[variable];
+      if (info == null) continue;
       VariableModel<Variable, Type> newInfo =
           info.discardPromotionsAndMarkNotUnassigned();
       if (!identical(info, newInfo)) {
@@ -1734,16 +1751,8 @@
 
     for (Variable variable in capturedVariables) {
       VariableModel<Variable, Type>? info = variableInfo[variable];
-      if (info == null) {
-        (newVariableInfo ??=
-            new Map<Variable?, VariableModel<Variable, Type>>.of(
-                variableInfo))[variable] = new VariableModel<Variable, Type>(
-            promotedTypes: null,
-            tested: const [],
-            assigned: false,
-            unassigned: false,
-            ssaNode: null);
-      } else if (!info.writeCaptured) {
+      if (info == null) continue;
+      if (!info.writeCaptured) {
         (newVariableInfo ??=
             new Map<Variable?, VariableModel<Variable, Type>>.of(
                 variableInfo))[variable] = info.writeCapture();
@@ -3468,7 +3477,20 @@
   final bool respectImplicitlyTypedVarInitializers;
 
   _FlowAnalysisImpl(this.typeOperations, this._assignedVariables,
-      {required this.respectImplicitlyTypedVarInitializers});
+      {required this.respectImplicitlyTypedVarInitializers}) {
+    if (!_assignedVariables._isFinished) {
+      _assignedVariables.finish();
+    }
+    AssignedVariablesNodeInfo<Variable> anywhere = _assignedVariables._anywhere;
+    Set<Variable> implicitlyDeclaredVars = {
+      ...anywhere._read,
+      ...anywhere._written
+    };
+    implicitlyDeclaredVars.removeAll(anywhere._declared);
+    for (Variable variable in implicitlyDeclaredVars) {
+      declare(variable, true);
+    }
+  }
 
   @override
   bool get isReachable => _current.reachable.overallReachable;
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
index 74bf73c..f10269c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -15,10 +15,8 @@
   void declareType(DeclarationCode typeDeclaration);
 }
 
-/// The interface to resolve a [TypeAnnotation] to a [StaticType].
-///
-/// The [StaticType]s can be compared against other [StaticType]s to see how
-/// they relate to each other.
+/// The interface used to create [StaticType] instances, which are used to
+/// examine type relationships.
 ///
 /// This api is only available to the declaration and definition phases of
 /// macro expansion.
@@ -30,7 +28,14 @@
   /// may be asked to run in this state during the development cycle. It is
   /// helpful for users if macros provide a best effort implementation in that
   /// case or handle the error in a useful way.
-  Future<StaticType> resolve(TypeAnnotation typeAnnotation);
+  Future<StaticType> instantiateType(covariant TypeAnnotation typeAnnotation);
+
+  /// Instantiates a new [StaticType] for a given [code] expression, which must
+  /// be a type expression.
+  ///
+  /// All type identifiers in [code] must be instances of [Identifier] and not
+  /// bare strings.
+  Future<StaticType> instantiateCode(ExpressionCode code);
 }
 
 /// The api used to introspect on a [ClassDeclaration].
@@ -44,28 +49,29 @@
   ///
   /// This may be incomplete if in the declaration phase and additional macros
   /// are going to run on this class.
-  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz);
+  Future<List<FieldDeclaration>> fieldsOf(covariant ClassDeclaration clazz);
 
   /// The methods available so far for the current class.
   ///
   /// This may be incomplete if additional declaration macros are running on
   /// this class.
-  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz);
+  Future<List<MethodDeclaration>> methodsOf(covariant ClassDeclaration clazz);
 
   /// The constructors available so far for the current class.
   ///
   /// This may be incomplete if additional declaration macros are running on
   /// this class.
-  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz);
+  Future<List<ConstructorDeclaration>> constructorsOf(
+      covariant ClassDeclaration clazz);
 
   /// The class that is directly extended via an `extends` clause.
-  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz);
+  Future<ClassDeclaration?> superclassOf(covariant ClassDeclaration clazz);
 
   /// All of the classes that are mixed in with `with` clauses.
-  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz);
+  Future<List<ClassDeclaration>> mixinsOf(covariant ClassDeclaration clazz);
 
   /// All of the classes that are implemented with an `implements` clause.
-  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz);
+  Future<List<ClassDeclaration>> interfacesOf(covariant ClassDeclaration clazz);
 }
 
 /// The api used by [Macro]s to contribute new (non-type)
@@ -86,18 +92,16 @@
   void declareInClass(DeclarationCode declaration);
 }
 
-/// The api used by [Macro]s to reflect on the currently available
-/// members, superclass, and mixins for a given [ClassDeclaration]
-abstract class ClassDeclarationBuilder
-    implements ClassMemberDeclarationBuilder, ClassIntrospector {}
-
-/// The interface used by [Macro]s to resolve any [NamedStaticType] to its
-/// declaration.
+/// The interface used by [Macro]s to resolve any [Identifier]s pointing to
+/// types to their type declarations.
 ///
 /// Only available in the definition phase of macro expansion.
 abstract class TypeDeclarationResolver {
-  /// Resolves a [NamedStaticType] to its [TypeDeclaration].
-  Future<TypeDeclaration> declarationOf(NamedStaticType annotation);
+  /// Resolves an [identifier] to its [TypeDeclaration].
+  ///
+  /// If [identifier] does resolve to a [TypeDeclaration], then an
+  /// [ArgumentError] is thrown.
+  Future<TypeDeclaration> declarationOf(covariant Identifier identifier);
 }
 
 /// The base class for builders in the definition phase. These can convert
@@ -113,26 +117,32 @@
 /// The apis used by [Macro]s that run on classes, to fill in the definitions
 /// of any external declarations within that class.
 abstract class ClassDefinitionBuilder implements DefinitionBuilder {
-  /// Retrieve a [VariableDefinitionBuilder] for a field by [name].
+  /// Retrieve a [VariableDefinitionBuilder] for a field by [identifier].
   ///
-  /// Throws an [ArgumentError] if there is no field by that name.
-  VariableDefinitionBuilder buildField(String name);
+  /// Throws an [ArgumentError] if [identifier] does not refer to a field in
+  /// this class.
+  Future<VariableDefinitionBuilder> buildField(Identifier identifier);
 
-  /// Retrieve a [FunctionDefinitionBuilder] for a method by [name].
+  /// Retrieve a [FunctionDefinitionBuilder] for a method by [identifier].
   ///
-  /// Throws an [ArgumentError] if there is no method by that name.
-  FunctionDefinitionBuilder buildMethod(String name);
+  /// Throws an [ArgumentError] if [identifier] does not refer to a method in
+  /// this class.
+  Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier);
 
-  /// Retrieve a [ConstructorDefinitionBuilder] for a constructor by [name].
+  /// Retrieve a [ConstructorDefinitionBuilder] for a constructor by
+  /// [identifier].
   ///
-  /// Throws an [ArgumentError] if there is no constructor by that name.
-  ConstructorDefinitionBuilder buildConstructor(String name);
+  /// Throws an [ArgumentError] if [identifier] does not refer to a constructor
+  /// in this class.
+  Future<ConstructorDefinitionBuilder> buildConstructor(Identifier identifier);
 }
 
 /// The apis used by [Macro]s to define the body of a constructor
 /// or wrap the body of an existing constructor with additional statements.
 abstract class ConstructorDefinitionBuilder implements DefinitionBuilder {
-  /// Augments an existing constructor body with [body].
+  /// Augments an existing constructor body with [body] and [initializers].
+  ///
+  /// The [initializers] should not contain trailing or preceding commas.
   ///
   /// TODO: Link the library augmentations proposal to describe the semantics.
   void augment({FunctionBodyCode? body, List<Code>? initializers});
@@ -150,6 +160,9 @@
 abstract class VariableDefinitionBuilder implements DefinitionBuilder {
   /// Augments the field.
   ///
+  /// For [getter] and [setter] the full function declaration should be
+  /// provided, minus the `augment` keyword (which will be implicitly added).
+  ///
   /// TODO: Link the library augmentations proposal to describe the semantics.
   void augment({
     DeclarationCode? getter,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
index 89f169f..e7af1bd 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
@@ -7,17 +7,26 @@
 /// The base class representing an arbitrary chunk of Dart code, which may or
 /// may not be syntactically or semantically valid yet.
 class Code {
-  /// All the chunks of [Code] or raw [String]s that comprise this [Code]
-  /// object.
+  /// All the chunks of [Code], raw [String]s, or [Identifier]s that
+  /// comprise this [Code] object.
   final List<Object> parts;
 
+  /// Can be used to more efficiently detect the kind of code, avoiding is
+  /// checks and enabling switch statements.
+  CodeKind get kind => CodeKind.raw;
+
   Code.fromString(String code) : parts = [code];
 
-  Code.fromParts(this.parts);
+  Code.fromParts(this.parts)
+      : assert(parts.every((element) =>
+            element is String || element is Code || element is Identifier));
 }
 
 /// A piece of code representing a syntactically valid declaration.
 class DeclarationCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.declaration;
+
   DeclarationCode.fromString(String code) : super.fromString(code);
 
   DeclarationCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -27,6 +36,9 @@
 ///
 /// Should not include any trailing commas,
 class ElementCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.element;
+
   ElementCode.fromString(String code) : super.fromString(code);
 
   ElementCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -34,6 +46,9 @@
 
 /// A piece of code representing a syntactically valid expression.
 class ExpressionCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.expression;
+
   ExpressionCode.fromString(String code) : super.fromString(code);
 
   ExpressionCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -46,22 +61,21 @@
 ///
 /// Both arrow and block function bodies are allowed.
 class FunctionBodyCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.functionBody;
+
   FunctionBodyCode.fromString(String code) : super.fromString(code);
 
   FunctionBodyCode.fromParts(List<Object> parts) : super.fromParts(parts);
 }
 
-/// A piece of code representing a syntactically valid identifier.
-class IdentifierCode extends Code {
-  IdentifierCode.fromString(String code) : super.fromString(code);
-
-  IdentifierCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
 /// A piece of code identifying a named argument.
 ///
 /// This should not include any trailing commas.
 class NamedArgumentCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.namedArgument;
+
   NamedArgumentCode.fromString(String code) : super.fromString(code);
 
   NamedArgumentCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -77,6 +91,9 @@
 /// construct and combine these together in a way that creates valid parameter
 /// lists.
 class ParameterCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.parameter;
+
   ParameterCode.fromString(String code) : super.fromString(code);
 
   ParameterCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -86,6 +103,9 @@
 ///
 /// Should always end with a semicolon.
 class StatementCode extends Code {
+  @override
+  CodeKind get kind => CodeKind.statement;
+
   StatementCode.fromString(String code) : super.fromString(code);
 
   StatementCode.fromParts(List<Object> parts) : super.fromParts(parts);
@@ -102,3 +122,14 @@
         last,
       ];
 }
+
+enum CodeKind {
+  raw,
+  declaration,
+  element,
+  expression,
+  functionBody,
+  namedArgument,
+  parameter,
+  statement,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
index e892296..11fd6c3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -4,6 +4,18 @@
 
 part of '../api.dart';
 
+/// A concrete reference to a named declaration, which may or may not yet be
+/// resolved.
+///
+/// These can be passed directly to [Code] objects, which will automatically do
+/// any necessary prefixing when emitting references.
+///
+/// Concrete implementations should override `==` so that identifiers can be
+/// reliably compared against each other.
+abstract class Identifier {
+  String get name;
+}
+
 /// The base class for an unresolved reference to a type.
 ///
 /// See the subtypes [FunctionTypeAnnotation] and [NamedTypeAnnotation].
@@ -12,7 +24,9 @@
   /// trailing `?`)
   bool get isNullable;
 
-  /// A [Code] object representation of this type annotation.
+  /// A convenience method to get a [Code] object representation of this full
+  /// type annotation, including support for generic type arguments as well as
+  /// function types.
   Code get code;
 }
 
@@ -36,8 +50,8 @@
 /// These can be resolved to a [TypeDeclaration] using the `builder` classes
 /// depending on the phase a macro is running in.
 abstract class NamedTypeAnnotation implements TypeAnnotation {
-  /// The name of the type as it exists in the type annotation.
-  String get name;
+  /// An identifier pointing to this named type.
+  Identifier get identifier;
 
   /// The type arguments, if applicable.
   Iterable<TypeAnnotation> get typeArguments;
@@ -49,39 +63,34 @@
 /// compared to other static types.
 abstract class StaticType {
   /// Returns true if this is a subtype of [other].
-  Future<bool> isSubtypeOf(StaticType other);
+  Future<bool> isSubtypeOf(covariant StaticType other);
 
   /// Returns true if this is an identical type to [other].
-  Future<bool> isExactly(StaticType other);
+  Future<bool> isExactly(covariant StaticType other);
 }
 
 /// A subtype of [StaticType] representing types that can be resolved by name
 /// to a concrete declaration.
-abstract class NamedStaticType implements StaticType {
-  String get name;
-}
+abstract class NamedStaticType implements StaticType {}
 
 /// The base class for all declarations.
 abstract class Declaration {
-  /// The name of this declaration.
-  String get name;
+  ///  An identifier pointing to this named declaration.
+  Identifier get identifier;
+}
+
+/// Base class for all Declarations which have a surrounding class.
+abstract class ClassMemberDeclaration implements Declaration {
+  /// The class that defines this method.
+  Identifier get definingClass;
 }
 
 /// A declaration that defines a new type in the program.
+///
+/// See subtypes [ClassDeclaration] and [TypeAliasDeclaration].
 abstract class TypeDeclaration implements Declaration {
   /// The type parameters defined for this type declaration.
   Iterable<TypeParameterDeclaration> get typeParameters;
-
-  /// Create a static type representing this type with [typeArguments].
-  ///
-  /// If [isNullable] is `true`, then this type will behave as if it has a
-  /// trailing `?`.
-  ///
-  /// Throws an exception if the type could not be instantiated, typically due
-  /// to one of the type arguments not matching the bounds of the corresponding
-  /// type parameter.
-  Future<StaticType> instantiate(
-      {required List<StaticType> typeArguments, required bool isNullable});
 }
 
 /// Class (and enum) introspection information.
@@ -108,6 +117,12 @@
   Iterable<TypeParameterDeclaration> get typeParameters;
 }
 
+/// Type alias introspection information.
+abstract class TypeAliasDeclaration extends TypeDeclaration {
+  /// The type annotation this is an alias for.
+  TypeAnnotation get aliasedType;
+}
+
 /// Function introspection information.
 abstract class FunctionDeclaration implements Declaration {
   /// Whether this function has an `abstract` modifier.
@@ -136,10 +151,8 @@
 }
 
 /// Method introspection information.
-abstract class MethodDeclaration implements FunctionDeclaration {
-  /// The class that defines this method.
-  TypeAnnotation get definingClass;
-}
+abstract class MethodDeclaration
+    implements FunctionDeclaration, ClassMemberDeclaration {}
 
 /// Constructor introspection information.
 abstract class ConstructorDeclaration implements MethodDeclaration {
@@ -149,24 +162,26 @@
 
 /// Variable introspection information.
 abstract class VariableDeclaration implements Declaration {
-  /// Whether this function has an `abstract` modifier.
-  bool get isAbstract;
-
-  /// Whether this function has an `external` modifier.
+  /// Whether this field has an `external` modifier.
   bool get isExternal;
 
+  /// Whether this field has a `final` modifier.
+  bool get isFinal;
+
+  /// Whether this field has a `late` modifier.
+  bool get isLate;
+
   /// The type of this field.
   TypeAnnotation get type;
 
-  /// A [Code] object representing the initializer for this field, if present.
-  Code? get initializer;
+  /// A [ExpressionCode] object representing the initializer for this field, if
+  /// present.
+  ExpressionCode? get initializer;
 }
 
-/// Field introspection information ..
-abstract class FieldDeclaration implements VariableDeclaration {
-  /// The class that defines this method.
-  TypeAnnotation get definingClass;
-}
+/// Field introspection information.
+abstract class FieldDeclaration
+    implements VariableDeclaration, ClassMemberDeclaration {}
 
 /// Parameter introspection information.
 abstract class ParameterDeclaration implements Declaration {
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart
index 7685589a..5ab073a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart
@@ -50,7 +50,7 @@
 /// The interface for [Macro]s that can be applied to any top level variable
 /// or instance field, and wants to augment the variable definition.
 abstract class VariableDefinitionMacro implements Macro {
-  FutureOr<void> buildDefinitionForFunction(
+  FutureOr<void> buildDefinitionForVariable(
       VariableDeclaration variable, VariableDefinitionBuilder builder);
 }
 
@@ -65,7 +65,7 @@
 /// contribute new non-type declarations to the program.
 abstract class ClassDeclarationsMacro implements Macro {
   FutureOr<void> buildDeclarationsForClass(
-      ClassDeclaration clazz, ClassDeclarationBuilder builder);
+      ClassDeclaration clazz, ClassMemberDeclarationBuilder builder);
 }
 
 /// The interface for [Macro]s that can be applied to any class, and wants to
@@ -85,13 +85,13 @@
 /// The interface for [Macro]s that can be applied to any field, and wants to
 /// contribute new type declarations to the program.
 abstract class FieldDeclarationsMacro implements Macro {
-  FutureOr<void> buildTypesForField(
+  FutureOr<void> buildDeclarationsForField(
       FieldDeclaration field, ClassMemberDeclarationBuilder builder);
 }
 
 /// The interface for [Macro]s that can be applied to any field, and wants to
 /// augment the field definition.
-abstract class FieldDefinitionsMacro implements Macro {
+abstract class FieldDefinitionMacro implements Macro {
   FutureOr<void> buildDefinitionForField(
       FieldDeclaration field, VariableDefinitionBuilder builder);
 }
@@ -105,7 +105,7 @@
 
 /// The interface for [Macro]s that can be applied to any method, and wants to
 /// contribute new non-type declarations to the program.
-abstract class MethodDeclarationDeclarationsMacro implements Macro {
+abstract class MethodDeclarationsMacro implements Macro {
   FutureOr<void> buildDeclarationsForMethod(
       MethodDeclaration method, ClassMemberDeclarationBuilder builder);
 }
@@ -121,19 +121,20 @@
 /// to contribute new type declarations to the program.
 abstract class ConstructorTypesMacro implements Macro {
   FutureOr<void> buildTypesForConstructor(
-      ConstructorDeclaration method, TypeBuilder builder);
+      ConstructorDeclaration constructor, TypeBuilder builder);
 }
 
 /// The interface for [Macro]s that can be applied to any constructors, and
 /// wants to contribute new non-type declarations to the program.
-abstract class ConstructorDeclarationDeclarationsMacro implements Macro {
+abstract class ConstructorDeclarationsMacro implements Macro {
   FutureOr<void> buildDeclarationsForConstructor(
-      ConstructorDeclaration method, ClassMemberDeclarationBuilder builder);
+      ConstructorDeclaration constructor,
+      ClassMemberDeclarationBuilder builder);
 }
 
 /// The interface for [Macro]s that can be applied to any constructor, and wants
 /// to augment the function definition.
 abstract class ConstructorDefinitionMacro implements Macro {
   FutureOr<void> buildDefinitionForConstructor(
-      ConstructorDeclaration method, ConstructorDefinitionBuilder builder);
+      ConstructorDeclaration constructor, ConstructorDefinitionBuilder builder);
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
new file mode 100644
index 0000000..f604c80
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -0,0 +1,257 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Generates a Dart program for a given set of macros, which can be compiled
+/// and then passed as a precompiled kernel file to `MacroExecutor.loadMacro`.
+///
+/// The [macroDeclarations] is a map from library URIs to macro classes for the
+/// macros supported. The macro classes are provided as a map from macro class
+/// names to the names of the macro class constructors.
+String bootstrapMacroIsolate(
+    Map<String, Map<String, List<String>>> macroDeclarations) {
+  StringBuffer imports = new StringBuffer();
+  StringBuffer constructorEntries = new StringBuffer();
+  macroDeclarations
+      .forEach((String macroImport, Map<String, List<String>> macroClasses) {
+    imports.writeln('import \'$macroImport\';');
+    macroClasses.forEach((String macroName, List<String> constructorNames) {
+      constructorEntries
+          .writeln("MacroClassIdentifierImpl(Uri.parse('$macroImport'), "
+              "'$macroName'): {");
+      for (String constructor in constructorNames) {
+        constructorEntries.writeln("'$constructor': "
+            "$macroName.${constructor.isEmpty ? 'new' : constructor},");
+      }
+      constructorEntries.writeln('},');
+    });
+  });
+  return template.replaceFirst(_importMarker, imports.toString()).replaceFirst(
+      _macroConstructorEntriesMarker, constructorEntries.toString());
+}
+
+const String _importMarker = '{{IMPORT}}';
+const String _macroConstructorEntriesMarker = '{{MACRO_CONSTRUCTOR_ENTRIES}}';
+
+const String template = '''
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/execute_macro.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/protocol.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+$_importMarker
+
+/// Entrypoint to be spawned with [Isolate.spawnUri].
+///
+/// Supports the client side of the macro expansion protocol.
+void main(_, SendPort sendPort) {
+  /// Local function that sends requests and returns responses using [sendPort].
+  Future<Response> sendRequest(Request request) => _sendRequest(request, sendPort);
+
+  withSerializationMode(SerializationMode.client, () {
+    ReceivePort receivePort = new ReceivePort();
+    sendPort.send(receivePort.sendPort);
+
+    receivePort.listen((message) async {
+      var deserializer = JsonDeserializer(message as Iterable<Object?>)
+          ..moveNext();
+      int zoneId = deserializer.expectNum();
+      deserializer..moveNext();
+      var type = MessageType.values[deserializer.expectNum()];
+      var serializer = JsonSerializer();
+      switch (type) {
+        case MessageType.instantiateMacroRequest:
+          var request = new InstantiateMacroRequest.deserialize(deserializer, zoneId);
+          (await _instantiateMacro(request)).serialize(serializer);
+          break;
+        case MessageType.executeDeclarationsPhaseRequest:
+          var request = new ExecuteDeclarationsPhaseRequest.deserialize(deserializer, zoneId);
+          (await _executeDeclarationsPhase(request, sendRequest)).serialize(serializer);
+          break;
+        case MessageType.executeDefinitionsPhaseRequest:
+          var request = new ExecuteDefinitionsPhaseRequest.deserialize(deserializer, zoneId);
+          (await _executeDefinitionsPhase(request, sendRequest)).serialize(serializer);
+          break;
+        case MessageType.executeTypesPhaseRequest:
+          var request = new ExecuteTypesPhaseRequest.deserialize(deserializer, zoneId);
+          (await _executeTypesPhase(request, sendRequest)).serialize(serializer);
+          break;
+        case MessageType.response:
+          var response = new SerializableResponse.deserialize(deserializer, zoneId);
+          _responseCompleters.remove(response.requestId)!.complete(response);
+          return;
+        default:
+          throw new StateError('Unhandled event type \$type');
+      }
+      sendPort.send(serializer.result);
+    });
+  });
+}
+
+/// Maps macro identifiers to constructors.
+final _macroConstructors = <MacroClassIdentifierImpl, Map<String, Macro Function()>>{
+  $_macroConstructorEntriesMarker
+};
+
+/// Maps macro instance identifiers to instances.
+final _macroInstances = <MacroInstanceIdentifierImpl, Macro>{};
+
+/// Handles [InstantiateMacroRequest]s.
+Future<SerializableResponse> _instantiateMacro(
+    InstantiateMacroRequest request) async {
+  try {
+    var constructors = _macroConstructors[request.macroClass];
+    if (constructors == null) {
+      throw new ArgumentError('Unrecognized macro class \${request.macroClass}');
+    }
+    var constructor = constructors[request.constructorName];
+    if (constructor == null) {
+      throw new ArgumentError(
+          'Unrecognized constructor name "\${request.constructorName}" for '
+          'macro class "\${request.macroClass}".');
+    }
+
+    var instance = Function.apply(constructor, request.arguments.positional, {
+      for (MapEntry<String, Object?> entry in request.arguments.named.entries)
+        new Symbol(entry.key): entry.value,
+    }) as Macro;
+    var identifier = new MacroInstanceIdentifierImpl(instance);
+    _macroInstances[identifier] = instance;
+    return new SerializableResponse(
+        responseType: MessageType.macroInstanceIdentifier,
+        response: identifier,
+        requestId: request.id,
+        serializationZoneId: request.serializationZoneId);
+  } catch (e, s) {
+    return new SerializableResponse(
+      responseType: MessageType.error,
+      error: e.toString(),
+      stackTrace: s.toString(),
+      requestId: request.id,
+      serializationZoneId: request.serializationZoneId);
+  }
+}
+
+Future<SerializableResponse> _executeTypesPhase(
+    ExecuteTypesPhaseRequest request,
+    Future<Response> Function(Request request) sendRequest) async {
+  try {
+    Macro? instance = _macroInstances[request.macro];
+    if (instance == null) {
+      throw new StateError('Unrecognized macro instance \${request.macro}\\n'
+          'Known instances: \$_macroInstances)');
+    }
+
+    var result = await executeTypesMacro(instance, request.declaration);
+    return new SerializableResponse(
+        responseType: MessageType.macroExecutionResult,
+        response: result,
+        requestId: request.id,
+        serializationZoneId: request.serializationZoneId);
+  } catch (e, s) {
+    return new SerializableResponse(
+      responseType: MessageType.error,
+      error: e.toString(),
+      stackTrace: s.toString(),
+      requestId: request.id,
+      serializationZoneId: request.serializationZoneId);
+  }
+}
+
+Future<SerializableResponse> _executeDeclarationsPhase(
+    ExecuteDeclarationsPhaseRequest request,
+    Future<Response> Function(Request request) sendRequest) async {
+  try {
+    Macro? instance = _macroInstances[request.macro];
+    if (instance == null) {
+      throw new StateError('Unrecognized macro instance \${request.macro}\\n'
+          'Known instances: \$_macroInstances)');
+    }
+    var classIntrospector = ClientClassIntrospector(
+        sendRequest,
+        remoteInstance: request.classIntrospector,
+        serializationZoneId: request.serializationZoneId);
+    var typeResolver = ClientTypeResolver(
+        sendRequest,
+        remoteInstance: request.typeResolver,
+        serializationZoneId: request.serializationZoneId);
+
+    var result = await executeDeclarationsMacro(
+        instance, request.declaration, classIntrospector, typeResolver);
+    return new SerializableResponse(
+        responseType: MessageType.macroExecutionResult,
+        response: result,
+        requestId: request.id,
+        serializationZoneId: request.serializationZoneId);
+  } catch (e, s) {
+    return new SerializableResponse(
+      responseType: MessageType.error,
+      error: e.toString(),
+      stackTrace: s.toString(),
+      requestId: request.id,
+      serializationZoneId: request.serializationZoneId);
+  }
+}
+
+Future<SerializableResponse> _executeDefinitionsPhase(
+    ExecuteDefinitionsPhaseRequest request,
+    Future<Response> Function(Request request) sendRequest) async {
+  try {
+    Macro? instance = _macroInstances[request.macro];
+    if (instance == null) {
+      throw new StateError('Unrecognized macro instance \${request.macro}\\n'
+          'Known instances: \$_macroInstances)');
+    }
+    var typeResolver = ClientTypeResolver(
+        sendRequest,
+        remoteInstance: request.typeResolver,
+        serializationZoneId: request.serializationZoneId);
+    var typeDeclarationResolver = ClientTypeDeclarationResolver(
+        sendRequest,
+        remoteInstance: request.typeDeclarationResolver,
+        serializationZoneId: request.serializationZoneId);
+    var classIntrospector = ClientClassIntrospector(
+        sendRequest,
+        remoteInstance: request.classIntrospector,
+        serializationZoneId: request.serializationZoneId);
+
+    var result = await executeDefinitionMacro(
+        instance, request.declaration, classIntrospector, typeResolver,
+        typeDeclarationResolver);
+    return new SerializableResponse(
+        responseType: MessageType.macroExecutionResult,
+        response: result,
+        requestId: request.id,
+        serializationZoneId: request.serializationZoneId);
+  } catch (e, s) {
+    return new SerializableResponse(
+      responseType: MessageType.error,
+      error: e.toString(),
+      stackTrace: s.toString(),
+      requestId: request.id,
+      serializationZoneId: request.serializationZoneId);
+  }
+}
+
+/// Holds on to response completers by request id.
+final _responseCompleters = <int, Completer<Response>>{};
+
+/// Serializes [request], sends it to [sendPort], and sets up a [Completer] in
+/// [_responseCompleters] to handle the response.
+Future<Response> _sendRequest(Request request, SendPort sendPort) {
+  Completer<Response> completer = Completer();
+  _responseCompleters[request.id] = completer;
+  JsonSerializer serializer = JsonSerializer();
+  serializer.addNum(request.serializationZoneId);
+  request.serialize(serializer);
+  sendPort.send(serializer.result);
+  return completer.future;
+}
+''';
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index 0d4e878..a4c2df3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -3,6 +3,17 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'api.dart';
+import 'bootstrap.dart'; // For doc comments only.
+import 'executor_shared/serialization.dart';
+
+/// Exposes a platform specific [MacroExecutor], through a top level
+/// `Future<MacroExecutor> start()` function.
+///
+/// TODO: conditionally load isolate_mirrors_executor.dart once conditional
+/// imports of mirrors are supported in AOT (issue #48057).
+import 'fake_executor/fake_executor.dart'
+    if (dart.library.isolate) 'isolated_executor/isolated_executor.dart'
+    as executor_impl show start;
 
 /// The interface used by Dart language implementations, in order to load
 /// and execute macros, as well as produce library augmentations from those
@@ -12,6 +23,14 @@
 /// during macro discovery and expansion, and unifies how augmentation libraries
 /// are produced.
 abstract class MacroExecutor {
+  /// Returns a platform specific [MacroExecutor]. On unsupported platforms this
+  /// will be a fake executor object, which will throw an [UnsupportedError] if
+  /// used.
+  ///
+  /// Note that some implementations will also require calls to [loadMacro]
+  /// to pass a `precompiledKernelUri`.
+  static Future<MacroExecutor> start() => executor_impl.start();
+
   /// Invoked when an implementation discovers a new macro definition in a
   /// [library] with [name], and prepares this executor to run the macro.
   ///
@@ -20,8 +39,17 @@
   /// [MacroInstanceIdentifier]s given for this macro will be invalid after
   /// that point and should be discarded.
   ///
+  /// The [precompiledKernelUri] if passed must point to a kernel program for
+  /// the given macro. A bootstrap Dart program can be generated with the
+  /// [bootstrapMacroIsolate] function, and the result should be compiled to
+  /// kernel and passed here.
+  ///
+  /// Some implementations may require [precompiledKernelUri] to be passed, and
+  /// will throw an [UnsupportedError] if it is not.
+  ///
   /// Throws an exception if the macro fails to load.
-  Future<MacroClassIdentifier> loadMacro(Uri library, String name);
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+      {Uri? precompiledKernelUri});
 
   /// Creates an instance of [macroClass] in the executor, and returns an
   /// identifier for that instance.
@@ -34,14 +62,14 @@
   ///
   /// Throws an exception if there is an error executing the macro.
   Future<MacroExecutionResult> executeTypesPhase(
-      MacroInstanceIdentifier macro, Declaration declaration);
+      MacroInstanceIdentifier macro, covariant Declaration declaration);
 
   /// Runs the declarations phase for [macro] on a given [declaration].
   ///
   /// Throws an exception if there is an error executing the macro.
   Future<MacroExecutionResult> executeDeclarationsPhase(
       MacroInstanceIdentifier macro,
-      Declaration declaration,
+      covariant Declaration declaration,
       TypeResolver typeResolver,
       ClassIntrospector classIntrospector);
 
@@ -50,7 +78,7 @@
   /// Throws an exception if there is an error executing the macro.
   Future<MacroExecutionResult> executeDefinitionsPhase(
       MacroInstanceIdentifier macro,
-      Declaration declaration,
+      covariant Declaration declaration,
       TypeResolver typeResolver,
       ClassIntrospector classIntrospector,
       TypeDeclarationResolver typeDeclarationResolver);
@@ -69,31 +97,152 @@
 ///
 /// All argument instances must be of type [Code] or a built-in value type that
 /// is serializable (num, bool, String, null, etc).
-class Arguments {
+class Arguments implements Serializable {
   final List<Object?> positional;
 
   final Map<String, Object?> named;
 
   Arguments(this.positional, this.named);
+
+  factory Arguments.deserialize(Deserializer deserializer) {
+    deserializer
+      ..moveNext()
+      ..expectList();
+    List<Object?> positionalArgs = [
+      for (bool hasNext = deserializer.moveNext();
+          hasNext;
+          hasNext = deserializer.moveNext())
+        _deserializeArg(deserializer, alreadyMoved: true),
+    ];
+    deserializer
+      ..moveNext()
+      ..expectList();
+    Map<String, Object?> namedArgs = {
+      for (bool hasNext = deserializer.moveNext();
+          hasNext;
+          hasNext = deserializer.moveNext())
+        deserializer.expectString(): _deserializeArg(deserializer),
+    };
+    return new Arguments(positionalArgs, namedArgs);
+  }
+
+  static Object? _deserializeArg(Deserializer deserializer,
+      {bool alreadyMoved = false}) {
+    if (!alreadyMoved) deserializer.moveNext();
+    _ArgumentKind kind = _ArgumentKind.values[deserializer.expectNum()];
+    switch (kind) {
+      case _ArgumentKind.nil:
+        return null;
+      case _ArgumentKind.string:
+        deserializer.moveNext();
+        return deserializer.expectString();
+      case _ArgumentKind.bool:
+        deserializer.moveNext();
+        return deserializer.expectBool();
+      case _ArgumentKind.num:
+        deserializer.moveNext();
+        return deserializer.expectNum();
+      case _ArgumentKind.list:
+        deserializer.moveNext();
+        deserializer.expectList();
+        return [
+          for (bool hasNext = deserializer.moveNext();
+              hasNext;
+              hasNext = deserializer.moveNext())
+            _deserializeArg(deserializer, alreadyMoved: true),
+        ];
+      case _ArgumentKind.map:
+        deserializer.moveNext();
+        deserializer.expectList();
+        return {
+          for (bool hasNext = deserializer.moveNext();
+              hasNext;
+              hasNext = deserializer.moveNext())
+            _deserializeArg(deserializer, alreadyMoved: true):
+                _deserializeArg(deserializer),
+        };
+    }
+  }
+
+  void serialize(Serializer serializer) {
+    serializer.startList();
+    for (Object? arg in positional) {
+      _serializeArg(arg, serializer);
+    }
+    serializer.endList();
+
+    serializer.startList();
+    for (MapEntry<String, Object?> arg in named.entries) {
+      serializer.addString(arg.key);
+      _serializeArg(arg.value, serializer);
+    }
+    serializer.endList();
+  }
+
+  static void _serializeArg(Object? arg, Serializer serializer) {
+    if (arg == null) {
+      serializer.addNum(_ArgumentKind.nil.index);
+    } else if (arg is String) {
+      serializer
+        ..addNum(_ArgumentKind.string.index)
+        ..addString(arg);
+    } else if (arg is num) {
+      serializer
+        ..addNum(_ArgumentKind.num.index)
+        ..addNum(arg);
+    } else if (arg is bool) {
+      serializer
+        ..addNum(_ArgumentKind.bool.index)
+        ..addBool(arg);
+    } else if (arg is List) {
+      serializer
+        ..addNum(_ArgumentKind.list.index)
+        ..startList();
+      for (Object? item in arg) {
+        _serializeArg(item, serializer);
+      }
+      serializer.endList();
+    } else if (arg is Map) {
+      serializer
+        ..addNum(_ArgumentKind.map.index)
+        ..startList();
+      for (MapEntry<Object?, Object?> entry in arg.entries) {
+        _serializeArg(entry.key, serializer);
+        _serializeArg(entry.value, serializer);
+      }
+      serializer.endList();
+    } else {
+      throw new UnsupportedError('Unsupported argument type $arg');
+    }
+  }
 }
 
 /// An opaque identifier for a macro class, retrieved by
 /// [MacroExecutor.loadMacro].
 ///
 /// Used to execute or reload this macro in the future.
-abstract class MacroClassIdentifier {}
+abstract class MacroClassIdentifier implements Serializable {}
 
 /// An opaque identifier for an instance of a macro class, retrieved by
 /// [MacroExecutor.instantiateMacro].
 ///
 /// Used to execute or reload this macro in the future.
-abstract class MacroInstanceIdentifier {}
+abstract class MacroInstanceIdentifier implements Serializable {
+  /// Whether or not this instance should run in [phase] on [declarationKind].
+  ///
+  /// Attempting to execute a macro in a phase it doesn't support, or on a
+  /// declaration kind it doesn't support is an error.
+  bool shouldExecute(DeclarationKind declarationKind, Phase phase);
+
+  /// Whether or not this macro supports [declarationKind] in any phase.
+  bool supportsDeclarationKind(DeclarationKind declarationKind);
+}
 
 /// A summary of the results of running a macro in a given phase.
 ///
 /// All modifications are expressed in terms of library augmentation
 /// declarations.
-abstract class MacroExecutionResult {
+abstract class MacroExecutionResult implements Serializable {
   /// Any library imports that should be added to support the code used in
   /// the augmentations.
   Iterable<DeclarationCode> get imports;
@@ -102,6 +251,16 @@
   Iterable<DeclarationCode> get augmentations;
 }
 
+/// Each of the possible types of declarations a macro can be applied to
+enum DeclarationKind {
+  clazz,
+  constructor,
+  field,
+  function,
+  method,
+  variable,
+}
+
 /// Each of the different macro execution phases.
 enum Phase {
   /// Only new types are added in this phase.
@@ -113,3 +272,6 @@
   /// This phase allows augmenting existing declarations.
   definitions,
 }
+
+/// Used for serializing and deserializing arguments.
+enum _ArgumentKind { string, bool, num, list, map, nil }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
new file mode 100644
index 0000000..099c58e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
@@ -0,0 +1,378 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. 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:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+
+import '../executor.dart';
+import '../api.dart';
+import 'response_impls.dart';
+
+class TypeBuilderBase {
+  /// The final result, will be built up over `augment` calls.
+  final List<DeclarationCode> _augmentations;
+
+  /// Creates and returns a [MacroExecutionResult] out of the [_augmentations]
+  /// created by this builder.
+  MacroExecutionResult get result => new MacroExecutionResultImpl(
+        augmentations: _augmentations,
+        // TODO: Implement `imports`, or possibly drop it?
+        imports: [],
+      );
+
+  TypeBuilderBase({List<DeclarationCode>? parentAugmentations})
+      : _augmentations = parentAugmentations ?? [];
+}
+
+class TypeBuilderImpl extends TypeBuilderBase implements TypeBuilder {
+  @override
+  void declareType(DeclarationCode typeDeclaration) {
+    _augmentations.add(typeDeclaration);
+  }
+}
+
+/// Base class for all [DeclarationBuilder]s.
+class DeclarationBuilderBase extends TypeBuilderBase
+    implements ClassIntrospector, TypeResolver {
+  final ClassIntrospector classIntrospector;
+  final TypeResolver typeResolver;
+
+  DeclarationBuilderBase(this.classIntrospector, this.typeResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(parentAugmentations: parentAugmentations);
+
+  @override
+  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
+      classIntrospector.constructorsOf(clazz);
+
+  @override
+  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
+      classIntrospector.fieldsOf(clazz);
+
+  @override
+  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
+      classIntrospector.interfacesOf(clazz);
+
+  @override
+  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
+      classIntrospector.methodsOf(clazz);
+
+  @override
+  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
+      classIntrospector.mixinsOf(clazz);
+
+  @override
+  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
+      classIntrospector.superclassOf(clazz);
+
+  @override
+  Future<StaticType> instantiateCode(ExpressionCode code) =>
+      typeResolver.instantiateCode(code);
+
+  @override
+  Future<StaticType> instantiateType(TypeAnnotation typeAnnotation) =>
+      typeResolver.instantiateType(typeAnnotation);
+}
+
+class DeclarationBuilderImpl extends DeclarationBuilderBase
+    implements DeclarationBuilder {
+  DeclarationBuilderImpl(
+      ClassIntrospector classIntrospector, TypeResolver typeResolver)
+      : super(classIntrospector, typeResolver);
+
+  @override
+  void declareInLibrary(DeclarationCode declaration) {
+    _augmentations.add(declaration);
+  }
+}
+
+class ClassMemberDeclarationBuilderImpl extends DeclarationBuilderImpl
+    implements ClassMemberDeclarationBuilder {
+  final Identifier definingClass;
+
+  ClassMemberDeclarationBuilderImpl(this.definingClass,
+      ClassIntrospector classIntrospector, TypeResolver typeResolver)
+      : super(classIntrospector, typeResolver);
+
+  @override
+  void declareInClass(DeclarationCode declaration) {
+    _augmentations.add(_buildClassAugmentation(definingClass, [declaration]));
+  }
+}
+
+/// Base class for all [DefinitionBuilder]s.
+class DefinitionBuilderBase extends DeclarationBuilderBase
+    implements TypeDeclarationResolver {
+  final TypeDeclarationResolver typeDeclarationResolver;
+
+  DefinitionBuilderBase(ClassIntrospector classIntrospector,
+      TypeResolver typeResolver, this.typeDeclarationResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(classIntrospector, typeResolver,
+            parentAugmentations: parentAugmentations);
+
+  @override
+  Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) =>
+      typeDeclarationResolver.declarationOf(identifier);
+}
+
+class ClassDefinitionBuilderImpl extends DefinitionBuilderBase
+    implements ClassDefinitionBuilder {
+  /// The declaration this is a builder for.
+  final ClassDeclaration declaration;
+
+  ClassDefinitionBuilderImpl(
+      this.declaration,
+      ClassIntrospector classIntrospector,
+      TypeResolver typeResolver,
+      TypeDeclarationResolver typeDeclarationResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(classIntrospector, typeResolver, typeDeclarationResolver,
+            parentAugmentations: parentAugmentations);
+
+  @override
+  Future<ConstructorDefinitionBuilder> buildConstructor(
+      Identifier identifier) async {
+    ConstructorDeclaration constructor =
+        (await classIntrospector.constructorsOf(declaration))
+            .firstWhere((constructor) => constructor.identifier == identifier);
+    return new ConstructorDefinitionBuilderImpl(
+        constructor, classIntrospector, typeResolver, typeDeclarationResolver,
+        parentAugmentations: _augmentations);
+  }
+
+  @override
+  Future<VariableDefinitionBuilder> buildField(Identifier identifier) async {
+    FieldDeclaration field = (await classIntrospector.fieldsOf(declaration))
+        .firstWhere((field) => field.identifier == identifier);
+    return new VariableDefinitionBuilderImpl(
+        field, classIntrospector, typeResolver, typeDeclarationResolver,
+        parentAugmentations: _augmentations);
+  }
+
+  @override
+  Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier) async {
+    MethodDeclaration method = (await classIntrospector.methodsOf(declaration))
+        .firstWhere((method) => method.identifier == identifier);
+    return new FunctionDefinitionBuilderImpl(
+        method, classIntrospector, typeResolver, typeDeclarationResolver,
+        parentAugmentations: _augmentations);
+  }
+}
+
+/// Implementation of [FunctionDefinitionBuilder].
+class FunctionDefinitionBuilderImpl extends DefinitionBuilderBase
+    implements FunctionDefinitionBuilder {
+  final FunctionDeclaration declaration;
+
+  FunctionDefinitionBuilderImpl(
+      this.declaration,
+      ClassIntrospector classIntrospector,
+      TypeResolver typeResolver,
+      TypeDeclarationResolver typeDeclarationResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(classIntrospector, typeResolver, typeDeclarationResolver,
+            parentAugmentations: parentAugmentations);
+
+  @override
+  void augment(FunctionBodyCode body) {
+    DeclarationCode augmentation =
+        _buildFunctionAugmentation(body, declaration);
+    if (declaration is ClassMemberDeclaration) {
+      augmentation = _buildClassAugmentation(
+          (declaration as ClassMemberDeclaration).definingClass,
+          [augmentation]);
+    }
+    _augmentations.add(augmentation);
+  }
+}
+
+class ConstructorDefinitionBuilderImpl extends DefinitionBuilderBase
+    implements ConstructorDefinitionBuilder {
+  final ConstructorDeclaration declaration;
+
+  ConstructorDefinitionBuilderImpl(
+      this.declaration,
+      ClassIntrospector classIntrospector,
+      TypeResolver typeResolver,
+      TypeDeclarationResolver typeDeclarationResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(classIntrospector, typeResolver, typeDeclarationResolver,
+            parentAugmentations: parentAugmentations);
+
+  @override
+  void augment({FunctionBodyCode? body, List<Code>? initializers}) {
+    body ??= new FunctionBodyCode.fromString('''{
+      augment super();
+    }''');
+    _augmentations.add(_buildClassAugmentation(declaration.definingClass, [
+      _buildFunctionAugmentation(body, declaration, initializers: initializers)
+    ]));
+  }
+}
+
+class VariableDefinitionBuilderImpl extends DefinitionBuilderBase
+    implements VariableDefinitionBuilder {
+  final VariableDeclaration declaration;
+
+  VariableDefinitionBuilderImpl(
+      this.declaration,
+      ClassIntrospector classIntrospector,
+      TypeResolver typeResolver,
+      TypeDeclarationResolver typeDeclarationResolver,
+      {List<DeclarationCode>? parentAugmentations})
+      : super(classIntrospector, typeResolver, typeDeclarationResolver,
+            parentAugmentations: parentAugmentations);
+
+  @override
+  void augment(
+      {DeclarationCode? getter,
+      DeclarationCode? setter,
+      ExpressionCode? initializer}) {
+    List<DeclarationCode> augmentations = _buildVariableAugmentations(
+        declaration,
+        getter: getter,
+        setter: setter,
+        initializer: initializer);
+    if (declaration is ClassMemberDeclaration) {
+      augmentations = [
+        _buildClassAugmentation(
+            (declaration as ClassMemberDeclaration).definingClass,
+            augmentations)
+      ];
+    }
+
+    _augmentations.addAll(augmentations);
+  }
+}
+
+/// Creates an augmentation of [clazz] with member [augmentations].
+DeclarationCode _buildClassAugmentation(
+        Identifier clazz, List<DeclarationCode> augmentations) =>
+    new DeclarationCode.fromParts([
+      'augment class ',
+      clazz,
+      ' {\n',
+      ...augmentations.joinAsCode('\n'),
+      '\n}',
+    ]);
+
+/// Builds all the possible augmentations for a variable.
+List<DeclarationCode> _buildVariableAugmentations(
+    VariableDeclaration declaration,
+    {DeclarationCode? getter,
+    DeclarationCode? setter,
+    ExpressionCode? initializer}) {
+  List<DeclarationCode> augmentations = [];
+  if (getter != null) {
+    augmentations.add(new DeclarationCode.fromParts([
+      'augment ',
+      getter,
+    ]));
+  }
+  if (setter != null) {
+    augmentations.add(new DeclarationCode.fromParts([
+      'augment ',
+      setter,
+    ]));
+  }
+  if (initializer != null) {
+    augmentations.add(new DeclarationCode.fromParts([
+      'augment ',
+      if (declaration.isFinal) 'final ',
+      declaration.type.code,
+      ' ',
+      declaration.identifier,
+      ' = ',
+      initializer,
+      ';',
+    ]));
+  }
+
+  return augmentations;
+}
+
+/// Builds the code to augment a function, method, or constructor with a new
+/// body.
+///
+/// The [initializers] parameter can only be used if [declaration] is a
+/// constructor.
+DeclarationCode _buildFunctionAugmentation(
+    FunctionBodyCode body, FunctionDeclaration declaration,
+    {List<Code>? initializers}) {
+  assert(initializers == null || declaration is ConstructorDeclaration);
+
+  return new DeclarationCode.fromParts([
+    'augment ',
+    if (declaration is ConstructorDeclaration) ...[
+      declaration.definingClass,
+      if (declaration.identifier.name.isNotEmpty) '.',
+    ] else ...[
+      declaration.returnType.code,
+      ' ',
+    ],
+    declaration.identifier,
+    if (declaration.typeParameters.isNotEmpty) ...[
+      '<',
+      for (TypeParameterDeclaration typeParam
+          in declaration.typeParameters) ...[
+        typeParam.identifier,
+        if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
+        if (typeParam != declaration.typeParameters.last) ', ',
+      ],
+      '>',
+    ],
+    '(',
+    for (ParameterDeclaration positionalRequired
+        in declaration.positionalParameters.where((p) => p.isRequired)) ...[
+      new ParameterCode.fromParts([
+        positionalRequired.type.code,
+        ' ',
+        positionalRequired.identifier,
+      ]),
+      ', '
+    ],
+    if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
+      '[',
+      for (ParameterDeclaration positionalOptional
+          in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
+        new ParameterCode.fromParts([
+          positionalOptional.type.code,
+          ' ',
+          positionalOptional.identifier,
+        ]),
+        ', ',
+      ],
+      ']',
+    ],
+    if (declaration.namedParameters.isNotEmpty) ...[
+      '{',
+      for (ParameterDeclaration named in declaration.namedParameters) ...[
+        new ParameterCode.fromParts([
+          if (named.isRequired) 'required ',
+          named.type.code,
+          ' ',
+          named.identifier,
+          if (named.defaultValue != null) ...[
+            ' = ',
+            named.defaultValue!,
+          ],
+        ]),
+        ', ',
+      ],
+      '}',
+    ],
+    ') ',
+    if (initializers != null && initializers.isNotEmpty) ...[
+      ' : ',
+      initializers.first,
+      for (Code initializer in initializers.skip(1)) ...[
+        ',\n',
+        initializer,
+      ],
+    ],
+    body,
+  ]);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart
new file mode 100644
index 0000000..7488445
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/execute_macro.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/builder_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+/// Runs [macro] in the types phase and returns a  [MacroExecutionResult].
+Future<MacroExecutionResult> executeTypesMacro(
+    Macro macro, Declaration declaration) async {
+  TypeBuilderImpl builder = new TypeBuilderImpl();
+  if (declaration is FunctionDeclaration) {
+    if (macro is ConstructorTypesMacro &&
+        declaration is ConstructorDeclaration) {
+      await macro.buildTypesForConstructor(declaration, builder);
+      return builder.result;
+    } else if (macro is MethodTypesMacro && declaration is MethodDeclaration) {
+      await macro.buildTypesForMethod(declaration, builder);
+      return builder.result;
+    } else if (macro is FunctionTypesMacro) {
+      await macro.buildTypesForFunction(declaration, builder);
+      return builder.result;
+    }
+  } else if (declaration is VariableDeclaration) {
+    if (macro is FieldTypesMacro && declaration is FieldDeclaration) {
+      await macro.buildTypesForField(declaration, builder);
+      return builder.result;
+    } else if (macro is VariableTypesMacro) {
+      await macro.buildTypesForVariable(declaration, builder);
+      return builder.result;
+    }
+  } else if (macro is ClassTypesMacro && declaration is ClassDeclaration) {
+    await macro.buildTypesForClass(declaration, builder);
+    return builder.result;
+  }
+  throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+      'macro: $macro\ndeclaration: $declaration');
+}
+
+/// Runs [macro] in the declaration phase and returns a  [MacroExecutionResult].
+Future<MacroExecutionResult> executeDeclarationsMacro(
+    Macro macro,
+    Declaration declaration,
+    ClassIntrospector classIntrospector,
+    TypeResolver typeResolver) async {
+  if (declaration is ClassDeclaration && macro is ClassDeclarationsMacro) {
+    ClassMemberDeclarationBuilderImpl builder =
+        new ClassMemberDeclarationBuilderImpl(
+            declaration.identifier, classIntrospector, typeResolver);
+    await macro.buildDeclarationsForClass(declaration, builder);
+    return builder.result;
+  } else if (declaration is ClassMemberDeclaration) {
+    ClassMemberDeclarationBuilderImpl builder =
+        new ClassMemberDeclarationBuilderImpl(
+            declaration.definingClass, classIntrospector, typeResolver);
+    if (declaration is FunctionDeclaration) {
+      if (macro is ConstructorDeclarationsMacro &&
+          declaration is ConstructorDeclaration) {
+        await macro.buildDeclarationsForConstructor(declaration, builder);
+        return builder.result;
+      } else if (macro is MethodDeclarationsMacro &&
+          declaration is MethodDeclaration) {
+        await macro.buildDeclarationsForMethod(declaration, builder);
+        return builder.result;
+      } else if (macro is FunctionDeclarationsMacro) {
+        await macro.buildDeclarationsForFunction(
+            declaration as FunctionDeclaration, builder);
+        return builder.result;
+      }
+    } else if (declaration is VariableDeclaration) {
+      if (macro is FieldDeclarationsMacro && declaration is FieldDeclaration) {
+        await macro.buildDeclarationsForField(declaration, builder);
+        return builder.result;
+      } else if (macro is VariableDeclarationsMacro) {
+        DeclarationBuilderImpl builder =
+            new DeclarationBuilderImpl(classIntrospector, typeResolver);
+        await macro.buildDeclarationsForVariable(
+            declaration as VariableDeclaration, builder);
+        return builder.result;
+      }
+    }
+  } else {
+    DeclarationBuilderImpl builder =
+        new DeclarationBuilderImpl(classIntrospector, typeResolver);
+    if (declaration is FunctionDeclaration &&
+        macro is FunctionDeclarationsMacro) {
+      await macro.buildDeclarationsForFunction(declaration, builder);
+      return builder.result;
+    } else if (macro is VariableDeclarationsMacro &&
+        declaration is VariableDeclaration) {
+      await macro.buildDeclarationsForVariable(declaration, builder);
+      return builder.result;
+    }
+  }
+  throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+      'macro: $macro\ndeclaration: $declaration');
+}
+
+/// Runs [macro] in the definition phase and returns a  [MacroExecutionResult].
+Future<MacroExecutionResult> executeDefinitionMacro(
+    Macro macro,
+    Declaration declaration,
+    ClassIntrospector classIntrospector,
+    TypeResolver typeResolver,
+    TypeDeclarationResolver typeDeclarationResolver) async {
+  if (declaration is FunctionDeclaration) {
+    if (macro is ConstructorDefinitionMacro &&
+        declaration is ConstructorDeclaration) {
+      ConstructorDefinitionBuilderImpl builder =
+          new ConstructorDefinitionBuilderImpl(declaration, classIntrospector,
+              typeResolver, typeDeclarationResolver);
+      await macro.buildDefinitionForConstructor(declaration, builder);
+      return builder.result;
+    } else {
+      FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
+          declaration,
+          classIntrospector,
+          typeResolver,
+          typeDeclarationResolver);
+      if (macro is MethodDefinitionMacro && declaration is MethodDeclaration) {
+        await macro.buildDefinitionForMethod(declaration, builder);
+        return builder.result;
+      } else if (macro is FunctionDefinitionMacro) {
+        await macro.buildDefinitionForFunction(declaration, builder);
+        return builder.result;
+      }
+    }
+  } else if (declaration is VariableDeclaration) {
+    VariableDefinitionBuilderImpl builder = new VariableDefinitionBuilderImpl(
+        declaration, classIntrospector, typeResolver, typeDeclarationResolver);
+    if (macro is FieldDefinitionMacro && declaration is FieldDeclaration) {
+      await macro.buildDefinitionForField(declaration, builder);
+      return builder.result;
+    } else if (macro is VariableDefinitionMacro) {
+      await macro.buildDefinitionForVariable(declaration, builder);
+      return builder.result;
+    }
+  } else if (macro is ClassDefinitionMacro && declaration is ClassDeclaration) {
+    ClassDefinitionBuilderImpl builder = new ClassDefinitionBuilderImpl(
+        declaration, classIntrospector, typeResolver, typeDeclarationResolver);
+    await macro.buildDefinitionForClass(declaration, builder);
+    return builder.result;
+  }
+  throw new UnsupportedError('Unsupported macro type or invalid declaration:\n'
+      'macro: $macro\ndeclaration: $declaration');
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
new file mode 100644
index 0000000..64e5e4f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
@@ -0,0 +1,653 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'remote_instance.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+import '../api.dart';
+
+class IdentifierImpl extends RemoteInstance implements Identifier {
+  final String name;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.identifier;
+
+  IdentifierImpl({required int id, required this.name}) : super(id);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer.addString(name);
+  }
+}
+
+abstract class TypeAnnotationImpl extends RemoteInstance
+    implements TypeAnnotation {
+  final bool isNullable;
+
+  TypeAnnotationImpl({required int id, required this.isNullable}) : super(id);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer.addBool(isNullable);
+  }
+}
+
+class NamedTypeAnnotationImpl extends TypeAnnotationImpl
+    implements NamedTypeAnnotation {
+  @override
+  Code get code => new Code.fromParts([
+        identifier,
+        if (typeArguments.isNotEmpty) ...[
+          '<',
+          typeArguments.first.code,
+          for (TypeAnnotation arg in typeArguments.skip(1)) ...[', ', arg.code],
+          '>',
+        ],
+        if (isNullable) '?',
+      ]);
+
+  @override
+  final IdentifierImpl identifier;
+
+  @override
+  final List<TypeAnnotationImpl> typeArguments;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.namedTypeAnnotation;
+
+  NamedTypeAnnotationImpl({
+    required int id,
+    required bool isNullable,
+    required this.identifier,
+    required this.typeArguments,
+  }) : super(id: id, isNullable: isNullable);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    identifier.serialize(serializer);
+    serializer.startList();
+    for (TypeAnnotationImpl typeArg in typeArguments) {
+      typeArg.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
+
+class FunctionTypeAnnotationImpl extends TypeAnnotationImpl
+    implements FunctionTypeAnnotation {
+  @override
+  Code get code => new Code.fromParts([
+        returnType.code,
+        'Function',
+        if (typeParameters.isNotEmpty) ...[
+          '<',
+          typeParameters.first.identifier.name,
+          if (typeParameters.first.bounds != null) ...[
+            ' extends ',
+            typeParameters.first.bounds!.code,
+          ],
+          for (TypeParameterDeclaration arg in typeParameters.skip(1)) ...[
+            ', ',
+            arg.identifier.name,
+            if (arg.bounds != null) ...[' extends ', arg.bounds!.code],
+          ],
+          '>',
+        ],
+        '(',
+        for (ParameterDeclaration positional in positionalParameters) ...[
+          positional.type.code,
+          ' ${positional.identifier.name}',
+        ],
+        if (namedParameters.isNotEmpty) ...[
+          '{',
+          for (ParameterDeclaration named in namedParameters) ...[
+            named.type.code,
+            ' ${named.identifier.name}',
+          ],
+          '}',
+        ],
+        ')',
+        if (isNullable) '?',
+      ]);
+
+  @override
+  final List<ParameterDeclarationImpl> namedParameters;
+
+  @override
+  final List<ParameterDeclarationImpl> positionalParameters;
+
+  @override
+  final TypeAnnotationImpl returnType;
+
+  @override
+  final List<TypeParameterDeclarationImpl> typeParameters;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.functionTypeAnnotation;
+
+  FunctionTypeAnnotationImpl({
+    required int id,
+    required bool isNullable,
+    required this.namedParameters,
+    required this.positionalParameters,
+    required this.returnType,
+    required this.typeParameters,
+  }) : super(id: id, isNullable: isNullable);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    returnType.serialize(serializer);
+
+    serializer.startList();
+    for (ParameterDeclarationImpl param in positionalParameters) {
+      param.serialize(serializer);
+    }
+    serializer.endList();
+
+    serializer.startList();
+    for (ParameterDeclarationImpl param in namedParameters) {
+      param.serialize(serializer);
+    }
+    serializer.endList();
+
+    serializer.startList();
+    for (TypeParameterDeclarationImpl typeParam in typeParameters) {
+      typeParam.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
+
+abstract class DeclarationImpl extends RemoteInstance implements Declaration {
+  final IdentifierImpl identifier;
+
+  DeclarationImpl({required int id, required this.identifier}) : super(id);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    identifier.serialize(serializer);
+  }
+}
+
+class ParameterDeclarationImpl extends DeclarationImpl
+    implements ParameterDeclaration {
+  @override
+  final Code? defaultValue;
+
+  @override
+  final bool isNamed;
+
+  @override
+  final bool isRequired;
+
+  @override
+  final TypeAnnotationImpl type;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.parameterDeclaration;
+
+  ParameterDeclarationImpl({
+    required int id,
+    required IdentifierImpl identifier,
+    required this.defaultValue,
+    required this.isNamed,
+    required this.isRequired,
+    required this.type,
+  }) : super(id: id, identifier: identifier);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    if (defaultValue == null) {
+      serializer.addNull();
+    } else {
+      defaultValue!.serialize(serializer);
+    }
+    serializer.addBool(isNamed);
+    serializer.addBool(isRequired);
+    type.serialize(serializer);
+  }
+}
+
+class TypeParameterDeclarationImpl extends DeclarationImpl
+    implements TypeParameterDeclaration {
+  @override
+  final TypeAnnotationImpl? bounds;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
+
+  TypeParameterDeclarationImpl({
+    required int id,
+    required IdentifierImpl identifier,
+    required this.bounds,
+  }) : super(id: id, identifier: identifier);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    TypeAnnotationImpl? bounds = this.bounds;
+    if (bounds == null) {
+      serializer.addNull();
+    } else {
+      bounds.serialize(serializer);
+    }
+  }
+}
+
+class FunctionDeclarationImpl extends DeclarationImpl
+    implements FunctionDeclaration {
+  @override
+  final bool isAbstract;
+
+  @override
+  final bool isExternal;
+
+  @override
+  final bool isGetter;
+
+  @override
+  final bool isSetter;
+
+  @override
+  final List<ParameterDeclarationImpl> namedParameters;
+
+  @override
+  final List<ParameterDeclarationImpl> positionalParameters;
+
+  @override
+  final TypeAnnotationImpl returnType;
+
+  @override
+  final List<TypeParameterDeclarationImpl> typeParameters;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.functionDeclaration;
+
+  FunctionDeclarationImpl({
+    required int id,
+    required IdentifierImpl identifier,
+    required this.isAbstract,
+    required this.isExternal,
+    required this.isGetter,
+    required this.isSetter,
+    required this.namedParameters,
+    required this.positionalParameters,
+    required this.returnType,
+    required this.typeParameters,
+  }) : super(id: id, identifier: identifier);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer
+      ..addBool(isAbstract)
+      ..addBool(isExternal)
+      ..addBool(isGetter)
+      ..addBool(isSetter)
+      ..startList();
+    for (ParameterDeclarationImpl named in namedParameters) {
+      named.serialize(serializer);
+    }
+    serializer
+      ..endList()
+      ..startList();
+    for (ParameterDeclarationImpl positional in positionalParameters) {
+      positional.serialize(serializer);
+    }
+    serializer.endList();
+    returnType.serialize(serializer);
+    serializer.startList();
+    for (TypeParameterDeclarationImpl param in typeParameters) {
+      param.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
+
+class MethodDeclarationImpl extends FunctionDeclarationImpl
+    implements MethodDeclaration {
+  @override
+  final IdentifierImpl definingClass;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.methodDeclaration;
+
+  MethodDeclarationImpl({
+    // Declaration fields
+    required int id,
+    required IdentifierImpl identifier,
+    // Function fields
+    required bool isAbstract,
+    required bool isExternal,
+    required bool isGetter,
+    required bool isSetter,
+    required List<ParameterDeclarationImpl> namedParameters,
+    required List<ParameterDeclarationImpl> positionalParameters,
+    required TypeAnnotationImpl returnType,
+    required List<TypeParameterDeclarationImpl> typeParameters,
+    // Method fields
+    required this.definingClass,
+  }) : super(
+          id: id,
+          identifier: identifier,
+          isAbstract: isAbstract,
+          isExternal: isExternal,
+          isGetter: isGetter,
+          isSetter: isSetter,
+          namedParameters: namedParameters,
+          positionalParameters: positionalParameters,
+          returnType: returnType,
+          typeParameters: typeParameters,
+        );
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    definingClass.serialize(serializer);
+  }
+}
+
+class ConstructorDeclarationImpl extends MethodDeclarationImpl
+    implements ConstructorDeclaration {
+  @override
+  final bool isFactory;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.constructorDeclaration;
+
+  ConstructorDeclarationImpl({
+    // Declaration fields
+    required int id,
+    required IdentifierImpl identifier,
+    // Function fields
+    required bool isAbstract,
+    required bool isExternal,
+    required bool isGetter,
+    required bool isSetter,
+    required List<ParameterDeclarationImpl> namedParameters,
+    required List<ParameterDeclarationImpl> positionalParameters,
+    required TypeAnnotationImpl returnType,
+    required List<TypeParameterDeclarationImpl> typeParameters,
+    // Method fields
+    required IdentifierImpl definingClass,
+    // Constructor fields
+    required this.isFactory,
+  }) : super(
+          id: id,
+          identifier: identifier,
+          isAbstract: isAbstract,
+          isExternal: isExternal,
+          isGetter: isGetter,
+          isSetter: isSetter,
+          namedParameters: namedParameters,
+          positionalParameters: positionalParameters,
+          returnType: returnType,
+          typeParameters: typeParameters,
+          definingClass: definingClass,
+        );
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer.addBool(isFactory);
+  }
+}
+
+class VariableDeclarationImpl extends DeclarationImpl
+    implements VariableDeclaration {
+  @override
+  final ExpressionCode? initializer;
+
+  @override
+  final bool isExternal;
+
+  @override
+  final bool isFinal;
+
+  @override
+  final bool isLate;
+
+  @override
+  final TypeAnnotationImpl type;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.variableDeclaration;
+
+  VariableDeclarationImpl({
+    required int id,
+    required IdentifierImpl identifier,
+    required this.initializer,
+    required this.isExternal,
+    required this.isFinal,
+    required this.isLate,
+    required this.type,
+  }) : super(id: id, identifier: identifier);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    initializer.serializeNullable(serializer);
+    serializer
+      ..addBool(isExternal)
+      ..addBool(isFinal)
+      ..addBool(isLate);
+    type.serialize(serializer);
+  }
+}
+
+class FieldDeclarationImpl extends VariableDeclarationImpl
+    implements FieldDeclaration {
+  @override
+  final IdentifierImpl definingClass;
+
+  FieldDeclarationImpl({
+    // Declaration fields
+    required int id,
+    required IdentifierImpl identifier,
+    // Variable fields
+    required ExpressionCode? initializer,
+    required bool isExternal,
+    required bool isFinal,
+    required bool isLate,
+    required TypeAnnotationImpl type,
+    // Field fields
+    required this.definingClass,
+  }) : super(
+            id: id,
+            identifier: identifier,
+            initializer: initializer,
+            isExternal: isExternal,
+            isFinal: isFinal,
+            isLate: isLate,
+            type: type);
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.fieldDeclaration;
+
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    definingClass.serialize(serializer);
+  }
+}
+
+abstract class TypeDeclarationImpl extends DeclarationImpl
+    implements TypeDeclaration {
+  @override
+  final List<TypeParameterDeclarationImpl> typeParameters;
+
+  TypeDeclarationImpl({
+    required int id,
+    required IdentifierImpl identifier,
+    required this.typeParameters,
+  }) : super(id: id, identifier: identifier);
+
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer..startList();
+    for (TypeParameterDeclarationImpl param in typeParameters) {
+      param.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
+
+class ClassDeclarationImpl extends TypeDeclarationImpl
+    implements ClassDeclaration {
+  @override
+  final List<TypeAnnotationImpl> interfaces;
+
+  @override
+  final bool isAbstract;
+
+  @override
+  final bool isExternal;
+
+  @override
+  final List<TypeAnnotationImpl> mixins;
+
+  @override
+  final TypeAnnotationImpl? superclass;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.classDeclaration;
+
+  ClassDeclarationImpl({
+    // Declaration fields
+    required int id,
+    required IdentifierImpl identifier,
+    // TypeDeclaration fields
+    required List<TypeParameterDeclarationImpl> typeParameters,
+    // ClassDeclaration fields
+    required this.interfaces,
+    required this.isAbstract,
+    required this.isExternal,
+    required this.mixins,
+    required this.superclass,
+  }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    serializer.startList();
+    for (TypeAnnotationImpl interface in interfaces) {
+      interface.serialize(serializer);
+    }
+    serializer
+      ..endList()
+      ..addBool(isAbstract)
+      ..addBool(isExternal)
+      ..startList();
+    for (TypeAnnotationImpl mixin in mixins) {
+      mixin.serialize(serializer);
+    }
+    serializer..endList();
+    superclass.serializeNullable(serializer);
+  }
+}
+
+class TypeAliasDeclarationImpl extends TypeDeclarationImpl
+    implements TypeAliasDeclaration {
+  /// The type being aliased.
+  final TypeAnnotationImpl aliasedType;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.typeAliasDeclaration;
+
+  TypeAliasDeclarationImpl({
+    // Declaration fields
+    required int id,
+    required IdentifierImpl identifier,
+    // TypeDeclaration fields
+    required List<TypeParameterDeclarationImpl> typeParameters,
+    // TypeAlias fields
+    required this.aliasedType,
+  }) : super(id: id, identifier: identifier, typeParameters: typeParameters);
+
+  @override
+  void serialize(Serializer serializer) {
+    super.serialize(serializer);
+    // Client side we don't encode anything but the ID.
+    if (serializationMode == SerializationMode.client) {
+      return;
+    }
+
+    aliasedType.serialize(serializer);
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
new file mode 100644
index 0000000..0577fa2
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
@@ -0,0 +1,712 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 objects used for communication between the macro executor and
+/// the isolate or process doing the work of macro loading and execution.
+library _fe_analyzer_shared.src.macros.executor_shared.protocol;
+
+import 'package:meta/meta.dart';
+
+import '../executor.dart';
+import '../api.dart';
+import '../executor_shared/response_impls.dart';
+import 'introspection_impls.dart';
+import 'remote_instance.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// Base class all requests extend, provides a unique id for each request.
+abstract class Request implements Serializable {
+  final int id;
+
+  final int serializationZoneId;
+
+  Request({int? id, required this.serializationZoneId})
+      : this.id = id ?? _next++;
+
+  /// The [serializationZoneId] is a part of the header and needs to be parsed
+  /// before deserializing objects, and then passed in here.
+  Request.deserialize(Deserializer deserializer, this.serializationZoneId)
+      : id = (deserializer..moveNext()).expectNum();
+
+  /// The [serializationZoneId] needs to be separately serialized before the
+  /// rest of the object. This is not done by the instances themselves but by
+  /// the macro implementations.
+  @mustCallSuper
+  void serialize(Serializer serializer) => serializer.addNum(id);
+
+  static int _next = 0;
+}
+
+/// A generic response object that contains either a response or an error, and
+/// a unique ID.
+class Response {
+  final Object? response;
+  final Object? error;
+  final String? stackTrace;
+  final int requestId;
+  final MessageType responseType;
+
+  Response({
+    this.response,
+    this.error,
+    this.stackTrace,
+    required this.requestId,
+    required this.responseType,
+  })  : assert(response != null || error != null),
+        assert(response == null || error == null);
+}
+
+/// A serializable [Response], contains the message type as an enum.
+class SerializableResponse implements Response, Serializable {
+  final Serializable? response;
+  final MessageType responseType;
+  final String? error;
+  final String? stackTrace;
+  final int requestId;
+  final int serializationZoneId;
+
+  SerializableResponse({
+    this.error,
+    this.stackTrace,
+    required this.requestId,
+    this.response,
+    required this.responseType,
+    required this.serializationZoneId,
+  });
+
+  /// You must first parse the [serializationZoneId] yourself, and then
+  /// call this function in that zone, and pass the ID.
+  factory SerializableResponse.deserialize(
+      Deserializer deserializer, int serializationZoneId) {
+    deserializer.moveNext();
+    MessageType responseType = MessageType.values[deserializer.expectNum()];
+    Serializable? response;
+    String? error;
+    String? stackTrace;
+    switch (responseType) {
+      case MessageType.error:
+        deserializer.moveNext();
+        error = deserializer.expectString();
+        deserializer.moveNext();
+        stackTrace = deserializer.expectNullableString();
+        break;
+      case MessageType.macroClassIdentifier:
+        response = new MacroClassIdentifierImpl.deserialize(deserializer);
+        break;
+      case MessageType.macroInstanceIdentifier:
+        response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
+        break;
+      case MessageType.macroExecutionResult:
+        response = new MacroExecutionResultImpl.deserialize(deserializer);
+        break;
+      case MessageType.staticType:
+      case MessageType.namedStaticType:
+        response = RemoteInstance.deserialize(deserializer);
+        break;
+      case MessageType.boolean:
+        response = new BooleanValue.deserialize(deserializer);
+        break;
+      case MessageType.declarationList:
+        response = new DeclarationList.deserialize(deserializer);
+        break;
+      case MessageType.remoteInstance:
+        deserializer.moveNext();
+        if (!deserializer.checkNull()) {
+          response = deserializer.expectRemoteInstance();
+        }
+        break;
+      default:
+        throw new StateError('Unexpected response type $responseType');
+    }
+
+    return new SerializableResponse(
+        responseType: responseType,
+        response: response,
+        error: error,
+        stackTrace: stackTrace,
+        requestId: (deserializer..moveNext()).expectNum(),
+        serializationZoneId: serializationZoneId);
+  }
+
+  void serialize(Serializer serializer) {
+    serializer
+      ..addNum(serializationZoneId)
+      ..addNum(MessageType.response.index)
+      ..addNum(responseType.index);
+    switch (responseType) {
+      case MessageType.error:
+        serializer.addString(error!.toString());
+        serializer.addNullableString(stackTrace);
+        break;
+      default:
+        response.serializeNullable(serializer);
+    }
+    serializer.addNum(requestId);
+  }
+}
+
+class BooleanValue implements Serializable {
+  final bool value;
+
+  BooleanValue(this.value);
+
+  BooleanValue.deserialize(Deserializer deserializer)
+      : value = (deserializer..moveNext()).expectBool();
+
+  @override
+  void serialize(Serializer serializer) => serializer..addBool(value);
+}
+
+/// A serialized list of [Declaration]s.
+class DeclarationList<T extends DeclarationImpl> implements Serializable {
+  final List<T> declarations;
+
+  DeclarationList(this.declarations);
+
+  DeclarationList.deserialize(Deserializer deserializer)
+      : declarations = [
+          for (bool hasNext = (deserializer
+                    ..moveNext()
+                    ..expectList())
+                  .moveNext();
+              hasNext;
+              hasNext = deserializer.moveNext())
+            deserializer.expectRemoteInstance(),
+        ];
+
+  @override
+  void serialize(Serializer serializer) {
+    serializer.startList();
+    for (DeclarationImpl declaration in declarations) {
+      declaration.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
+
+/// A request to load a macro in this isolate.
+class LoadMacroRequest extends Request {
+  final Uri library;
+  final String name;
+
+  LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  LoadMacroRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : library = Uri.parse((deserializer..moveNext()).expectString()),
+        name = (deserializer..moveNext()).expectString(),
+        super.deserialize(deserializer, serializationZoneId);
+
+  @override
+  void serialize(Serializer serializer) {
+    serializer
+      ..addNum(MessageType.loadMacroRequest.index)
+      ..addString(library.toString())
+      ..addString(name);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to instantiate a macro instance.
+class InstantiateMacroRequest extends Request {
+  final MacroClassIdentifier macroClass;
+  final String constructorName;
+  final Arguments arguments;
+
+  InstantiateMacroRequest(this.macroClass, this.constructorName, this.arguments,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  InstantiateMacroRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
+        constructorName = (deserializer..moveNext()).expectString(),
+        arguments = new Arguments.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  @override
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.instantiateMacroRequest.index);
+    macroClass.serialize(serializer);
+    serializer.addString(constructorName);
+    arguments.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to execute a macro on a particular declaration in the types phase.
+class ExecuteTypesPhaseRequest extends Request {
+  final MacroInstanceIdentifier macro;
+  final DeclarationImpl declaration;
+
+  ExecuteTypesPhaseRequest(this.macro, this.declaration,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  ExecuteTypesPhaseRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+        declaration = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.executeTypesPhaseRequest.index);
+    macro.serialize(serializer);
+    declaration.serialize(serializer);
+
+    super.serialize(serializer);
+  }
+}
+
+/// A request to execute a macro on a particular declaration in the definition
+/// phase.
+class ExecuteDeclarationsPhaseRequest extends Request {
+  final MacroInstanceIdentifier macro;
+  final DeclarationImpl declaration;
+
+  final RemoteInstanceImpl typeResolver;
+  final RemoteInstanceImpl classIntrospector;
+
+  ExecuteDeclarationsPhaseRequest(
+      this.macro, this.declaration, this.typeResolver, this.classIntrospector,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  ExecuteDeclarationsPhaseRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+        declaration = RemoteInstance.deserialize(deserializer),
+        typeResolver = RemoteInstance.deserialize(deserializer),
+        classIntrospector = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.executeDeclarationsPhaseRequest.index);
+    macro.serialize(serializer);
+    declaration.serialize(serializer);
+    typeResolver.serialize(serializer);
+    classIntrospector.serialize(serializer);
+
+    super.serialize(serializer);
+  }
+}
+
+/// A request to execute a macro on a particular declaration in the definition
+/// phase.
+class ExecuteDefinitionsPhaseRequest extends Request {
+  final MacroInstanceIdentifier macro;
+  final DeclarationImpl declaration;
+
+  final RemoteInstanceImpl typeResolver;
+  final RemoteInstanceImpl classIntrospector;
+  final RemoteInstanceImpl typeDeclarationResolver;
+
+  ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
+      this.typeResolver, this.classIntrospector, this.typeDeclarationResolver,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  ExecuteDefinitionsPhaseRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
+        declaration = RemoteInstance.deserialize(deserializer),
+        typeResolver = RemoteInstance.deserialize(deserializer),
+        classIntrospector = RemoteInstance.deserialize(deserializer),
+        typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.executeDefinitionsPhaseRequest.index);
+    macro.serialize(serializer);
+    declaration.serialize(serializer);
+    typeResolver.serialize(serializer);
+    classIntrospector.serialize(serializer);
+    typeDeclarationResolver.serialize(serializer);
+
+    super.serialize(serializer);
+  }
+}
+
+/// A request to reflect on a type annotation
+class InstantiateTypeRequest extends Request {
+  final TypeAnnotationImpl typeAnnotation;
+  final RemoteInstanceImpl typeResolver;
+
+  InstantiateTypeRequest(this.typeAnnotation, this.typeResolver,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  InstantiateTypeRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : typeAnnotation = RemoteInstance.deserialize(deserializer),
+        typeResolver = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.instantiateTypeRequest.index);
+    typeAnnotation.serialize(serializer);
+    typeResolver.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to check if a type is exactly another type.
+class IsExactlyTypeRequest extends Request {
+  final RemoteInstanceImpl leftType;
+  final RemoteInstanceImpl rightType;
+
+  IsExactlyTypeRequest(this.leftType, this.rightType,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  IsExactlyTypeRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : leftType = RemoteInstance.deserialize(deserializer),
+        rightType = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.isExactlyTypeRequest.index);
+    leftType.serialize(serializer);
+    rightType.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to check if a type is exactly another type.
+class IsSubtypeOfRequest extends Request {
+  final RemoteInstanceImpl leftType;
+  final RemoteInstanceImpl rightType;
+
+  IsSubtypeOfRequest(this.leftType, this.rightType,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  IsSubtypeOfRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : leftType = RemoteInstance.deserialize(deserializer),
+        rightType = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.isSubtypeOfRequest.index);
+    leftType.serialize(serializer);
+    rightType.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A general request class for all requests coming from methods on the
+/// [ClassIntrospector] interface.
+class ClassIntrospectionRequest extends Request {
+  final ClassDeclarationImpl classDeclaration;
+  final RemoteInstanceImpl classIntrospector;
+  final MessageType requestKind;
+
+  ClassIntrospectionRequest(
+      this.classDeclaration, this.classIntrospector, this.requestKind,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again and it should instead be passed in here.
+  ClassIntrospectionRequest.deserialize(
+      Deserializer deserializer, this.requestKind, int serializationZoneId)
+      : classDeclaration = RemoteInstance.deserialize(deserializer),
+        classIntrospector = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  @override
+  void serialize(Serializer serializer) {
+    serializer.addNum(requestKind.index);
+    classDeclaration.serialize(serializer);
+    classIntrospector.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to get a [TypeDeclaration] for a [StaticType].
+class DeclarationOfRequest extends Request {
+  final IdentifierImpl identifier;
+  final RemoteInstanceImpl typeDeclarationResolver;
+
+  DeclarationOfRequest(this.identifier, this.typeDeclarationResolver,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  DeclarationOfRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : identifier = RemoteInstance.deserialize(deserializer),
+        typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  @override
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.declarationOfRequest.index);
+    identifier.serialize(serializer);
+    typeDeclarationResolver.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// Client side implementation of a [TypeResolver], which creates a
+/// [ResolveTypeRequest] and passes it to a given [sendRequest] function which
+/// can return the [Response].
+class ClientTypeResolver implements TypeResolver {
+  /// The actual remote instance of this type resolver.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) _sendRequest;
+
+  ClientTypeResolver(this._sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
+  @override
+  Future<StaticType> instantiateType(TypeAnnotationImpl typeAnnotation) async {
+    InstantiateTypeRequest request = new InstantiateTypeRequest(
+        typeAnnotation, remoteInstance,
+        serializationZoneId: serializationZoneId);
+    RemoteInstanceImpl remoteType =
+        _handleResponse(await _sendRequest(request));
+    switch (remoteType.kind) {
+      case RemoteInstanceKind.namedStaticType:
+        return new ClientNamedStaticTypeImpl(_sendRequest,
+            remoteInstance: remoteType,
+            serializationZoneId: serializationZoneId);
+      case RemoteInstanceKind.staticType:
+        return new ClientStaticTypeImpl(_sendRequest,
+            remoteInstance: remoteType,
+            serializationZoneId: serializationZoneId);
+      default:
+        throw new StateError(
+            'Expected either a StaticType or NamedStaticType but got '
+            '${remoteType.kind}');
+    }
+  }
+
+  @override
+  Future<StaticType> instantiateCode(ExpressionCode code) {
+    // TODO: implement instantiateCode
+    throw new UnimplementedError();
+  }
+}
+
+class ClientStaticTypeImpl implements StaticType {
+  /// The actual remote instance of this static type.
+  final RemoteInstanceImpl remoteInstance;
+
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientStaticTypeImpl(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
+  @override
+  Future<bool> isExactly(ClientStaticTypeImpl other) async {
+    IsExactlyTypeRequest request = new IsExactlyTypeRequest(
+        this.remoteInstance, other.remoteInstance,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
+  }
+
+  @override
+  Future<bool> isSubtypeOf(ClientStaticTypeImpl other) async {
+    IsSubtypeOfRequest request = new IsSubtypeOfRequest(
+        remoteInstance, other.remoteInstance,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
+  }
+}
+
+/// Named variant of the [ClientStaticTypeImpl].
+class ClientNamedStaticTypeImpl extends ClientStaticTypeImpl
+    implements NamedStaticType {
+  ClientNamedStaticTypeImpl(
+      Future<Response> Function(Request request) sendRequest,
+      {required RemoteInstanceImpl remoteInstance,
+      required int serializationZoneId})
+      : super(sendRequest,
+            remoteInstance: remoteInstance,
+            serializationZoneId: serializationZoneId);
+}
+
+/// Client side implementation of the [ClientClassIntrospector], converts all
+/// invocations into remote RPC calls.
+class ClientClassIntrospector implements ClassIntrospector {
+  /// The actual remote instance of this class introspector.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientClassIntrospector(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
+  @override
+  Future<List<ConstructorDeclaration>> constructorsOf(
+      ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.constructorsOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<DeclarationList>(await sendRequest(request))
+        .declarations
+        // TODO: Refactor so we can remove this cast
+        .cast();
+  }
+
+  @override
+  Future<List<FieldDeclaration>> fieldsOf(ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.fieldsOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<DeclarationList>(await sendRequest(request))
+        .declarations
+        // TODO: Refactor so we can remove this cast
+        .cast();
+  }
+
+  @override
+  Future<List<ClassDeclaration>> interfacesOf(
+      ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.interfacesOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<DeclarationList>(await sendRequest(request))
+        .declarations
+        // TODO: Refactor so we can remove this cast
+        .cast();
+  }
+
+  @override
+  Future<List<MethodDeclaration>> methodsOf(ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.methodsOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<DeclarationList>(await sendRequest(request))
+        .declarations
+        // TODO: Refactor so we can remove this cast
+        .cast();
+  }
+
+  @override
+  Future<List<ClassDeclaration>> mixinsOf(ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.mixinsOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<DeclarationList>(await sendRequest(request))
+        .declarations
+        // TODO: Refactor so we can remove this cast
+        .cast();
+  }
+
+  @override
+  Future<ClassDeclaration?> superclassOf(ClassDeclarationImpl clazz) async {
+    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
+        clazz, remoteInstance, MessageType.superclassOfRequest,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<ClassDeclaration?>(await sendRequest(request));
+  }
+}
+
+/// Client side implementation of a [TypeDeclarationResolver], converts all
+/// invocations into remote procedure calls.
+class ClientTypeDeclarationResolver implements TypeDeclarationResolver {
+  /// The actual remote instance of this type resolver.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientTypeDeclarationResolver(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
+  @override
+  Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) async {
+    DeclarationOfRequest request = new DeclarationOfRequest(
+        identifier, remoteInstance,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<TypeDeclaration>(await sendRequest(request));
+  }
+}
+
+/// An exception that occurred remotely, the exception object and stack trace
+/// are serialized as [String]s and both included in the [toString] output.
+class RemoteException implements Exception {
+  final String error;
+  final String? stackTrace;
+
+  RemoteException(this.error, [this.stackTrace]);
+
+  String toString() =>
+      'RemoteException: $error${stackTrace == null ? '' : '\n\n$stackTrace'}';
+}
+
+/// Either returns the actual response from [response], casted to [T], or throws
+/// a [RemoteException] with the given error and stack trace.
+T _handleResponse<T>(Response response) {
+  if (response.responseType == MessageType.error) {
+    throw new RemoteException(response.error!.toString(), response.stackTrace);
+  }
+  return response.response as T;
+}
+
+enum MessageType {
+  boolean,
+  constructorsOfRequest,
+  declarationOfRequest,
+  declarationList,
+  fieldsOfRequest,
+  interfacesOfRequest,
+  methodsOfRequest,
+  mixinsOfRequest,
+  superclassOfRequest,
+  error,
+  executeDeclarationsPhaseRequest,
+  executeDefinitionsPhaseRequest,
+  executeTypesPhaseRequest,
+  instantiateMacroRequest,
+  instantiateTypeRequest,
+  isExactlyTypeRequest,
+  isSubtypeOfRequest,
+  loadMacroRequest,
+  remoteInstance,
+  macroClassIdentifier,
+  macroInstanceIdentifier,
+  macroExecutionResult,
+  namedStaticType,
+  response,
+  staticType,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
new file mode 100644
index 0000000..7ba94f8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. 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:meta/meta.dart';
+
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// The key used to store the remote instance cache in the current serialization
+/// zone (in server mode only).
+const Symbol remoteInstanceZoneKey = #remoteInstanceCache;
+
+/// On the server side we keep track of remote instances by their ID.
+///
+/// These are a part of the current serialization zone, which all serialization
+/// and deserialization must be done in.
+///
+/// This means the cache lifetime is that of the serialization zone it is run
+/// in.
+Map<int, RemoteInstance> get _remoteInstanceCache =>
+    Zone.current[remoteInstanceZoneKey];
+
+/// Base class for types that need to be able to be traced back to a specific
+/// instance on the server side.
+abstract class RemoteInstance implements Serializable {
+  /// The unique ID for this instance.
+  final int id;
+
+  /// The type of instance being encoded.
+  RemoteInstanceKind get kind;
+
+  /// Static, incrementing ids.
+  static int _nextId = 0;
+
+  /// Gets the next unique identifier.
+  static int get uniqueId => _nextId++;
+
+  /// On the client side [id]s are given and you should reconstruct objects with
+  /// the given ID. On the server side ids should be created using
+  /// [RemoteInstance.uniqueId].
+  RemoteInstance(this.id);
+
+  /// Retrieves a cached instance by ID.
+  static T cached<T>(int id) => _remoteInstanceCache[id] as T;
+
+  /// Deserializes an instance based on the current [serializationMode].
+  static T deserialize<T>(Deserializer deserializer) =>
+      (deserializer..moveNext()).expectRemoteInstance();
+
+  /// This method should be overridden by all subclasses, which should on their
+  /// first line call this super function.
+  ///
+  /// They should then return immediately if [serializationMode] is
+  /// [SerializationMode.client], so that only an ID is sent.
+  @mustCallSuper
+  void serialize(Serializer serializer) {
+    serializer.addNum(id);
+    switch (serializationMode) {
+      case SerializationMode.client:
+        // We only send the ID from the client side.
+        return;
+      case SerializationMode.server:
+        serializer.addNum(kind.index);
+        _remoteInstanceCache[id] = this;
+        return;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) => other is RemoteInstance && id == other.id;
+}
+
+/// A remote instance which is just a pointer to some server side instance of
+/// a generic object.
+///
+/// The wrapped object is not serialized.
+class RemoteInstanceImpl extends RemoteInstance {
+  /// Always null on the client side, has an actual instance on the server side.
+  final Object? instance;
+
+  @override
+  final RemoteInstanceKind kind;
+
+  RemoteInstanceImpl({
+    required int id,
+    this.instance,
+    required this.kind,
+  }) : super(id);
+}
+
+// The kinds of instances.
+enum RemoteInstanceKind {
+  classDeclaration,
+  classIntrospector,
+  constructorDeclaration,
+  fieldDeclaration,
+  functionDeclaration,
+  functionTypeAnnotation,
+  identifier,
+  namedStaticType,
+  methodDeclaration,
+  namedTypeAnnotation,
+  parameterDeclaration,
+  staticType,
+  typeAliasDeclaration,
+  typeParameterDeclaration,
+  typeResolver,
+  typeDeclarationResolver,
+  variableDeclaration,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
new file mode 100644
index 0000000..eb4e5ae
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/response_impls.dart
@@ -0,0 +1,257 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../executor.dart';
+import '../api.dart';
+import 'serialization.dart';
+import 'serialization_extensions.dart';
+
+/// Implementation of [MacroClassIdentifier].
+class MacroClassIdentifierImpl implements MacroClassIdentifier {
+  final String id;
+
+  MacroClassIdentifierImpl(Uri library, String name) : id = '$library#$name';
+
+  MacroClassIdentifierImpl.deserialize(Deserializer deserializer)
+      : id = (deserializer..moveNext()).expectString();
+
+  void serialize(Serializer serializer) => serializer.addString(id);
+
+  operator ==(other) => other is MacroClassIdentifierImpl && id == other.id;
+
+  int get hashCode => id.hashCode;
+}
+
+/// Implementation of [MacroInstanceIdentifier].
+class MacroInstanceIdentifierImpl implements MacroInstanceIdentifier {
+  /// A single int where each bit indicates whether a specific macro interface
+  /// is implemented by this macro.
+  final int _interfaces;
+
+  static int _next = 0;
+
+  final int id;
+
+  MacroInstanceIdentifierImpl._(this._interfaces) : id = _next++;
+
+  factory MacroInstanceIdentifierImpl(Macro macro) {
+    // Build up the interfaces value, there is a bit for each declaration/phase
+    // combination (as there is an interface for each).
+    int interfaces = 0;
+    for (DeclarationKind declarationKind in DeclarationKind.values) {
+      for (Phase phase in Phase.values) {
+        int interfaceMask = _interfaceMask(declarationKind, phase);
+        switch (declarationKind) {
+          case DeclarationKind.clazz:
+            switch (phase) {
+              case Phase.types:
+                if (macro is ClassTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is ClassDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is ClassDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+          case DeclarationKind.constructor:
+            switch (phase) {
+              case Phase.types:
+                if (macro is ConstructorTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is ConstructorDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is ConstructorDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+          case DeclarationKind.field:
+            switch (phase) {
+              case Phase.types:
+                if (macro is FieldTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is FieldDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is FieldDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+          case DeclarationKind.function:
+            switch (phase) {
+              case Phase.types:
+                if (macro is FunctionTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is FunctionDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is FunctionDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+          case DeclarationKind.method:
+            switch (phase) {
+              case Phase.types:
+                if (macro is MethodTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is MethodDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is MethodDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+          case DeclarationKind.variable:
+            switch (phase) {
+              case Phase.types:
+                if (macro is VariableTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.declarations:
+                if (macro is VariableDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+              case Phase.definitions:
+                if (macro is VariableDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+                break;
+            }
+            break;
+        }
+      }
+    }
+
+    return new MacroInstanceIdentifierImpl._(interfaces);
+  }
+
+  MacroInstanceIdentifierImpl.deserialize(Deserializer deserializer)
+      : id = (deserializer..moveNext()).expectNum(),
+        _interfaces = (deserializer..moveNext()).expectNum();
+
+  void serialize(Serializer serializer) => serializer
+    ..addNum(id)
+    ..addNum(_interfaces);
+
+  operator ==(other) => other is MacroInstanceIdentifierImpl && id == other.id;
+
+  int get hashCode => id;
+
+  @override
+  bool shouldExecute(DeclarationKind declarationKind, Phase phase) {
+    int mask = _interfaceMask(declarationKind, phase);
+    if (declarationKind == DeclarationKind.method) {
+      // Apply function macros to methods.
+      mask |= _interfaceMask(DeclarationKind.function, phase);
+    } else if (declarationKind == DeclarationKind.field) {
+      // Apply variable macros to fields.
+      mask |= _interfaceMask(DeclarationKind.variable, phase);
+    }
+    return _interfaces & mask != 0x0;
+  }
+
+  @override
+  bool supportsDeclarationKind(DeclarationKind declarationKind) {
+    for (Phase phase in Phase.values) {
+      if (shouldExecute(declarationKind, phase)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// The mask for a particular interface, which is a combination of a kind of
+  /// declaration and a phase.
+  static int _interfaceMask(DeclarationKind declarationKind, Phase phase) =>
+      0x1 << (declarationKind.index * Phase.values.length) << phase.index;
+}
+
+/// Implementation of [MacroExecutionResult].
+class MacroExecutionResultImpl implements MacroExecutionResult {
+  @override
+  final List<DeclarationCode> augmentations;
+
+  @override
+  final List<DeclarationCode> imports;
+
+  MacroExecutionResultImpl({
+    required this.augmentations,
+    required this.imports,
+  });
+
+  factory MacroExecutionResultImpl.deserialize(Deserializer deserializer) {
+    deserializer.moveNext();
+    deserializer.expectList();
+    List<DeclarationCode> augmentations = [
+      for (bool hasNext = deserializer.moveNext();
+          hasNext;
+          hasNext = deserializer.moveNext())
+        deserializer.expectCode()
+    ];
+    deserializer.moveNext();
+    deserializer.expectList();
+    List<DeclarationCode> imports = [
+      for (bool hasNext = deserializer.moveNext();
+          hasNext;
+          hasNext = deserializer.moveNext())
+        deserializer.expectCode()
+    ];
+
+    return new MacroExecutionResultImpl(
+      augmentations: augmentations,
+      imports: imports,
+    );
+  }
+
+  void serialize(Serializer serializer) {
+    serializer.startList();
+    for (DeclarationCode augmentation in augmentations) {
+      augmentation.serialize(serializer);
+    }
+    serializer.endList();
+    serializer.startList();
+    for (DeclarationCode import in imports) {
+      import.serialize(serializer);
+    }
+    serializer.endList();
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
new file mode 100644
index 0000000..89bbf59
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization.dart
@@ -0,0 +1,238 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. 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 'remote_instance.dart';
+
+/// All serialization must be done in a serialization Zone, which tells it
+/// whether we are the client or server.
+///
+/// In [SerializationMode.server], sets up a remote instance cache to use when
+/// deserializing remote instances back to their original instance.
+T withSerializationMode<T>(SerializationMode mode, T Function() fn) =>
+    runZoned(fn, zoneValues: {
+      #serializationMode: mode,
+      if (mode == SerializationMode.server)
+        remoteInstanceZoneKey: <int, RemoteInstance>{}
+    });
+
+/// Serializable interface
+abstract class Serializable {
+  /// Serializes this object using [serializer].
+  void serialize(Serializer serializer);
+}
+
+/// A push based object serialization interface.
+abstract class Serializer {
+  /// Serializes a [String].
+  void addString(String value);
+
+  /// Serializes a nullable [String].
+  void addNullableString(String? value);
+
+  /// Serializes a [num].
+  void addNum(num value);
+
+  /// Serializes a nullable [num].
+  void addNullableNum(num? value);
+
+  /// Serializes a [bool].
+  void addBool(bool value);
+
+  /// Serializes a nullable [bool].
+  void addNullableBool(bool? value);
+
+  /// Serializes a `null` literal.
+  void addNull();
+
+  /// Used to signal the start of an arbitrary length list of items.
+  void startList();
+
+  /// Used to signal the end of an arbitrary length list of items.
+  void endList();
+}
+
+/// A pull based object deserialization interface.
+///
+/// You must call [moveNext] before reading any items, and in order to advance
+/// to the next item.
+abstract class Deserializer {
+  /// Checks if the current value is a null, returns `true` if so and `false`
+  /// otherwise.
+  bool checkNull();
+
+  /// Reads the current value as a non-nullable [String].
+  bool expectBool();
+
+  /// Reads the current value as a nullable [bool].
+  bool? expectNullableBool();
+
+  /// Reads the current value as a non-nullable [String].
+  T expectNum<T extends num>();
+
+  /// Reads the current value as a nullable [num].
+  num? expectNullableNum();
+
+  /// Reads the current value as a non-nullable [String].
+  String expectString();
+
+  /// Reads the current value as a nullable [String].
+  String? expectNullableString();
+
+  /// Asserts that the current item is the start of a list.
+  ///
+  /// An example for how to read from a list is as follows:
+  ///
+  /// var json = JsonReader.fromString(source);
+  /// I know it's a list of strings.
+  ///
+  /// ```
+  ///   var result = <String>[];
+  ///   deserializer.moveNext();
+  ///   deserializer.expectList();
+  ///   while (json.moveNext()) {
+  ///     result.add(json.expectString());
+  ///   }
+  ///   // Can now read later items, but need to call `moveNext` again to move
+  ///   // past the list.
+  ///   deserializer.moveNext();
+  ///   deserializer.expectBool();
+  /// ```
+  void expectList();
+
+  /// Moves to the next item, returns `false` if there are no more items to
+  /// read.
+  ///
+  /// If inside of a list, this returns `false` when the end of the list is
+  /// reached, and moves back to the parent, but does not advance it, so another
+  /// call to `moveNext` is needed. See example in the [expectList] docs.
+  bool moveNext();
+}
+
+class JsonSerializer implements Serializer {
+  /// The full result.
+  final _result = <Object?>[];
+
+  /// A path to the current list we are modifying.
+  late List<List<Object?>> _path = [_result];
+
+  /// Returns the result as an unmodifiable [Iterable].
+  ///
+  /// Asserts that all [List] entries have not been closed with [endList].
+  Iterable<Object?> get result {
+    assert(_path.length == 1);
+    return _result;
+  }
+
+  @override
+  void addBool(bool value) => _path.last.add(value);
+  @override
+  void addNullableBool(bool? value) => _path.last.add(value);
+
+  @override
+  void addNum(num value) => _path.last.add(value);
+  @override
+  void addNullableNum(num? value) => _path.last.add(value);
+
+  @override
+  void addString(String value) => _path.last.add(value);
+  @override
+  void addNullableString(String? value) => _path.last.add(value);
+
+  @override
+  void addNull() => _path.last.add(null);
+
+  @override
+  void startList() {
+    List<Object?> sublist = [];
+    _path.last.add(sublist);
+    _path.add(sublist);
+  }
+
+  @override
+  void endList() {
+    _path.removeLast();
+  }
+}
+
+class JsonDeserializer implements Deserializer {
+  /// The root source list to read from.
+  final Iterable<Object?> _source;
+
+  /// The path to the current iterator we are reading from.
+  late List<Iterator<Object?>> _path = [];
+
+  /// Whether we have received our first [moveNext] call.
+  bool _initialized = false;
+
+  /// Initialize this deserializer from `_source`.
+  JsonDeserializer(this._source);
+
+  @override
+  bool checkNull() => _expectValue<Object?>() == null;
+
+  @override
+  void expectList() => _path.add(_expectValue<Iterable<Object?>>().iterator);
+
+  @override
+  bool expectBool() => _expectValue();
+  @override
+  bool? expectNullableBool() => _expectValue();
+
+  @override
+  T expectNum<T extends num>() => _expectValue();
+  @override
+  num? expectNullableNum() => _expectValue();
+
+  @override
+  String expectString() => _expectValue();
+  @override
+  String? expectNullableString() => _expectValue();
+
+  /// Reads the current value and casts it to [T].
+  T _expectValue<T>() {
+    if (!_initialized) {
+      throw new StateError(
+          'You must call `moveNext()` before reading any values.');
+    }
+    return _path.last.current as T;
+  }
+
+  @override
+  bool moveNext() {
+    if (!_initialized) {
+      _path.add(_source.iterator);
+      _initialized = true;
+    }
+
+    // Move the current iterable, if its at the end of its items remove it from
+    // the current path and return false.
+    if (!_path.last.moveNext()) {
+      _path.removeLast();
+      return false;
+    }
+
+    return true;
+  }
+}
+
+/// Must be set using `withSerializationMode` before doing any serialization or
+/// deserialization.
+SerializationMode get serializationMode {
+  SerializationMode? mode =
+      Zone.current[#serializationMode] as SerializationMode?;
+  if (mode == null) {
+    throw new StateError('No SerializationMode set, you must do all '
+        'serialization inside a call to `withSerializationMode`.');
+  }
+  return mode;
+}
+
+/// Some objects are serialized differently on the client side versus the server
+/// side. This indicates the different modes.
+enum SerializationMode {
+  server,
+  client,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
new file mode 100644
index 0000000..ff8a0b2
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
@@ -0,0 +1,299 @@
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+
+import 'remote_instance.dart';
+import 'serialization.dart';
+import '../api.dart';
+
+extension DeserializerExtensions on Deserializer {
+  T expectRemoteInstance<T>() {
+    int id = expectNum();
+    switch (serializationMode) {
+      case SerializationMode.client:
+        moveNext();
+        RemoteInstanceKind kind = RemoteInstanceKind.values[expectNum()];
+        switch (kind) {
+          case RemoteInstanceKind.classIntrospector:
+          case RemoteInstanceKind.namedStaticType:
+          case RemoteInstanceKind.staticType:
+          case RemoteInstanceKind.typeDeclarationResolver:
+          case RemoteInstanceKind.typeResolver:
+            // These are simple wrappers, just pass in the kind
+            return new RemoteInstanceImpl(id: id, kind: kind) as T;
+          case RemoteInstanceKind.classDeclaration:
+            moveNext();
+            return _expectClassDeclaration(id) as T;
+          case RemoteInstanceKind.constructorDeclaration:
+            moveNext();
+            return _expectConstructorDeclaration(id) as T;
+          case RemoteInstanceKind.fieldDeclaration:
+            moveNext();
+            return _expectFieldDeclaration(id) as T;
+          case RemoteInstanceKind.functionDeclaration:
+            moveNext();
+            return _expectFunctionDeclaration(id) as T;
+          case RemoteInstanceKind.functionTypeAnnotation:
+            moveNext();
+            return _expectFunctionTypeAnnotation(id) as T;
+          case RemoteInstanceKind.identifier:
+            moveNext();
+            return _expectIdentifier(id) as T;
+          case RemoteInstanceKind.methodDeclaration:
+            moveNext();
+            return _expectMethodDeclaration(id) as T;
+          case RemoteInstanceKind.namedTypeAnnotation:
+            moveNext();
+            return _expectNamedTypeAnnotation(id) as T;
+          case RemoteInstanceKind.parameterDeclaration:
+            moveNext();
+            return _expectParameterDeclaration(id) as T;
+          case RemoteInstanceKind.typeAliasDeclaration:
+            moveNext();
+            return _expectTypeAliasDeclaration(id) as T;
+          case RemoteInstanceKind.typeParameterDeclaration:
+            moveNext();
+            return _expectTypeParameterDeclaration(id) as T;
+          case RemoteInstanceKind.variableDeclaration:
+            moveNext();
+            return _expectVariableDeclaration(id) as T;
+        }
+      case SerializationMode.server:
+        return RemoteInstance.cached(id) as T;
+    }
+  }
+
+  /// Helper method to read a list of [RemoteInstance]s.
+  List<T> _expectRemoteInstanceList<T extends RemoteInstance>() {
+    expectList();
+    return [
+      for (bool hasNext = moveNext(); hasNext; hasNext = moveNext())
+        expectRemoteInstance(),
+    ];
+  }
+
+  NamedTypeAnnotation _expectNamedTypeAnnotation(int id) =>
+      new NamedTypeAnnotationImpl(
+        id: id,
+        isNullable: expectBool(),
+        identifier: RemoteInstance.deserialize(this),
+        typeArguments: (this..moveNext())._expectRemoteInstanceList(),
+      );
+
+  FunctionTypeAnnotation _expectFunctionTypeAnnotation(int id) =>
+      new FunctionTypeAnnotationImpl(
+        id: id,
+        isNullable: expectBool(),
+        returnType: RemoteInstance.deserialize(this),
+        positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+        namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+      );
+
+  Identifier _expectIdentifier(int id) => new IdentifierImpl(
+        id: id,
+        name: expectString(),
+      );
+
+  ParameterDeclaration _expectParameterDeclaration(int id) =>
+      new ParameterDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        defaultValue: (this..moveNext()).checkNull() ? null : expectCode(),
+        isNamed: (this..moveNext()).expectBool(),
+        isRequired: (this..moveNext()).expectBool(),
+        type: RemoteInstance.deserialize(this),
+      );
+
+  TypeParameterDeclaration _expectTypeParameterDeclaration(int id) =>
+      new TypeParameterDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        bounds: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+      );
+
+  FunctionDeclaration _expectFunctionDeclaration(int id) =>
+      new FunctionDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        isAbstract: (this..moveNext()).expectBool(),
+        isExternal: (this..moveNext()).expectBool(),
+        isGetter: (this..moveNext()).expectBool(),
+        isSetter: (this..moveNext()).expectBool(),
+        namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+        positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+        returnType: RemoteInstance.deserialize(this),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+      );
+
+  MethodDeclaration _expectMethodDeclaration(int id) =>
+      new MethodDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        isAbstract: (this..moveNext()).expectBool(),
+        isExternal: (this..moveNext()).expectBool(),
+        isGetter: (this..moveNext()).expectBool(),
+        isSetter: (this..moveNext()).expectBool(),
+        namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+        positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+        returnType: RemoteInstance.deserialize(this),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+        definingClass: RemoteInstance.deserialize(this),
+      );
+
+  ConstructorDeclaration _expectConstructorDeclaration(int id) =>
+      new ConstructorDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        isAbstract: (this..moveNext()).expectBool(),
+        isExternal: (this..moveNext()).expectBool(),
+        isGetter: (this..moveNext()).expectBool(),
+        isSetter: (this..moveNext()).expectBool(),
+        namedParameters: (this..moveNext())._expectRemoteInstanceList(),
+        positionalParameters: (this..moveNext())._expectRemoteInstanceList(),
+        returnType: RemoteInstance.deserialize(this),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+        definingClass: RemoteInstance.deserialize(this),
+        isFactory: (this..moveNext()).expectBool(),
+      );
+
+  VariableDeclaration _expectVariableDeclaration(int id) =>
+      new VariableDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        initializer: (this..moveNext()).expectNullableCode(),
+        isExternal: (this..moveNext()).expectBool(),
+        isFinal: (this..moveNext()).expectBool(),
+        isLate: (this..moveNext()).expectBool(),
+        type: RemoteInstance.deserialize(this),
+      );
+
+  FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        initializer: (this..moveNext()).expectNullableCode(),
+        isExternal: (this..moveNext()).expectBool(),
+        isFinal: (this..moveNext()).expectBool(),
+        isLate: (this..moveNext()).expectBool(),
+        type: RemoteInstance.deserialize(this),
+        definingClass: RemoteInstance.deserialize(this),
+      );
+
+  ClassDeclaration _expectClassDeclaration(int id) => new ClassDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+        interfaces: (this..moveNext())._expectRemoteInstanceList(),
+        isAbstract: (this..moveNext()).expectBool(),
+        isExternal: (this..moveNext()).expectBool(),
+        mixins: (this..moveNext())._expectRemoteInstanceList(),
+        superclass:
+            (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+      );
+
+  TypeAliasDeclaration _expectTypeAliasDeclaration(int id) =>
+      new TypeAliasDeclarationImpl(
+        id: id,
+        identifier: expectRemoteInstance(),
+        typeParameters: (this..moveNext())._expectRemoteInstanceList(),
+        aliasedType: RemoteInstance.deserialize(this),
+      );
+
+  T expectCode<T extends Code>() {
+    CodeKind kind = CodeKind.values[expectNum()];
+    moveNext();
+    expectList();
+    List<Object> parts = [];
+    while (moveNext()) {
+      CodePartKind partKind = CodePartKind.values[expectNum()];
+      moveNext();
+      switch (partKind) {
+        case CodePartKind.code:
+          parts.add(expectCode());
+          break;
+        case CodePartKind.string:
+          parts.add(expectString());
+          break;
+        case CodePartKind.identifier:
+          parts.add(expectRemoteInstance());
+          break;
+      }
+    }
+
+    switch (kind) {
+      case CodeKind.raw:
+        return new Code.fromParts(parts) as T;
+      case CodeKind.declaration:
+        return new DeclarationCode.fromParts(parts) as T;
+      case CodeKind.element:
+        return new ElementCode.fromParts(parts) as T;
+      case CodeKind.expression:
+        return new ExpressionCode.fromParts(parts) as T;
+      case CodeKind.functionBody:
+        return new FunctionBodyCode.fromParts(parts) as T;
+      case CodeKind.namedArgument:
+        return new NamedArgumentCode.fromParts(parts) as T;
+      case CodeKind.parameter:
+        return new ParameterCode.fromParts(parts) as T;
+      case CodeKind.statement:
+        return new StatementCode.fromParts(parts) as T;
+    }
+  }
+
+  T? expectNullableCode<T extends Code>() {
+    if (checkNull()) return null;
+    return expectCode();
+  }
+}
+
+extension SerializeNullable on Serializable? {
+  /// Either serializes a `null` literal or the object.
+  void serializeNullable(Serializer serializer) {
+    Serializable? self = this;
+    if (self == null) {
+      serializer.addNull();
+    } else {
+      self.serialize(serializer);
+    }
+  }
+}
+
+extension SerializeNullableCode on Code? {
+  /// Either serializes a `null` literal or the code object.
+  void serializeNullable(Serializer serializer) {
+    Code? self = this;
+    if (self == null) {
+      serializer.addNull();
+    } else {
+      self.serialize(serializer);
+    }
+  }
+}
+
+extension SerializeCode on Code {
+  void serialize(Serializer serializer) {
+    serializer
+      ..addNum(kind.index)
+      ..startList();
+    for (Object part in parts) {
+      if (part is String) {
+        serializer
+          ..addNum(CodePartKind.string.index)
+          ..addString(part);
+      } else if (part is Code) {
+        serializer.addNum(CodePartKind.code.index);
+        part.serialize(serializer);
+      } else if (part is IdentifierImpl) {
+        serializer.addNum(CodePartKind.identifier.index);
+        part.serialize(serializer);
+      } else {
+        throw new StateError('Unrecognized code part $part');
+      }
+    }
+    serializer.endList();
+  }
+}
+
+enum CodePartKind {
+  string,
+  code,
+  identifier,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart
new file mode 100644
index 0000000..9bfd0a7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/fake_executor/fake_executor.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../executor.dart';
+
+/// The only public api exposed by this library, returns a [_FakeMacroExecutor].
+Future<MacroExecutor> start() async => new _FakeMacroExecutor();
+
+/// A [MacroExecutor] implementation which throws an [UnsupportedError] in all
+/// methods.
+class _FakeMacroExecutor implements MacroExecutor {
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    throw new UnsupportedError(
+        'Macro expansion is not supported on this platform.');
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
index d6476af..797ffb8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
@@ -7,16 +7,23 @@
 import 'dart:mirrors';
 
 import 'isolate_mirrors_impl.dart';
-import 'protocol.dart';
+import '../executor_shared/introspection_impls.dart';
+import '../executor_shared/protocol.dart';
+import '../executor_shared/remote_instance.dart';
 import '../executor.dart';
 import '../api.dart';
 
+/// Returns an instance of [_IsolateMirrorMacroExecutor].
+///
+/// This is the only public api exposed by this library.
+Future<MacroExecutor> start() => _IsolateMirrorMacroExecutor.start();
+
 /// A [MacroExecutor] implementation which relies on [IsolateMirror.loadUri]
 /// in order to load macros libraries.
 ///
 /// All actual work happens in a separate [Isolate], and this class serves as
 /// a bridge between that isolate and the language frontends.
-class IsolateMirrorMacroExecutor implements MacroExecutor {
+class _IsolateMirrorMacroExecutor implements MacroExecutor {
   /// The actual isolate doing macro loading and execution.
   final Isolate _macroIsolate;
 
@@ -24,19 +31,19 @@
   final SendPort _sendPort;
 
   /// The stream of responses from the [_macroIsolate].
-  final Stream<GenericResponse> _responseStream;
+  final Stream<Response> _responseStream;
 
   /// A map of response completers by request id.
-  final _responseCompleters = <int, Completer<GenericResponse>>{};
+  final _responseCompleters = <int, Completer<Response>>{};
 
   /// A function that should be invoked when shutting down this executor
   /// to perform any necessary cleanup.
   final void Function() _onClose;
 
-  IsolateMirrorMacroExecutor._(
+  _IsolateMirrorMacroExecutor._(
       this._macroIsolate, this._sendPort, this._responseStream, this._onClose) {
     _responseStream.listen((event) {
-      Completer<GenericResponse>? completer =
+      Completer<Response>? completer =
           _responseCompleters.remove(event.requestId);
       if (completer == null) {
         throw new StateError(
@@ -52,18 +59,18 @@
   static Future<MacroExecutor> start() async {
     ReceivePort receivePort = new ReceivePort();
     Completer<SendPort> sendPortCompleter = new Completer<SendPort>();
-    StreamController<GenericResponse> responseStreamController =
-        new StreamController<GenericResponse>(sync: true);
+    StreamController<Response> responseStreamController =
+        new StreamController<Response>(sync: true);
     receivePort.listen((message) {
       if (!sendPortCompleter.isCompleted) {
         sendPortCompleter.complete(message as SendPort);
       } else {
-        responseStreamController.add(message as GenericResponse);
+        responseStreamController.add(message as Response);
       }
     }).onDone(responseStreamController.close);
     Isolate macroIsolate = await Isolate.spawn(spawn, receivePort.sendPort);
 
-    return new IsolateMirrorMacroExecutor._(
+    return new _IsolateMirrorMacroExecutor._(
         macroIsolate,
         await sendPortCompleter.future,
         responseStreamController.stream,
@@ -96,12 +103,27 @@
   @override
   Future<MacroExecutionResult> executeDefinitionsPhase(
           MacroInstanceIdentifier macro,
-          Declaration declaration,
+          DeclarationImpl declaration,
           TypeResolver typeResolver,
           ClassIntrospector classIntrospector,
           TypeDeclarationResolver typeDeclarationResolver) =>
-      _sendRequest(new ExecuteDefinitionsPhaseRequest(macro, declaration,
-          typeResolver, classIntrospector, typeDeclarationResolver));
+      _sendRequest(new ExecuteDefinitionsPhaseRequest(
+          macro,
+          declaration,
+          new RemoteInstanceImpl(
+              instance: typeResolver,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.typeResolver),
+          new RemoteInstanceImpl(
+              instance: classIntrospector,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.classIntrospector),
+          new RemoteInstanceImpl(
+              instance: typeDeclarationResolver,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.typeDeclarationResolver),
+          // Serialization zones are not necessary in this executor.
+          serializationZoneId: -1));
 
   @override
   Future<MacroExecutionResult> executeTypesPhase(
@@ -116,21 +138,31 @@
           String constructor,
           Arguments arguments) =>
       _sendRequest(
-          new InstantiateMacroRequest(macroClass, constructor, arguments));
+          new InstantiateMacroRequest(macroClass, constructor, arguments,
+              // Serialization zones are not necessary in this executor.
+              serializationZoneId: -1));
 
   @override
-  Future<MacroClassIdentifier> loadMacro(Uri library, String name) =>
-      _sendRequest(new LoadMacroRequest(library, name));
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+      {Uri? precompiledKernelUri}) {
+    if (precompiledKernelUri != null) {
+      // TODO: Implement support?
+      throw new UnsupportedError(
+          'The IsolateMirrorsExecutor does not support precompiled dill files');
+    }
+    return _sendRequest(new LoadMacroRequest(library, name,
+        // Serialization zones are not necessary in this executor.
+        serializationZoneId: -1));
+  }
 
   /// Sends a request and returns the response, casting it to the expected
   /// type.
   Future<T> _sendRequest<T>(Request request) async {
     _sendPort.send(request);
-    Completer<GenericResponse<T>> completer =
-        new Completer<GenericResponse<T>>();
+    Completer<Response> completer = new Completer<Response>();
     _responseCompleters[request.id] = completer;
-    GenericResponse<T> response = await completer.future;
-    T? result = response.response;
+    Response response = await completer.future;
+    T? result = response.response as T?;
     if (result != null) return result;
     throw response.error!;
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
index 3cf24a5..4c435f6 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
@@ -6,8 +6,10 @@
 import 'dart:isolate';
 import 'dart:mirrors';
 
-import 'protocol.dart';
-import '../executor.dart';
+import '../executor_shared/builder_impls.dart';
+import '../executor_shared/introspection_impls.dart';
+import '../executor_shared/response_impls.dart';
+import '../executor_shared/protocol.dart';
 import '../api.dart';
 
 /// Spawns a new isolate for loading and executing macros.
@@ -15,33 +17,28 @@
   ReceivePort receivePort = new ReceivePort();
   sendPort.send(receivePort.sendPort);
   receivePort.listen((message) async {
+    Response response;
     if (message is LoadMacroRequest) {
-      GenericResponse<MacroClassIdentifier> response =
-          await _loadMacro(message);
-      sendPort.send(response);
+      response = await _loadMacro(message);
     } else if (message is InstantiateMacroRequest) {
-      GenericResponse<MacroInstanceIdentifier> response =
-          await _instantiateMacro(message);
-      sendPort.send(response);
+      response = await _instantiateMacro(message);
     } else if (message is ExecuteDefinitionsPhaseRequest) {
-      GenericResponse<MacroExecutionResult> response =
-          await _executeDefinitionsPhase(message);
-      sendPort.send(response);
+      response = await _executeDefinitionsPhase(message);
     } else {
       throw new StateError('Unrecognized event type $message');
     }
+    sendPort.send(response);
   });
 }
 
 /// Maps macro identifiers to class mirrors.
-final _macroClasses = <_MacroClassIdentifier, ClassMirror>{};
+final _macroClasses = <MacroClassIdentifierImpl, ClassMirror>{};
 
 /// Handles [LoadMacroRequest]s.
-Future<GenericResponse<MacroClassIdentifier>> _loadMacro(
-    LoadMacroRequest request) async {
+Future<Response> _loadMacro(LoadMacroRequest request) async {
   try {
-    _MacroClassIdentifier identifier =
-        new _MacroClassIdentifier(request.library, request.name);
+    MacroClassIdentifierImpl identifier =
+        new MacroClassIdentifierImpl(request.library, request.name);
     if (_macroClasses.containsKey(identifier)) {
       throw new UnsupportedError(
           'Reloading macros is not supported by this implementation');
@@ -51,18 +48,21 @@
     ClassMirror macroClass =
         libMirror.declarations[new Symbol(request.name)] as ClassMirror;
     _macroClasses[identifier] = macroClass;
-    return new GenericResponse(response: identifier, requestId: request.id);
+    return new Response(
+        response: identifier,
+        requestId: request.id,
+        responseType: MessageType.macroClassIdentifier);
   } catch (e) {
-    return new GenericResponse(error: e, requestId: request.id);
+    return new Response(
+        error: e, requestId: request.id, responseType: MessageType.error);
   }
 }
 
 /// Maps macro instance identifiers to instances.
-final _macroInstances = <_MacroInstanceIdentifier, Macro>{};
+final _macroInstances = <MacroInstanceIdentifierImpl, Macro>{};
 
 /// Handles [InstantiateMacroRequest]s.
-Future<GenericResponse<MacroInstanceIdentifier>> _instantiateMacro(
-    InstantiateMacroRequest request) async {
+Future<Response> _instantiateMacro(InstantiateMacroRequest request) async {
   try {
     ClassMirror? clazz = _macroClasses[request.macroClass];
     if (clazz == null) {
@@ -73,16 +73,20 @@
       for (MapEntry<String, Object?> entry in request.arguments.named.entries)
         new Symbol(entry.key): entry.value,
     }).reflectee as Macro;
-    _MacroInstanceIdentifier identifier = new _MacroInstanceIdentifier();
+    MacroInstanceIdentifierImpl identifier =
+        new MacroInstanceIdentifierImpl(instance);
     _macroInstances[identifier] = instance;
-    return new GenericResponse<MacroInstanceIdentifier>(
-        response: identifier, requestId: request.id);
+    return new Response(
+        response: identifier,
+        requestId: request.id,
+        responseType: MessageType.macroInstanceIdentifier);
   } catch (e) {
-    return new GenericResponse(error: e, requestId: request.id);
+    return new Response(
+        error: e, requestId: request.id, responseType: MessageType.error);
   }
 }
 
-Future<GenericResponse<MacroExecutionResult>> _executeDefinitionsPhase(
+Future<Response> _executeDefinitionsPhase(
     ExecuteDefinitionsPhaseRequest request) async {
   try {
     Macro? instance = _macroInstances[request.macro];
@@ -90,166 +94,38 @@
       throw new StateError('Unrecognized macro instance ${request.macro}\n'
           'Known instances: $_macroInstances)');
     }
-    Declaration declaration = request.declaration;
+    DeclarationImpl declaration = request.declaration;
     if (instance is FunctionDefinitionMacro &&
-        declaration is FunctionDeclaration) {
-      _FunctionDefinitionBuilder builder = new _FunctionDefinitionBuilder(
+        declaration is FunctionDeclarationImpl) {
+      FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
           declaration,
-          request.typeResolver,
-          request.typeDeclarationResolver,
-          request.classIntrospector);
+          request.classIntrospector.instance as ClassIntrospector,
+          request.typeResolver.instance as TypeResolver,
+          request.typeDeclarationResolver.instance as TypeDeclarationResolver);
       await instance.buildDefinitionForFunction(declaration, builder);
-      return new GenericResponse(
-          response: builder.result, requestId: request.id);
+      return new Response(
+          response: builder.result,
+          requestId: request.id,
+          responseType: MessageType.macroExecutionResult);
+    } else if (instance is MethodDefinitionMacro &&
+        declaration is MethodDeclarationImpl) {
+      FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
+          declaration,
+          request.classIntrospector.instance as ClassIntrospector,
+          request.typeResolver.instance as TypeResolver,
+          request.typeDeclarationResolver.instance as TypeDeclarationResolver);
+      await instance.buildDefinitionForMethod(declaration, builder);
+      return new SerializableResponse(
+          responseType: MessageType.macroExecutionResult,
+          response: builder.result,
+          requestId: request.id,
+          serializationZoneId: request.serializationZoneId);
     } else {
       throw new UnsupportedError(
-          ('Only FunctionDefinitionMacros are supported currently'));
+          'Only Method and Function Definition Macros are supported currently');
     }
   } catch (e) {
-    return new GenericResponse(error: e, requestId: request.id);
+    return new Response(
+        error: e, requestId: request.id, responseType: MessageType.error);
   }
 }
-
-/// Our implementation of [MacroClassIdentifier].
-class _MacroClassIdentifier implements MacroClassIdentifier {
-  final String id;
-
-  _MacroClassIdentifier(Uri library, String name) : id = '$library#$name';
-
-  operator ==(other) => other is _MacroClassIdentifier && id == other.id;
-
-  int get hashCode => id.hashCode;
-}
-
-/// Our implementation of [MacroInstanceIdentifier].
-class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
-  static int _next = 0;
-
-  final int id;
-
-  _MacroInstanceIdentifier() : id = _next++;
-
-  operator ==(other) => other is _MacroInstanceIdentifier && id == other.id;
-
-  int get hashCode => id;
-}
-
-/// Our implementation of [MacroExecutionResult].
-class _MacroExecutionResult implements MacroExecutionResult {
-  @override
-  final List<DeclarationCode> augmentations = <DeclarationCode>[];
-
-  @override
-  final List<DeclarationCode> imports = <DeclarationCode>[];
-}
-
-/// Custom implementation of [FunctionDefinitionBuilder].
-class _FunctionDefinitionBuilder implements FunctionDefinitionBuilder {
-  final TypeResolver typeResolver;
-  final TypeDeclarationResolver typeDeclarationResolver;
-  final ClassIntrospector classIntrospector;
-
-  /// The declaration this is a builder for.
-  final FunctionDeclaration declaration;
-
-  /// The final result, will be built up over `augment` calls.
-  final _MacroExecutionResult result = new _MacroExecutionResult();
-
-  _FunctionDefinitionBuilder(this.declaration, this.typeResolver,
-      this.typeDeclarationResolver, this.classIntrospector);
-
-  @override
-  void augment(FunctionBodyCode body) {
-    result.augmentations.add(new DeclarationCode.fromParts([
-      'augment ',
-      declaration.returnType.code,
-      ' ',
-      declaration.name,
-      if (declaration.typeParameters.isNotEmpty) ...[
-        '<',
-        for (TypeParameterDeclaration typeParam
-            in declaration.typeParameters) ...[
-          typeParam.name,
-          if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
-          if (typeParam != declaration.typeParameters.last) ', ',
-        ],
-        '>',
-      ],
-      '(',
-      for (ParameterDeclaration positionalRequired
-          in declaration.positionalParameters.where((p) => p.isRequired)) ...[
-        new ParameterCode.fromParts([
-          positionalRequired.type.code,
-          ' ',
-          positionalRequired.name,
-        ]),
-        ', '
-      ],
-      if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
-        '[',
-        for (ParameterDeclaration positionalOptional in declaration
-            .positionalParameters
-            .where((p) => !p.isRequired)) ...[
-          new ParameterCode.fromParts([
-            positionalOptional.type.code,
-            ' ',
-            positionalOptional.name,
-          ]),
-          ', ',
-        ],
-        ']',
-      ],
-      if (declaration.namedParameters.isNotEmpty) ...[
-        '{',
-        for (ParameterDeclaration named in declaration.namedParameters) ...[
-          new ParameterCode.fromParts([
-            if (named.isRequired) 'required ',
-            named.type.code,
-            ' ',
-            named.name,
-            if (named.defaultValue != null) ...[
-              ' = ',
-              named.defaultValue!,
-            ],
-          ]),
-          ', ',
-        ],
-        '}',
-      ],
-      ') ',
-      body,
-    ]));
-  }
-
-  @override
-  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
-      classIntrospector.constructorsOf(clazz);
-
-  @override
-  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
-      classIntrospector.fieldsOf(clazz);
-
-  @override
-  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
-      classIntrospector.interfacesOf(clazz);
-
-  @override
-  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
-      classIntrospector.methodsOf(clazz);
-
-  @override
-  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
-      classIntrospector.mixinsOf(clazz);
-
-  @override
-  Future<TypeDeclaration> declarationOf(NamedStaticType annotation) =>
-      typeDeclarationResolver.declarationOf(annotation);
-
-  @override
-  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
-      classIntrospector.superclassOf(clazz);
-
-  @override
-  Future<StaticType> resolve(TypeAnnotation typeAnnotation) =>
-      typeResolver.resolve(typeAnnotation);
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart
deleted file mode 100644
index 96a2724..0000000
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/protocol.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
-// for 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 objects used for communication between the macro executor and
-/// the isolate doing the work of macro loading and execution.
-library protocol;
-
-import '../executor.dart';
-import '../api.dart';
-
-/// Base class all requests extend, provides a unique id for each request.
-class Request {
-  final int id;
-
-  Request() : id = _next++;
-
-  static int _next = 0;
-}
-
-/// A generic response object that is either an instance of [T] or an error.
-class GenericResponse<T> {
-  final T? response;
-  final Object? error;
-  final int requestId;
-
-  GenericResponse({this.response, this.error, required this.requestId})
-      : assert(response != null || error != null),
-        assert(response == null || error == null);
-}
-
-/// A request to load a macro in this isolate.
-class LoadMacroRequest extends Request {
-  final Uri library;
-  final String name;
-
-  LoadMacroRequest(this.library, this.name);
-}
-
-/// A request to instantiate a macro instance.
-class InstantiateMacroRequest extends Request {
-  final MacroClassIdentifier macroClass;
-  final String constructorName;
-  final Arguments arguments;
-
-  InstantiateMacroRequest(
-      this.macroClass, this.constructorName, this.arguments);
-}
-
-/// A request to execute a macro on a particular declaration in the definition
-/// phase.
-class ExecuteDefinitionsPhaseRequest extends Request {
-  final MacroInstanceIdentifier macro;
-  final Declaration declaration;
-  final TypeResolver typeResolver;
-  final ClassIntrospector classIntrospector;
-  final TypeDeclarationResolver typeDeclarationResolver;
-
-  ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
-      this.typeResolver, this.classIntrospector, this.typeDeclarationResolver);
-}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
new file mode 100644
index 0000000..cfe6602
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
@@ -0,0 +1,466 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+
+import '../api.dart';
+import '../executor_shared/introspection_impls.dart';
+import '../executor_shared/protocol.dart';
+import '../executor_shared/response_impls.dart';
+import '../executor_shared/serialization.dart';
+import '../executor.dart';
+
+/// Returns an instance of [_IsolatedMacroExecutor].
+///
+/// This is the only public api exposed by this library.
+Future<MacroExecutor> start() async => new _IsolatedMacroExecutor();
+
+/// A [MacroExecutor] implementation which spawns a separate isolate for each
+/// macro that is loaded. Each of these is wrapped in its own
+/// [_SingleIsolatedMacroExecutor] which requests are delegated to.
+///
+/// This implementation requires precompiled kernel files when loading macros,
+/// (you must pass a `precompiledKernelUri` to [loadMacro]).
+///
+/// Spawned isolates are not ran in the same isolate group, so objects are
+/// serialized between isolates.
+class _IsolatedMacroExecutor implements MacroExecutor {
+  /// Individual executors indexed by [MacroClassIdentifier] or
+  /// [MacroInstanceIdentifier].
+  final _executors = <Object, _SingleIsolatedMacroExecutor>{};
+
+  @override
+  Future<String> buildAugmentationLibrary(
+      Iterable<MacroExecutionResult> macroResults) {
+    // TODO: implement buildAugmentationLibrary
+    throw new UnimplementedError();
+  }
+
+  @override
+  void close() {
+    for (_SingleIsolatedMacroExecutor executor in _executors.values) {
+      executor.close();
+    }
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+          MacroInstanceIdentifier macro,
+          DeclarationImpl declaration,
+          TypeResolver typeResolver,
+          ClassIntrospector classIntrospector) =>
+      _executors[macro]!.executeDeclarationsPhase(
+          macro, declaration, typeResolver, classIntrospector);
+
+  @override
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+          MacroInstanceIdentifier macro,
+          DeclarationImpl declaration,
+          TypeResolver typeResolver,
+          ClassIntrospector classIntrospector,
+          TypeDeclarationResolver typeDeclarationResolver) =>
+      _executors[macro]!.executeDefinitionsPhase(macro, declaration,
+          typeResolver, classIntrospector, typeDeclarationResolver);
+
+  @override
+  Future<MacroExecutionResult> executeTypesPhase(
+          MacroInstanceIdentifier macro, DeclarationImpl declaration) =>
+      _executors[macro]!.executeTypesPhase(macro, declaration);
+
+  @override
+  Future<MacroInstanceIdentifier> instantiateMacro(
+      MacroClassIdentifier macroClass,
+      String constructor,
+      Arguments arguments) async {
+    _SingleIsolatedMacroExecutor executor = _executors[macroClass]!;
+    MacroInstanceIdentifier instance =
+        await executor.instantiateMacro(macroClass, constructor, arguments);
+    _executors[instance] = executor;
+    return instance;
+  }
+
+  @override
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+      {Uri? precompiledKernelUri}) async {
+    if (precompiledKernelUri == null) {
+      throw new UnsupportedError(
+          'This environment requires a non-null `precompiledKernelUri` to be '
+          'passed when loading macros.');
+    }
+    MacroClassIdentifier identifier =
+        new MacroClassIdentifierImpl(library, name);
+    _executors.remove(identifier)?.close();
+
+    _SingleIsolatedMacroExecutor executor =
+        await _SingleIsolatedMacroExecutor.start(
+            library, name, precompiledKernelUri);
+    _executors[identifier] = executor;
+    return identifier;
+  }
+}
+
+class _SingleIsolatedMacroExecutor extends MacroExecutor {
+  /// The stream on which we receive responses.
+  final Stream<Object> messageStream;
+
+  /// The send port where we should send requests.
+  final SendPort sendPort;
+
+  /// A function that should be invoked when shutting down this executor
+  /// to perform any necessary cleanup.
+  final void Function() onClose;
+
+  /// A map of response completers by request id.
+  final responseCompleters = <int, Completer<Response>>{};
+
+  /// We need to know which serialization zone to deserialize objects in, so
+  /// that we read them from the correct cache. Each request creates its own
+  /// zone which it stores here by ID and then responses are deserialized in
+  /// the same zone.
+  static final serializationZones = <int, Zone>{};
+
+  /// Incrementing identifier for the serialization zone ids.
+  static int _nextSerializationZoneId = 0;
+
+  _SingleIsolatedMacroExecutor(
+      {required this.onClose,
+      required this.messageStream,
+      required this.sendPort}) {
+    messageStream.listen((message) {
+      withSerializationMode(SerializationMode.server, () {
+        JsonDeserializer deserializer =
+            new JsonDeserializer(message as List<Object?>);
+        // Every object starts with a zone ID which dictates the zone in which
+        // we should deserialize the message.
+        deserializer.moveNext();
+        int zoneId = deserializer.expectNum();
+        Zone zone = serializationZones[zoneId]!;
+        zone.run(() async {
+          deserializer.moveNext();
+          MessageType messageType =
+              MessageType.values[deserializer.expectNum()];
+          switch (messageType) {
+            case MessageType.response:
+              SerializableResponse response =
+                  new SerializableResponse.deserialize(deserializer, zoneId);
+              Completer<Response>? completer =
+                  responseCompleters.remove(response.requestId);
+              if (completer == null) {
+                throw new StateError(
+                    'Got a response for an unrecognized request id '
+                    '${response.requestId}');
+              }
+              completer.complete(response);
+              break;
+            case MessageType.instantiateTypeRequest:
+              InstantiateTypeRequest request =
+                  new InstantiateTypeRequest.deserialize(deserializer, zoneId);
+              StaticType instance =
+                  await (request.typeResolver.instance as TypeResolver)
+                      .instantiateType(request.typeAnnotation);
+              SerializableResponse response = new SerializableResponse(
+                  response: new RemoteInstanceImpl(
+                      id: RemoteInstance.uniqueId,
+                      instance: instance,
+                      kind: instance is NamedStaticType
+                          ? RemoteInstanceKind.namedStaticType
+                          : RemoteInstanceKind.staticType),
+                  requestId: request.id,
+                  responseType: instance is NamedStaticType
+                      ? MessageType.namedStaticType
+                      : MessageType.staticType,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.isExactlyTypeRequest:
+              IsExactlyTypeRequest request =
+                  new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
+              StaticType leftType = request.leftType.instance as StaticType;
+              StaticType rightType = request.rightType.instance as StaticType;
+              SerializableResponse response = new SerializableResponse(
+                  response:
+                      new BooleanValue(await leftType.isExactly(rightType)),
+                  requestId: request.id,
+                  responseType: MessageType.boolean,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.isSubtypeOfRequest:
+              IsSubtypeOfRequest request =
+                  new IsSubtypeOfRequest.deserialize(deserializer, zoneId);
+              StaticType leftType = request.leftType.instance as StaticType;
+              StaticType rightType = request.rightType.instance as StaticType;
+              SerializableResponse response = new SerializableResponse(
+                  response:
+                      new BooleanValue(await leftType.isSubtypeOf(rightType)),
+                  requestId: request.id,
+                  responseType: MessageType.boolean,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.declarationOfRequest:
+              DeclarationOfRequest request =
+                  new DeclarationOfRequest.deserialize(deserializer, zoneId);
+              TypeDeclarationResolver resolver = request
+                  .typeDeclarationResolver.instance as TypeDeclarationResolver;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.remoteInstance,
+                  response: (await resolver.declarationOf(request.identifier)
+                      // TODO: Consider refactoring to avoid the need for this.
+                      as TypeDeclarationImpl),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.constructorsOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.declarationList,
+                  response: new DeclarationList((await classIntrospector
+                          .constructorsOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      .cast<ConstructorDeclarationImpl>()),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.fieldsOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.declarationList,
+                  response: new DeclarationList((await classIntrospector
+                          .fieldsOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      .cast<FieldDeclarationImpl>()),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.interfacesOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.declarationList,
+                  response: new DeclarationList((await classIntrospector
+                          .interfacesOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      .cast<ClassDeclarationImpl>()),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.methodsOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.declarationList,
+                  response: new DeclarationList((await classIntrospector
+                          .methodsOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      .cast<MethodDeclarationImpl>()),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.mixinsOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.declarationList,
+                  response: new DeclarationList((await classIntrospector
+                          .mixinsOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      .cast<ClassDeclarationImpl>()),
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.superclassOfRequest:
+              ClassIntrospectionRequest request =
+                  new ClassIntrospectionRequest.deserialize(
+                      deserializer, messageType, zoneId);
+              ClassIntrospector classIntrospector =
+                  request.classIntrospector.instance as ClassIntrospector;
+              SerializableResponse response = new SerializableResponse(
+                  requestId: request.id,
+                  responseType: MessageType.remoteInstance,
+                  response: (await classIntrospector
+                          .superclassOf(request.classDeclaration))
+                      // TODO: Consider refactoring to avoid the need for this.
+                      as ClassDeclarationImpl?,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            default:
+              throw new StateError('Unexpected message type $messageType');
+          }
+        });
+      });
+    });
+  }
+
+  static Future<_SingleIsolatedMacroExecutor> start(
+      Uri library, String name, Uri precompiledKernelUri) async {
+    ReceivePort receivePort = new ReceivePort();
+    Isolate isolate =
+        await Isolate.spawnUri(precompiledKernelUri, [], receivePort.sendPort);
+    Completer<SendPort> sendPortCompleter = new Completer();
+    StreamController<Object> messageStreamController =
+        new StreamController(sync: true);
+    receivePort.listen((message) {
+      if (!sendPortCompleter.isCompleted) {
+        sendPortCompleter.complete(message as SendPort);
+      } else {
+        messageStreamController.add(message);
+      }
+    }).onDone(messageStreamController.close);
+
+    return new _SingleIsolatedMacroExecutor(
+        onClose: () {
+          receivePort.close();
+          isolate.kill();
+        },
+        messageStream: messageStreamController.stream,
+        sendPort: await sendPortCompleter.future);
+  }
+
+  @override
+  void close() => onClose();
+
+  /// These calls are handled by the higher level executor.
+  @override
+  Future<String> buildAugmentationLibrary(
+          Iterable<MacroExecutionResult> macroResults) =>
+      throw new StateError('Unreachable');
+
+  @override
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+          MacroInstanceIdentifier macro,
+          DeclarationImpl declaration,
+          TypeResolver typeResolver,
+          ClassIntrospector classIntrospector) =>
+      _sendRequest((zoneId) => new ExecuteDeclarationsPhaseRequest(
+          macro,
+          declaration,
+          new RemoteInstanceImpl(
+              instance: typeResolver,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.typeResolver),
+          new RemoteInstanceImpl(
+              instance: classIntrospector,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.classIntrospector),
+          serializationZoneId: zoneId));
+
+  @override
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+          MacroInstanceIdentifier macro,
+          DeclarationImpl declaration,
+          TypeResolver typeResolver,
+          ClassIntrospector classIntrospector,
+          TypeDeclarationResolver typeDeclarationResolver) =>
+      _sendRequest((zoneId) => new ExecuteDefinitionsPhaseRequest(
+          macro,
+          declaration,
+          new RemoteInstanceImpl(
+              instance: typeResolver,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.typeResolver),
+          new RemoteInstanceImpl(
+              instance: classIntrospector,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.classIntrospector),
+          new RemoteInstanceImpl(
+              instance: typeDeclarationResolver,
+              id: RemoteInstance.uniqueId,
+              kind: RemoteInstanceKind.typeDeclarationResolver),
+          serializationZoneId: zoneId));
+
+  @override
+  Future<MacroExecutionResult> executeTypesPhase(
+          MacroInstanceIdentifier macro, DeclarationImpl declaration) =>
+      _sendRequest((zoneId) => new ExecuteTypesPhaseRequest(macro, declaration,
+          serializationZoneId: zoneId));
+
+  @override
+  Future<MacroInstanceIdentifier> instantiateMacro(
+          MacroClassIdentifier macroClass,
+          String constructor,
+          Arguments arguments) =>
+      _sendRequest((zoneId) => new InstantiateMacroRequest(
+          macroClass, constructor, arguments,
+          serializationZoneId: zoneId));
+
+  /// These calls are handled by the higher level executor.
+  @override
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+          {Uri? precompiledKernelUri}) =>
+      throw new StateError('Unreachable');
+
+  /// Creates a [Request] with a given serialization zone ID, and handles the
+  /// response, casting it to the expected type or throwing the error provided.
+  Future<T> _sendRequest<T>(Request Function(int) requestFactory) =>
+      withSerializationMode(SerializationMode.server, () async {
+        int zoneId = _nextSerializationZoneId++;
+        serializationZones[zoneId] = Zone.current;
+        Request request = requestFactory(zoneId);
+        JsonSerializer serializer = new JsonSerializer();
+        // It is our responsibility to add the zone ID header.
+        serializer.addNum(zoneId);
+        request.serialize(serializer);
+        sendPort.send(serializer.result);
+        Completer<Response> completer = new Completer<Response>();
+        responseCompleters[request.id] = completer;
+        try {
+          Response response = await completer.future;
+          T? result = response.response as T?;
+          if (result != null) return result;
+          throw new RemoteException(
+              response.error!.toString(), response.stackTrace);
+        } finally {
+          // Clean up the zone after the request is done.
+          serializationZones.remove(zoneId);
+        }
+      });
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 14682ea..027c7bb 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1434,6 +1434,17 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalFailedAssertionWithNonStringMessage =
+    messageConstEvalFailedAssertionWithNonStringMessage;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalFailedAssertionWithNonStringMessage =
+    const MessageCode("ConstEvalFailedAssertionWithNonStringMessage",
+        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"],
+        problemMessage:
+            r"""This assertion failed with a non-String message.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String nameOKEmpty)>
     templateConstEvalGetterNotFound =
     const Template<Message Function(String nameOKEmpty)>(
@@ -2768,16 +2779,26 @@
     problemMessage: r"""An enum declaration can't be empty.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEnumDeclaresFactory = messageEnumDeclaresFactory;
+const Code<Null> codeEnumDeclaresConstFactory = messageEnumDeclaresConstFactory;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEnumDeclaresFactory = const MessageCode(
-    "EnumDeclaresFactory",
-    problemMessage: r"""Enums can't declare factory constructors.""",
+const MessageCode messageEnumDeclaresConstFactory = const MessageCode(
+    "EnumDeclaresConstFactory",
+    problemMessage: r"""Enums can't declare const factory constructors.""",
     correctionMessage:
         r"""Try removing the factory constructor declaration.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumEntryWithTypeArgumentsWithoutArguments =
+    messageEnumEntryWithTypeArgumentsWithoutArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumEntryWithTypeArgumentsWithoutArguments =
+    const MessageCode("EnumEntryWithTypeArgumentsWithoutArguments",
+        problemMessage:
+            r"""Missing arguments in enum constructor invocation.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeEnumInClass = messageEnumInClass;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2796,6 +2817,30 @@
     problemMessage: r"""Enums can't be instantiated.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateEnumSupertypeOfNonAbstractClass =
+    const Template<Message Function(String name)>(
+        problemMessageTemplate:
+            r"""Non-abstract class '#name' has 'Enum' as a superinterface.""",
+        withArguments: _withArgumentsEnumSupertypeOfNonAbstractClass);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeEnumSupertypeOfNonAbstractClass =
+    const Code<Message Function(String name)>(
+  "EnumSupertypeOfNonAbstractClass",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsEnumSupertypeOfNonAbstractClass(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeEnumSupertypeOfNonAbstractClass,
+      problemMessage:
+          """Non-abstract class '${name}' has 'Enum' as a superinterface.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeEqualityCannotBeEqualityOperand =
     messageEqualityCannotBeEqualityOperand;
 
@@ -5131,26 +5176,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateInferredPackageUri =
-    const Template<Message Function(Uri uri_)>(
-        problemMessageTemplate:
-            r"""Interpreting this as package URI, '#uri'.""",
-        withArguments: _withArgumentsInferredPackageUri);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Uri uri_)> codeInferredPackageUri =
-    const Code<Message Function(Uri uri_)>("InferredPackageUri",
-        severity: Severity.warning);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInferredPackageUri(Uri uri_) {
-  String? uri = relativizeUri(uri_);
-  return new Message(codeInferredPackageUri,
-      problemMessage: """Interpreting this as package URI, '${uri}'.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeInheritedMembersConflict = messageInheritedMembersConflict;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
index 6e224d0..6e4c96b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -504,7 +504,7 @@
 /// See [IdentifierContext.fieldInitializer].
 class FieldInitializerIdentifierContext extends IdentifierContext {
   const FieldInitializerIdentifierContext()
-      : super('fieldInitializer', isContinuation: true);
+      : super('fieldInitializer', inDeclaration: true, isContinuation: true);
 
   @override
   bool get allowsNewAsIdentifier => true;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 43e8331..a441a40 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -4375,8 +4375,6 @@
       case DeclarationKind.TopLevel:
         throw "Internal error: TopLevel factory.";
       case DeclarationKind.Enum:
-        reportRecoverableError(
-            factoryKeyword, codes.messageEnumDeclaresFactory);
         listener.endEnumFactoryMethod(beforeStart.next!, factoryKeyword, token);
         break;
     }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
index d599819..9e76440 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
@@ -251,6 +251,18 @@
 
   assert(typeParamOrArg == noTypeParamOrArg);
   next = next.next!;
+
+  // TODO(scheglov) This is a hack to partially fix.
+  // https://github.com/dart-lang/sdk/issues/47951
+  if (optional('?', next) &&
+      optional('super', next.next!) &&
+      optional('.', next.next!.next!)) {
+    return simpleNullableType;
+  }
+  if (optional('super', next) && optional('.', next.next!)) {
+    return simpleType;
+  }
+
   if (optional('.', next)) {
     next = next.next!;
     if (isValidTypeReference(next)) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
index fd2ed54..e1596e1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
@@ -358,7 +358,7 @@
       'offset=$offset,object=$objectText)';
 }
 
-abstract class DataRegistry<T> {
+mixin DataRegistry<T> {
   Map<Id, ActualData<T>> get actualMap;
 
   /// Registers [value] with [id] in [actualMap].
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart b/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
index bbc64f4..4e453145 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/libraries_specification.dart
@@ -42,8 +42,8 @@
 ///   - a top level entry for each target. Keys are target names (e.g. "vm"
 ///     above), and values contain the entire specification of a target.
 ///
-///   - each target specification is a map. Today, only one key is supported on
-///     this map: "libraries".
+///   - each target specification is a map. The supported keys are "libraries"
+///     and "include".
 ///
 ///   - The "libraries" entry contains details for how each platform library is
 ///     implemented. The entry is a map, where keys are the name of the platform
@@ -76,6 +76,33 @@
 ///     report that such library is still not supported in conditional imports
 ///     and const `fromEnvironment` expressions.
 ///
+///     Internal libraries are never supported through conditional imports and
+///     const `fromEnvironment` expressions.
+///
+///   - The "include" entry is a list of maps, each containing either a "path"
+///     and a "target" entry, or only a "target" entry.
+///
+///     If both "path" and "target" entries are present, the libraries
+///     specification file located at "path", relative to the location current
+///     libraries specification file is loaded, and the libraries defined
+///     in the target with the target name of the "target" entry are included in
+///     this target.
+///
+///     If only the "target" is present, the libraries in the target in the
+///     current libraries specification file with the target name of the
+///     "target" entry are included in this target.
+///
+///     The "include" mechanism support transitive inclusion but doesn't allow
+///     cyclic dependencies.
+///
+///     If the same library is defined in multiple included target
+///     specifications, the last included takes precedence. This means that
+///     if a target specification include a library and also defines it itself,
+///     the latter is used.
+///
+///     Currently it is not supported to include a subset of the libraries from
+///     an included target specifications.
+///
 ///
 /// Note: we currently have several different files that need to be updated
 /// when changing libraries, sources, and patch files:
@@ -96,9 +123,10 @@
 /// Contains information about all libraries on all target platforms defined in
 /// that file.
 class LibrariesSpecification {
+  final Uri specUri;
   final Map<String, TargetLibrariesSpecification> _targets;
 
-  const LibrariesSpecification(
+  const LibrariesSpecification(this.specUri,
       [this._targets = const <String, TargetLibrariesSpecification>{}]);
 
   /// The library specification for a given [target], or throws if none is
@@ -107,23 +135,53 @@
     TargetLibrariesSpecification? targetSpec = _targets[target];
     if (targetSpec == null) {
       throw new LibrariesSpecificationException(
-          'No library specification for target "$target"');
+          messageMissingTarget(target, specUri));
     }
     return targetSpec;
   }
 
+  static Future<LibrariesSpecification> load(
+      Uri uri, Future<String> Function(Uri uri) read) {
+    Map<Uri, LibrariesSpecification?> cache = {};
+    Future<LibrariesSpecification> loadSpecification(Uri uri) async {
+      if (cache.containsKey(uri)) {
+        LibrariesSpecification? specification = cache[uri];
+        if (specification == null) {
+          throw new LibrariesSpecificationException(messageCyclicSpec(uri));
+        }
+        return specification;
+      }
+      cache[uri] = null;
+      String json;
+      try {
+        json = await read(uri);
+      } catch (e) {
+        throw new LibrariesSpecificationException(
+            messageIncludePathCouldNotBeRead(uri, e));
+      }
+      return cache[uri] =
+          await LibrariesSpecification.parse(uri, json, loadSpecification);
+    }
+
+    return loadSpecification(uri);
+  }
+
   /// Parse the given [json] as a library specification, resolving any relative
-  /// paths from [baseUri].
+  /// paths from [specUri].
   ///
   /// May throw an exception if [json] is not properly formatted or contains
   /// invalid values.
-  static LibrariesSpecification parse(Uri baseUri, String? json) {
-    if (json == null) return const LibrariesSpecification();
+  static Future<LibrariesSpecification> parse(
+      Uri specUri,
+      String? json,
+      Future<LibrariesSpecification> Function(Uri uri)
+          loadSpecification) async {
+    if (json == null) return new LibrariesSpecification(specUri);
     Map<String, dynamic> jsonData;
     try {
       dynamic data = jsonDecode(json);
       if (data is! Map<String, dynamic>) {
-        return _reportError('top-level specification is not a map');
+        return _reportError(messageTopLevelIsNotAMap(specUri));
       }
       jsonData = data;
     } on FormatException catch (e) {
@@ -131,62 +189,131 @@
     }
     Map<String, TargetLibrariesSpecification> targets =
         <String, TargetLibrariesSpecification>{};
-    jsonData.forEach((String targetName, targetData) {
-      if (targetName.startsWith("comment:")) return null;
+
+    Set<String> currentTargets = {};
+
+    Future<TargetLibrariesSpecification> resolveTargetData(
+        String targetName) async {
+      TargetLibrariesSpecification? spec = targets[targetName];
+      if (spec != null) {
+        return spec;
+      }
+      if (currentTargets.contains(targetName)) {
+        _reportError(messageCyclicInternalInclude(targetName, specUri));
+      }
+
+      currentTargets.add(targetName);
       Map<String, LibraryInfo> libraries = <String, LibraryInfo>{};
+      Object? targetData = jsonData[targetName];
       if (targetData is! Map) {
-        _reportError("target specification for '$targetName' is not a map");
+        _reportError(messageTargetIsNotAMap(targetName, specUri));
+      }
+
+      Object? include = targetData["include"];
+      if (include != null) {
+        if (include is! List) {
+          _reportError(messageIncludeIsNotAList(targetName, specUri));
+        }
+        for (Object? map in include) {
+          if (map is! Map<String, dynamic>) {
+            _reportError(messageIncludeEntryIsNotAMap(targetName, specUri));
+          }
+          if (!map.containsKey("target")) {
+            _reportError(messageIncludeTargetMissing(targetName, specUri));
+          }
+          Object? target = map["target"];
+          if (target is! String) {
+            _reportError(messageIncludeTargetIsNotAString(targetName, specUri));
+          }
+          if (!map.containsKey("path")) {
+            if (!jsonData.containsKey(target)) {
+              _reportError(messageMissingTarget(target, specUri));
+            }
+            TargetLibrariesSpecification targetLibrariesSpecification =
+                await resolveTargetData(target);
+            libraries.addAll(targetLibrariesSpecification._libraries);
+          } else {
+            Object? path = map["path"];
+            if (path is! String) {
+              _reportError(messageIncludePathIsNotAString(targetName, specUri));
+            }
+            Uri uri = Uri.parse(path);
+            if (uri.scheme != '' && uri.scheme != 'file') {
+              return _reportError(messageUnsupportedUriScheme(path, specUri));
+            }
+            LibrariesSpecification specification =
+                await loadSpecification(specUri.resolveUri(uri));
+            TargetLibrariesSpecification targetSpecification =
+                specification.specificationFor(target);
+            for (LibraryInfo libraryInfo in targetSpecification.allLibraries) {
+              libraries[libraryInfo.name] = libraryInfo;
+            }
+          }
+        }
       }
       if (!targetData.containsKey("libraries")) {
-        _reportError("target specification "
-            "for '$targetName' doesn't have a libraries entry");
+        _reportError(messageTargetLibrariesMissing(targetName, specUri));
       }
-      dynamic librariesData = targetData["libraries"];
+      Object? librariesData = targetData["libraries"];
       if (librariesData is! Map<String, dynamic>) {
-        _reportError("libraries entry for '$targetName' is not a map");
+        _reportError(messageLibrariesEntryIsNotAMap(targetName, specUri));
       }
-      librariesData.forEach((String name, data) {
+      librariesData.forEach((String libraryName, Object? data) {
         if (data is! Map<String, dynamic>) {
           _reportError(
-              "library data for '$name' in target '$targetName' is not a map");
+              messageLibraryDataIsNotAMap(libraryName, targetName, specUri));
         }
-        Uri checkAndResolve(uriString) {
+        Uri checkAndResolve(Object? uriString) {
           if (uriString is! String) {
-            return _reportError("uri value '$uriString' is not a string"
-                "(from library '$name' in target '$targetName')");
+            return _reportError(messageLibraryUriIsNotAString(
+                uriString, libraryName, targetName, specUri));
           }
           Uri uri = Uri.parse(uriString);
           if (uri.scheme != '' && uri.scheme != 'file') {
-            return _reportError("uri scheme in '$uriString' is not supported.");
+            return _reportError(
+                messageUnsupportedUriScheme(uriString, specUri));
           }
-          return baseUri.resolveUri(uri);
+          return specUri.resolveUri(uri);
         }
 
+        if (!data.containsKey('uri')) {
+          _reportError(
+              messageLibraryUriMissing(libraryName, targetName, specUri));
+        }
         Uri uri = checkAndResolve(data['uri']);
         List<Uri> patches;
         if (data['patches'] is List) {
           patches =
-              data['patches'].map<Uri>((s) => baseUri.resolve(s)).toList();
+              data['patches'].map<Uri>((s) => specUri.resolve(s)).toList();
         } else if (data['patches'] is String) {
           patches = [checkAndResolve(data['patches'])];
         } else if (data['patches'] == null) {
           patches = const [];
         } else {
-          _reportError("patches entry for '$name' is not a list or a string");
+          _reportError(messagePatchesMustBeListOrString(libraryName));
         }
 
         dynamic supported = data['supported'] ?? true;
         if (supported is! bool) {
-          _reportError("\"supported\" entry: expected a 'bool' but "
-              "got a '${supported.runtimeType}' ('$supported')");
+          _reportError(messageSupportedIsNotABool(supported));
         }
-        libraries[name] =
-            new LibraryInfo(name, uri, patches, isSupported: supported);
+        libraries[libraryName] = new LibraryInfo(libraryName, uri, patches,
+            // Internal libraries are never supported through conditional
+            // imports and const `fromEnvironment` expressions.
+            isSupported: supported && !libraryName.startsWith('_'));
       });
-      targets[targetName] =
+      currentTargets.remove(targetName);
+      return targets[targetName] =
           new TargetLibrariesSpecification(targetName, libraries);
-    });
-    return new LibrariesSpecification(targets);
+    }
+
+    for (String targetName in jsonData.keys) {
+      if (targetName.startsWith("comment:")) {
+        continue;
+      }
+      await resolveTargetData(targetName);
+    }
+    return new LibrariesSpecification(specUri, targets);
   }
 
   static Never _reportError(String error) =>
@@ -264,3 +391,67 @@
   @override
   String toString() => '$error';
 }
+
+String messageMissingTarget(String targetName, Uri specUri) =>
+    'No library specification for target "$targetName" in ${specUri}.';
+
+String messageCyclicSpec(Uri specUri) => 'Cyclic dependency in ${specUri}.';
+
+String messageCyclicInternalInclude(String targetName, Uri specUri) =>
+    'Cyclic dependency of target "$targetName" in ${specUri}.';
+
+String messageTopLevelIsNotAMap(Uri specUri) =>
+    'Top-level specification is not a map in ${specUri}.';
+
+String messageTargetIsNotAMap(String targetName, Uri specUri) =>
+    'Target specification for "$targetName" is not a map in $specUri.';
+
+String messageIncludeIsNotAList(String targetName, Uri specUri) =>
+    '"include" specification for "$targetName" is not a list in $specUri.';
+
+String messageIncludeEntryIsNotAMap(String targetName, Uri specUri) =>
+    '"include" entry in "$targetName" is not a map in $specUri.';
+
+String messageIncludePathIsNotAString(String targetName, Uri specUri) =>
+    '"include" path in "$targetName" is not a string in  $specUri.';
+
+String messageIncludePathCouldNotBeRead(Uri includeUri, Object error) =>
+    '"include" path \'$includeUri\' could not be read: $error';
+
+String messageIncludeTargetMissing(String targetName, Uri specUri) =>
+    '"include" target in "$targetName" is missing in $specUri.';
+
+String messageIncludeTargetIsNotAString(String targetName, Uri specUri) =>
+    '"include" target in "$targetName" is not a string in $specUri.';
+
+String messageTargetLibrariesMissing(String targetName, Uri specUri) =>
+    'Target specification '
+    'for "$targetName" doesn\'t have a libraries entry in $specUri.';
+
+String messageLibrariesEntryIsNotAMap(String targetName, Uri specUri) =>
+    '"libraries" entry for "$targetName" is not a map in $specUri.';
+
+String messageLibraryDataIsNotAMap(
+        String libraryName, String targetName, Uri specUri) =>
+    'Library data for \'$libraryName\' in target "$targetName" is not a map '
+    'in $specUri.';
+
+String messageLibraryUriMissing(
+        String libraryName, String targetName, Uri specUri) =>
+    '"uri" is missing '
+    'from library \'$libraryName\' in target "$targetName" in $specUri.';
+
+String messageLibraryUriIsNotAString(
+        Object? uriValue, String libraryName, String targetName, Uri specUri) =>
+    'Uri value `$uriValue` is not a string '
+    '(from library \'$libraryName\' in target "$targetName" in $specUri).';
+
+String messageUnsupportedUriScheme(String uriValue, Uri specUri) =>
+    "Uri scheme in '$uriValue' is not supported in $specUri.";
+
+String messagePatchesMustBeListOrString(String libraryName) =>
+    '"patches" entry for "$libraryName" is not a list or a string.';
+
+String messageSupportedIsNotABool(Object supportedValue) =>
+    '"supported" entry: expected a `bool` but '
+    'got a `${supportedValue.runtimeType}` ("$supportedValue").';
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 9b35add..cfc2267 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 32.0.0
+version: 34.0.0
 description: Logic that is shared between the front_end and analyzer packages.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
 
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart
index 5dd4825..1b7e731 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart
@@ -8,3 +8,14 @@
     a = 0;
   }
 }
+
+class D {
+  const D(bool b) : assert(b);
+}
+
+class E {
+  final String a;
+  final String? b;
+
+  const E(this.a, {this.b});
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart
index b2b8e7d..40b86c3 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart
@@ -2,6 +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.
 
-dynamic /*member: x:assigned={a}*/ x = /*declared={a, b}*/ (int a, int b) {
+dynamic /*member: x1:assigned={a}*/ x1 = /*declared={a, b}*/ (int a, int b) {
   a = 0;
 };
+
+/*member: x2:none*/
+final x2 = new List.filled(0, null);
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index 249b33d..a3700cd 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -34,6 +34,7 @@
       var h = Harness();
       var x = Var('x', 'int?');
       h.run([
+        declare(x, initialized: true),
         assert_(x.expr.eq(nullLiteral),
             checkPromoted(x, 'int').thenExpr(expr('String'))),
       ]);
@@ -45,6 +46,9 @@
       var y = Var('y', 'int?');
       var z = Var('z', 'int?');
       h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        declare(z, initialized: true),
         x.expr.as_('int').stmt,
         z.expr.as_('int').stmt,
         assert_(block([
@@ -1008,9 +1012,10 @@
       var x = Var('x', 'int?');
       var y = Var('y', 'int?');
       h.run([
+        declare(x, initialized: true),
         declare(y, initialized: true),
         y.expr.as_('int').stmt,
-        getSsaNodes((nodes) => expect(nodes[x], null)),
+        getSsaNodes((nodes) => expect(nodes[x], isNotNull)),
         localFunction([
           getSsaNodes((nodes) => expect(nodes[x], isNot(nodes[y]))),
           x.expr.as_('int').stmt,
@@ -1019,7 +1024,6 @@
           checkNotPromoted(x),
         ]),
         localFunction([
-          declare(x, initialized: true),
           x.write(expr('Null')).stmt,
         ]),
       ]);
@@ -1384,6 +1388,7 @@
       var y = Var('y', 'int?');
       late ExpressionInfo<Var, Type> writtenValueInfo;
       h.run([
+        declare(y, initialized: true),
         declareInitialized(
             x,
             y.expr.eq(nullLiteral).getExpressionInfo((info) {
@@ -1401,6 +1406,7 @@
       var x = Var('x', 'Object', isLate: true);
       var y = Var('y', 'int?');
       h.run([
+        declare(y, initialized: true),
         declareInitialized(x, y.expr.eq(nullLiteral)),
         getSsaNodes((nodes) {
           expect(nodes[x]!.expressionInfo, isNull);
@@ -1415,6 +1421,7 @@
       var x = Var('x', 'Object', isImplicitlyTyped: true);
       var y = Var('y', 'int?');
       h.run([
+        declare(y, initialized: true),
         declareInitialized(x, y.expr.eq(nullLiteral)),
         getSsaNodes((nodes) {
           expect(nodes[x]!.expressionInfo, isNull);
@@ -1429,6 +1436,7 @@
       var x = Var('x', 'Object', isImplicitlyTyped: true);
       var y = Var('y', 'int?');
       h.run([
+        declare(y, initialized: true),
         declareInitialized(x, y.expr.eq(nullLiteral)),
         getSsaNodes((nodes) {
           expect(nodes[x]!.expressionInfo, isNotNull);
@@ -1443,6 +1451,7 @@
       var x = Var('x', 'Object');
       var y = Var('y', 'int?');
       h.run([
+        declare(y, initialized: true),
         declareInitialized(x, y.expr.eq(nullLiteral)),
         getSsaNodes((nodes) {
           expect(nodes[x]!.expressionInfo, isNotNull);
@@ -1853,6 +1862,7 @@
       var h = Harness();
       var x = Var('x', 'int?');
       h.run([
+        declare(x, initialized: true),
         if_(
             x.expr.parenthesized.notEq(nullLiteral.parenthesized).parenthesized,
             [
@@ -3039,6 +3049,7 @@
       late ExpressionInfo<Var, Type> writtenValueInfo;
       h.run([
         declare(x, initialized: true),
+        declare(y, initialized: true),
         getSsaNodes((nodes) => ssaBeforeWrite = nodes[x]!),
         x
             .write(y.expr.eq(nullLiteral).getExpressionInfo((info) {
@@ -3186,6 +3197,25 @@
         x.expr.as_('int').stmt, checkNotPromoted(x),
       ]);
     });
+
+    test('issue 47991', () {
+      var h = Harness();
+      var b = Var('b', 'bool');
+      var i = Var('i', 'int', isFinal: true);
+      h.run([
+        localFunction([
+          declareInitialized(b, expr('bool').or(expr('bool'))),
+          declare(i, initialized: false),
+          if_(b.expr, [
+            checkUnassigned(i, true),
+            i.write(expr('int')).stmt,
+          ], [
+            checkUnassigned(i, true),
+            i.write(expr('int')).stmt,
+          ]),
+        ]),
+      ]);
+    });
   });
 
   group('Reachability', () {
@@ -5871,17 +5901,17 @@
 }
 
 extension on FlowModel<Var, Type> {
+  ExpressionInfo<Var, Type> _tryMarkNonNullable(Harness h, Var variable) =>
+      tryMarkNonNullable(h, _varRefWithType(variable));
+
+  ExpressionInfo<Var, Type> _tryPromoteForTypeCheck(
+          Harness h, Var variable, String type) =>
+      tryPromoteForTypeCheck(h, _varRefWithType(variable), Type(type));
+
   Reference<Var, Type> _varRef(Var variable) =>
       new VariableReference<Var, Type>(variable);
 
   ReferenceWithType<Var, Type> _varRefWithType(Var variable) =>
       new ReferenceWithType<Var, Type>(_varRef(variable),
           variableInfo[variable]?.promotedTypes?.last ?? variable.type);
-
-  ExpressionInfo<Var, Type> _tryPromoteForTypeCheck(
-          Harness h, Var variable, String type) =>
-      tryPromoteForTypeCheck(h, _varRefWithType(variable), Type(type));
-
-  ExpressionInfo<Var, Type> _tryMarkNonNullable(Harness h, Var variable) =>
-      tryMarkNonNullable(h, _varRefWithType(variable));
 }
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
index 79f1f75..ceda8df 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
@@ -27,6 +27,9 @@
 /*class: Enum:Enum,Object*/
 abstract class Enum {}
 
+/*class: _Enum:Enum,Object,_Enum*/
+abstract class _Enum implements Enum {}
+
 /*class: Null:Null,Object*/
 class Null {
   factory Null._uninstantiable() {
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
index 2682390..f3d77df 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_out/core.dart
@@ -29,6 +29,9 @@
 /*class: Enum:Enum,Object*/
 abstract class Enum {}
 
+/*class: _Enum:Enum,Object,_Enum*/
+abstract class _Enum implements Enum {}
+
 /*class: Null:Null,Object*/
 class Null {
   factory Null._uninstantiable() {
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart
new file mode 100644
index 0000000..da0c02e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/response_impls_test.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/fake.dart';
+import 'package:test/test.dart';
+
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+void main() {
+  group('MacroInstanceIdentifierImpl', () {
+    test('shouldExecute', () {
+      for (var kind in DeclarationKind.values) {
+        for (var phase in Phase.values) {
+          var instance = instancesByKindAndPhase[kind]![phase]!;
+          for (var otherKind in DeclarationKind.values) {
+            for (var otherPhase in Phase.values) {
+              var expected = false;
+              if (otherPhase == phase) {
+                if (kind == otherKind) {
+                  expected = true;
+                } else if (kind == DeclarationKind.function &&
+                    otherKind == DeclarationKind.method) {
+                  expected = true;
+                } else if (kind == DeclarationKind.variable &&
+                    otherKind == DeclarationKind.field) {
+                  expected = true;
+                }
+              }
+              expect(instance.shouldExecute(otherKind, otherPhase), expected,
+                  reason: 'Expected a $kind macro in $phase to '
+                      '${expected ? '' : 'not '}be applied to a $otherKind '
+                      'in $otherPhase');
+            }
+          }
+        }
+      }
+    });
+
+    test('supportsDeclarationKind', () {
+      for (var kind in DeclarationKind.values) {
+        for (var phase in Phase.values) {
+          var instance = instancesByKindAndPhase[kind]![phase]!;
+          for (var otherKind in DeclarationKind.values) {
+            var expected = false;
+            if (kind == otherKind) {
+              expected = true;
+            } else if (kind == DeclarationKind.function &&
+                otherKind == DeclarationKind.method) {
+              expected = true;
+            } else if (kind == DeclarationKind.variable &&
+                otherKind == DeclarationKind.field) {
+              expected = true;
+            }
+            expect(instance.supportsDeclarationKind(otherKind), expected,
+                reason: 'Expected a $kind macro to ${expected ? '' : 'not '}'
+                    'support a $otherKind');
+          }
+        }
+      }
+    });
+  });
+}
+
+final Map<DeclarationKind, Map<Phase, MacroInstanceIdentifierImpl>>
+    instancesByKindAndPhase = {
+  DeclarationKind.clazz: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeClassTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeClassDeclarationsMacro()),
+    Phase.definitions: MacroInstanceIdentifierImpl(FakeClassDefinitionMacro()),
+  },
+  DeclarationKind.constructor: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeConstructorTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeConstructorDeclarationsMacro()),
+    Phase.definitions:
+        MacroInstanceIdentifierImpl(FakeConstructorDefinitionMacro()),
+  },
+  DeclarationKind.field: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeFieldTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeFieldDeclarationsMacro()),
+    Phase.definitions: MacroInstanceIdentifierImpl(FakeFieldDefinitionMacro()),
+  },
+  DeclarationKind.function: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeFunctionTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeFunctionDeclarationsMacro()),
+    Phase.definitions:
+        MacroInstanceIdentifierImpl(FakeFunctionDefinitionMacro()),
+  },
+  DeclarationKind.method: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeMethodTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeMethodDeclarationsMacro()),
+    Phase.definitions: MacroInstanceIdentifierImpl(FakeMethodDefinitionMacro()),
+  },
+  DeclarationKind.variable: {
+    Phase.types: MacroInstanceIdentifierImpl(FakeVariableTypesMacro()),
+    Phase.declarations:
+        MacroInstanceIdentifierImpl(FakeVariableDeclarationsMacro()),
+    Phase.definitions:
+        MacroInstanceIdentifierImpl(FakeVariableDefinitionMacro()),
+  },
+};
+
+class FakeClassTypesMacro extends Fake implements ClassTypesMacro {}
+
+class FakeClassDeclarationsMacro extends Fake
+    implements ClassDeclarationsMacro {}
+
+class FakeClassDefinitionMacro extends Fake implements ClassDefinitionMacro {}
+
+class FakeConstructorTypesMacro extends Fake implements ConstructorTypesMacro {}
+
+class FakeConstructorDeclarationsMacro extends Fake
+    implements ConstructorDeclarationsMacro {}
+
+class FakeConstructorDefinitionMacro extends Fake
+    implements ConstructorDefinitionMacro {}
+
+class FakeFieldTypesMacro extends Fake implements FieldTypesMacro {}
+
+class FakeFieldDeclarationsMacro extends Fake
+    implements FieldDeclarationsMacro {}
+
+class FakeFieldDefinitionMacro extends Fake implements FieldDefinitionMacro {}
+
+class FakeFunctionTypesMacro extends Fake implements FunctionTypesMacro {}
+
+class FakeFunctionDeclarationsMacro extends Fake
+    implements FunctionDeclarationsMacro {}
+
+class FakeFunctionDefinitionMacro extends Fake
+    implements FunctionDefinitionMacro {}
+
+class FakeMethodTypesMacro extends Fake implements MethodTypesMacro {}
+
+class FakeMethodDeclarationsMacro extends Fake
+    implements MethodDeclarationsMacro {}
+
+class FakeMethodDefinitionMacro extends Fake implements MethodDefinitionMacro {}
+
+class FakeVariableTypesMacro extends Fake implements VariableTypesMacro {}
+
+class FakeVariableDeclarationsMacro extends Fake
+    implements VariableDeclarationsMacro {}
+
+class FakeVariableDefinitionMacro extends Fake
+    implements VariableDefinitionMacro {}
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
new file mode 100644
index 0000000..502f9f9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
@@ -0,0 +1,315 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization_extensions.dart';
+import 'package:test/test.dart';
+
+import '../util.dart';
+
+void main() {
+  group('json serializer', () {
+    test('can serialize and deserialize basic data', () {
+      var serializer = JsonSerializer();
+      serializer
+        ..addNum(1)
+        ..addNullableNum(null)
+        ..addString('hello')
+        ..addNullableString(null)
+        ..startList()
+        ..addBool(true)
+        ..startList()
+        ..addNull()
+        ..endList()
+        ..addNullableBool(null)
+        ..endList()
+        ..addNum(1.0)
+        ..startList()
+        ..endList();
+      expect(
+          serializer.result,
+          equals([
+            1,
+            null,
+            'hello',
+            null,
+            [
+              true,
+              [null],
+              null
+            ],
+            1.0,
+            [],
+          ]));
+      var deserializer = JsonDeserializer(serializer.result);
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectNum(), 1);
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectNullableNum(), null);
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectString(), 'hello');
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectNullableString(), null);
+      expect(deserializer.moveNext(), true);
+
+      deserializer.expectList();
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectBool(), true);
+      expect(deserializer.moveNext(), true);
+
+      deserializer.expectList();
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.checkNull(), true);
+      expect(deserializer.moveNext(), false);
+
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectNullableBool(), null);
+      expect(deserializer.moveNext(), false);
+
+      // Have to move the parent again to advance it past the list entry.
+      expect(deserializer.moveNext(), true);
+      expect(deserializer.expectNum(), 1.0);
+      expect(deserializer.moveNext(), true);
+
+      deserializer.expectList();
+      expect(deserializer.moveNext(), false);
+
+      expect(deserializer.moveNext(), false);
+    });
+
+    test('remote instances', () async {
+      var string = NamedTypeAnnotationImpl(
+          id: RemoteInstance.uniqueId,
+          isNullable: false,
+          identifier:
+              IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
+          typeArguments: const []);
+      var foo = NamedTypeAnnotationImpl(
+          id: RemoteInstance.uniqueId,
+          isNullable: false,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+          typeArguments: [string]);
+      Object? serializedFoo;
+      var serializer = JsonSerializer();
+
+      withSerializationMode(SerializationMode.server, () {
+        foo.serialize(serializer);
+        serializedFoo = serializer.result;
+        var response = roundTrip(serializedFoo);
+        var deserializer = JsonDeserializer(response as List<Object?>);
+        var instance = RemoteInstance.deserialize(deserializer);
+        expect(instance, foo);
+      });
+    });
+
+    group('declarations', () {
+      final barType = NamedTypeAnnotationImpl(
+          id: RemoteInstance.uniqueId,
+          isNullable: false,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Bar'),
+          typeArguments: []);
+      final fooType = NamedTypeAnnotationImpl(
+          id: RemoteInstance.uniqueId,
+          isNullable: true,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+          typeArguments: [barType]);
+
+      test('NamedTypeAnnotation', () {
+        expectSerializationEquality(fooType);
+      });
+
+      final fooNamedParam = ParameterDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          defaultValue: null,
+          isNamed: true,
+          isRequired: true,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
+          type: fooType);
+
+      final barPositionalParam = ParameterDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          defaultValue: Code.fromString('const Bar()'),
+          isNamed: false,
+          isRequired: false,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+          type: barType);
+
+      final zapTypeParam = TypeParameterDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
+          bounds: barType);
+
+      // Transitively tests `TypeParameterDeclaration` and
+      // `ParameterDeclaration`.
+      test('FunctionTypeAnnotation', () {
+        var functionType = FunctionTypeAnnotationImpl(
+          id: RemoteInstance.uniqueId,
+          isNullable: true,
+          namedParameters: [fooNamedParam],
+          positionalParameters: [barPositionalParam],
+          returnType: fooType,
+          typeParameters: [zapTypeParam],
+        );
+        expectSerializationEquality(functionType);
+      });
+
+      test('FunctionDeclaration', () {
+        var function = FunctionDeclarationImpl(
+            id: RemoteInstance.uniqueId,
+            identifier:
+                IdentifierImpl(id: RemoteInstance.uniqueId, name: 'name'),
+            isAbstract: true,
+            isExternal: false,
+            isGetter: true,
+            isSetter: false,
+            namedParameters: [],
+            positionalParameters: [],
+            returnType: fooType,
+            typeParameters: []);
+        expectSerializationEquality(function);
+      });
+
+      test('MethodDeclaration', () {
+        var method = MethodDeclarationImpl(
+            id: RemoteInstance.uniqueId,
+            identifier:
+                IdentifierImpl(id: RemoteInstance.uniqueId, name: 'zorp'),
+            isAbstract: false,
+            isExternal: false,
+            isGetter: false,
+            isSetter: true,
+            namedParameters: [fooNamedParam],
+            positionalParameters: [barPositionalParam],
+            returnType: fooType,
+            typeParameters: [zapTypeParam],
+            definingClass: fooType.identifier);
+        expectSerializationEquality(method);
+      });
+
+      test('ConstructorDeclaration', () {
+        var constructor = ConstructorDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'new'),
+          isAbstract: false,
+          isExternal: false,
+          isGetter: false,
+          isSetter: false,
+          namedParameters: [fooNamedParam],
+          positionalParameters: [barPositionalParam],
+          returnType: fooType,
+          typeParameters: [zapTypeParam],
+          definingClass: fooType.identifier,
+          isFactory: true,
+        );
+        expectSerializationEquality(constructor);
+      });
+
+      test('VariableDeclaration', () {
+        var bar = VariableDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+          isExternal: true,
+          isFinal: false,
+          isLate: true,
+          initializer: ExpressionCode.fromString('Bar()'),
+          type: barType,
+        );
+        expectSerializationEquality(bar);
+      });
+
+      test('FieldDeclaration', () {
+        var bar = FieldDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
+          isExternal: false,
+          isFinal: true,
+          isLate: false,
+          initializer: null,
+          type: barType,
+          definingClass: fooType.identifier,
+        );
+        expectSerializationEquality(bar);
+      });
+
+      var objectType = NamedTypeAnnotationImpl(
+        id: RemoteInstance.uniqueId,
+        identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Object'),
+        isNullable: false,
+        typeArguments: [],
+      );
+      var serializableType = NamedTypeAnnotationImpl(
+        id: RemoteInstance.uniqueId,
+        identifier:
+            IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Serializable'),
+        isNullable: false,
+        typeArguments: [],
+      );
+
+      test('ClassDeclaration', () {
+        var fooClass = ClassDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+          interfaces: [barType],
+          isAbstract: true,
+          isExternal: false,
+          mixins: [serializableType],
+          superclass: objectType,
+          typeParameters: [zapTypeParam],
+        );
+        expectSerializationEquality(fooClass);
+      });
+
+      test('TypeAliasDeclaration', () {
+        var typeAlias = TypeAliasDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier:
+              IdentifierImpl(id: RemoteInstance.uniqueId, name: 'FooOfBar'),
+          typeParameters: [zapTypeParam],
+          aliasedType: NamedTypeAnnotationImpl(
+              id: RemoteInstance.uniqueId,
+              isNullable: false,
+              identifier:
+                  IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Foo'),
+              typeArguments: [barType]),
+        );
+        expectSerializationEquality(typeAlias);
+      });
+    });
+  });
+}
+
+/// Serializes [serializable] in server mode, then deserializes it in client
+/// mode, and checks that all the fields are the same.
+void expectSerializationEquality(Serializable serializable) {
+  var serializer = JsonSerializer();
+  withSerializationMode(SerializationMode.server, () {
+    serializable.serialize(serializer);
+  });
+  withSerializationMode(SerializationMode.client, () {
+    var deserializer = JsonDeserializer(serializer.result);
+    var deserialized = (deserializer..moveNext()).expectRemoteInstance();
+    if (deserialized is Declaration) {
+      expect(serializable, deepEqualsDeclaration(deserialized));
+    } else if (deserialized is TypeAnnotation) {
+      expect(serializable, deepEqualsTypeAnnotation(deserialized));
+    } else {
+      throw new UnsupportedError('Unsupported object type $deserialized');
+    }
+  });
+}
+
+/// Deserializes [serialized] in client mode and sends it back.
+Object? roundTrip<Declaration>(Object? serialized) {
+  return withSerializationMode(SerializationMode.client, () {
+    var deserializer = JsonDeserializer(serialized as List<Object?>);
+    var instance =
+        RemoteInstance.deserialize<NamedTypeAnnotationImpl>(deserializer);
+    var serializer = JsonSerializer();
+    instance.serialize(serializer);
+    return serializer.result;
+  });
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
index 48ca97b..80136bd 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
@@ -4,18 +4,32 @@
 
 import 'dart:io';
 
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor.dart';
-import 'package:_fe_analyzer_shared/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:_fe_analyzer_shared/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart'
+    as mirrorExecutor;
 
-import 'package:test/fake.dart';
 import 'package:test/test.dart';
 
+import '../util.dart';
+
 void main() {
   late MacroExecutor executor;
+  late File simpleMacroFile;
+
+  setUpAll(() {
+    // We support running from either the root of the SDK or the package root.
+    simpleMacroFile = File(
+        'pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart');
+    if (!simpleMacroFile.existsSync()) {
+      simpleMacroFile =
+          File('test/macros/isolate_mirror_executor/simple_macro.dart');
+    }
+  });
 
   setUp(() async {
-    executor = await IsolateMirrorMacroExecutor.start();
+    executor = await mirrorExecutor.start();
   });
 
   tearDown(() {
@@ -23,12 +37,8 @@
   });
 
   test('can load macros and create instances', () async {
-    var clazzId = await executor.loadMacro(
-        // Tests run from the root of the repo.
-        File('pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart')
-            .absolute
-            .uri,
-        'SimpleMacro');
+    var clazzId =
+        await executor.loadMacro(simpleMacroFile.absolute.uri, 'SimpleMacro');
     expect(clazzId, isNotNull, reason: 'Can load a macro.');
 
     var instanceId =
@@ -46,23 +56,31 @@
     expect(instanceId, isNotNull,
         reason: 'Can create an instance with named arguments.');
 
+    var returnType = NamedTypeAnnotationImpl(
+        id: RemoteInstance.uniqueId,
+        identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
+        isNullable: false,
+        typeArguments: const []);
     var definitionResult = await executor.executeDefinitionsPhase(
         instanceId,
-        _FunctionDeclaration(
+        FunctionDeclarationImpl(
+          id: RemoteInstance.uniqueId,
           isAbstract: false,
           isExternal: false,
           isGetter: false,
           isSetter: false,
-          name: 'foo',
+          identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
           namedParameters: [],
           positionalParameters: [],
-          returnType:
-              _TypeAnnotation(Code.fromString('String'), isNullable: false),
+          returnType: returnType,
           typeParameters: [],
         ),
-        _FakeTypeResolver(),
-        _FakeClassIntrospector(),
-        _FakeTypeDeclarationResolver());
+        TestTypeResolver({
+          returnType:
+              TestNamedStaticType(returnType.identifier, 'dart:core', [])
+        }),
+        FakeClassIntrospector(),
+        FakeTypeDeclarationResolver());
     expect(definitionResult.augmentations, hasLength(1));
     expect(definitionResult.augmentations.first.debugString().toString(),
         equalsIgnoringWhitespace('''
@@ -72,76 +90,3 @@
             }'''));
   });
 }
-
-class _FakeClassIntrospector with Fake implements ClassIntrospector {}
-
-class _FakeTypeResolver with Fake implements TypeResolver {}
-
-class _FakeTypeDeclarationResolver
-    with Fake
-    implements TypeDeclarationResolver {}
-
-class _FunctionDeclaration implements FunctionDeclaration {
-  @override
-  final bool isAbstract;
-
-  @override
-  final bool isExternal;
-
-  @override
-  final bool isGetter;
-
-  @override
-  final bool isSetter;
-
-  @override
-  final String name;
-
-  @override
-  final Iterable<ParameterDeclaration> namedParameters;
-
-  @override
-  final Iterable<ParameterDeclaration> positionalParameters;
-
-  @override
-  final TypeAnnotation returnType;
-
-  @override
-  final Iterable<TypeParameterDeclaration> typeParameters;
-
-  _FunctionDeclaration({
-    required this.isAbstract,
-    required this.isExternal,
-    required this.isGetter,
-    required this.isSetter,
-    required this.name,
-    required this.namedParameters,
-    required this.positionalParameters,
-    required this.returnType,
-    required this.typeParameters,
-  });
-}
-
-class _TypeAnnotation implements TypeAnnotation {
-  @override
-  final Code code;
-
-  @override
-  final bool isNullable;
-
-  _TypeAnnotation(this.code, {required this.isNullable});
-}
-
-extension _ on Code {
-  StringBuffer debugString([StringBuffer? buffer]) {
-    buffer ??= StringBuffer();
-    for (var part in parts) {
-      if (part is Code) {
-        part.debugString(buffer);
-      } else {
-        buffer.write(part.toString());
-      }
-    }
-    return buffer;
-  }
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
index b95da0b..7972041 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
@@ -18,13 +18,23 @@
 
   @override
   FutureOr<void> buildDefinitionForFunction(
-      FunctionDeclaration method, FunctionDefinitionBuilder builder) {
+      FunctionDeclaration method, FunctionDefinitionBuilder builder) async {
     if (method.namedParameters
         .followedBy(method.positionalParameters)
         .isNotEmpty) {
       throw ArgumentError(
           'This macro can only be run on functions with no arguments!');
     }
+
+    // Test the type resolver and static type interfaces
+    var staticReturnType = await builder.instantiateType(method.returnType);
+    if (!(await staticReturnType.isExactly(staticReturnType))) {
+      throw StateError('The return type should be exactly equal to itself!');
+    }
+    if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
+      throw StateError('The return type should be a subtype of itself!');
+    }
+
     builder.augment(FunctionBodyCode.fromString('''{
       print('x: $x, y: $y');
       return augment super();
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
new file mode 100644
index 0000000..cdd1725
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
@@ -0,0 +1,448 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. 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 'dart:isolate';
+
+import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
+    as isolatedExecutor;
+
+import 'package:test/test.dart';
+
+import '../util.dart';
+
+void main() {
+  late MacroExecutor executor;
+  late File kernelOutputFile;
+  final macroName = 'SimpleMacro';
+  late MacroInstanceIdentifier instanceId;
+  late Uri macroUri;
+  late File simpleMacroFile;
+  late Directory tmpDir;
+
+  setUpAll(() async {
+    // We support running from either the root of the SDK or the package root.
+    simpleMacroFile = File(
+        'pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart');
+    if (!simpleMacroFile.existsSync()) {
+      simpleMacroFile = File('test/macros/isolated_executor/simple_macro.dart');
+    }
+    executor = await isolatedExecutor.start();
+    tmpDir = Directory.systemTemp.createTempSync('isolated_executor_test');
+    macroUri = simpleMacroFile.absolute.uri;
+
+    var bootstrapContent = bootstrapMacroIsolate({
+      macroUri.toString(): {
+        macroName: ['', 'named']
+      }
+    });
+    var bootstrapFile = File(tmpDir.uri.resolve('main.dart').toFilePath())
+      ..writeAsStringSync(bootstrapContent);
+    kernelOutputFile = File(tmpDir.uri.resolve('main.dart.dill').toFilePath());
+    var buildSnapshotResult = await Process.run(Platform.resolvedExecutable, [
+      '--snapshot=${kernelOutputFile.uri.toFilePath()}',
+      '--snapshot-kind=kernel',
+      '--packages=${(await Isolate.packageConfig)!}',
+      bootstrapFile.uri.toFilePath(),
+    ]);
+    expect(buildSnapshotResult.exitCode, 0,
+        reason: 'stdout: ${buildSnapshotResult.stdout}\n'
+            'stderr: ${buildSnapshotResult.stderr}');
+
+    var clazzId = await executor.loadMacro(macroUri, macroName,
+        precompiledKernelUri: kernelOutputFile.uri);
+    expect(clazzId, isNotNull, reason: 'Can load a macro.');
+
+    instanceId =
+        await executor.instantiateMacro(clazzId, '', Arguments([], {}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with no arguments.');
+
+    instanceId =
+        await executor.instantiateMacro(clazzId, '', Arguments([1, 2], {}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with positional arguments.');
+
+    instanceId = await executor.instantiateMacro(
+        clazzId, 'named', Arguments([], {'x': 1, 'y': 2}));
+    expect(instanceId, isNotNull,
+        reason: 'Can create an instance with named arguments.');
+  });
+
+  tearDownAll(() {
+    if (tmpDir.existsSync()) tmpDir.deleteSync(recursive: true);
+    executor.close();
+  });
+
+  group('run macros', () {
+    group('in the types phase', () {
+      test('on functions', () async {
+        var result =
+            await executor.executeTypesPhase(instanceId, Fixtures.myFunction);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyFunction {}'));
+      });
+
+      test('on methods', () async {
+        var result =
+            await executor.executeTypesPhase(instanceId, Fixtures.myMethod);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyMethod {}'));
+      });
+
+      test('on getters', () async {
+        var result = await executor.executeTypesPhase(
+          instanceId,
+          Fixtures.myVariableGetter,
+        );
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyVariableGetter {}'));
+      });
+
+      test('on setters', () async {
+        var result = await executor.executeTypesPhase(
+          instanceId,
+          Fixtures.myVariableSetter,
+        );
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyVariableSetter {}'));
+      });
+
+      test('on variables', () async {
+        var result = await executor.executeTypesPhase(
+          instanceId,
+          Fixtures.myVariable,
+        );
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedBy_myVariable {}'));
+      });
+
+      test('on constructors', () async {
+        var result = await executor.executeTypesPhase(
+            instanceId, Fixtures.myConstructor);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyConstructor {}'));
+      });
+
+      test('on fields', () async {
+        var result =
+            await executor.executeTypesPhase(instanceId, Fixtures.myField);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('class GeneratedByMyField {}'));
+      });
+
+      test('on classes', () async {
+        var result =
+            await executor.executeTypesPhase(instanceId, Fixtures.myClass);
+        expect(
+            result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace(
+                'class MyClassBuilder implements Builder<MyClass> {}'));
+      });
+    });
+
+    group('in the declaration phase', () {
+      test('on functions', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myFunction,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(
+            result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace(
+                'String delegateMyFunction() => myFunction();'));
+      });
+
+      test('on methods', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myMethod,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(
+            result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace(
+                'String delegateMemberMyMethod() => myMethod();'));
+      });
+
+      test('on constructors', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myConstructor,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+              augment class MyClass {
+                factory MyClass.myConstructorDelegate() => MyClass.myConstructor();
+              }'''));
+      });
+
+      test('on getters', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myVariableGetter,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                String get delegateMyVariable => myVariable;'''));
+      });
+
+      test('on setters', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myVariableSetter,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                void set delegateMyVariable(String value) => myVariable = value;'''));
+      });
+
+      test('on variables', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myVariable,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                String get delegate_myVariable => _myVariable;'''));
+      });
+
+      test('on fields', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myField,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+              augment class MyClass {
+                String get delegateMyField => myField;
+              }'''));
+      });
+
+      test('on classes', () async {
+        var result = await executor.executeDeclarationsPhase(
+            instanceId,
+            Fixtures.myClass,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+              augment class MyClass {
+                static const List<String> fieldNames = ['myField',];
+              }'''));
+      });
+    });
+
+    group('in the definition phase', () {
+      test('on functions', () async {
+        var result = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myFunction,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                augment String myFunction() {
+                  print('isAbstract: false');
+                  print('isExternal: false');
+                  print('isGetter: false');
+                  print('isSetter: false');
+                  print('returnType: String');
+                  return augment super();
+                }'''));
+      });
+
+      test('on methods', () async {
+        var definitionResult = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myMethod,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(definitionResult.augmentations, hasLength(2));
+        var augmentationStrings = definitionResult.augmentations
+            .map((a) => a.debugString().toString())
+            .toList();
+        expect(augmentationStrings, unorderedEquals(methodDefinitionMatchers));
+      });
+
+      test('on constructors', () async {
+        var definitionResult = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myConstructor,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(definitionResult.augmentations, hasLength(1));
+        expect(definitionResult.augmentations.first.debugString().toString(),
+            constructorDefinitionMatcher);
+      });
+
+      test('on getters', () async {
+        var result = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myVariableGetter,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                augment String myVariable() {
+                  print('isAbstract: false');
+                  print('isExternal: false');
+                  print('isGetter: true');
+                  print('isSetter: false');
+                  print('returnType: String');
+                  return augment super;
+                }'''));
+      });
+
+      test('on setters', () async {
+        var result = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myVariableSetter,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(result.augmentations.single.debugString().toString(),
+            equalsIgnoringWhitespace('''
+                augment void myVariable(String value, ) {
+                  print('isAbstract: false');
+                  print('isExternal: false');
+                  print('isGetter: false');
+                  print('isSetter: true');
+                  print('returnType: void');
+                  print('positionalParam: String value');
+                  return augment super = value;
+                }'''));
+      });
+
+      test('on variables', () async {
+        var result = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myVariable,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(
+            result.augmentations.map((a) => a.debugString().toString()),
+            unorderedEquals([
+              equalsIgnoringWhitespace('''
+                augment String get _myVariable {
+                  print('parentClass: ');
+                  print('isExternal: false');
+                  print('isFinal: true');
+                  print('isLate: false');
+                  return augment super;
+                }'''),
+              equalsIgnoringWhitespace('''
+                augment set _myVariable(String value) {
+                  augment super = value;
+                }'''),
+              equalsIgnoringWhitespace('''
+                augment final String _myVariable = '';
+                '''),
+            ]));
+      });
+
+      test('on fields', () async {
+        var definitionResult = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myField,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        expect(definitionResult.augmentations, hasLength(1));
+        expect(definitionResult.augmentations.first.debugString().toString(),
+            fieldDefinitionMatcher);
+      });
+
+      test('on classes', () async {
+        var definitionResult = await executor.executeDefinitionsPhase(
+            instanceId,
+            Fixtures.myClass,
+            Fixtures.testTypeResolver,
+            Fixtures.testClassIntrospector,
+            Fixtures.testTypeDeclarationResolver);
+        var augmentationStrings = definitionResult.augmentations
+            .map((a) => a.debugString().toString())
+            .toList();
+        expect(
+            augmentationStrings,
+            unorderedEquals([
+              ...methodDefinitionMatchers,
+              constructorDefinitionMatcher,
+              fieldDefinitionMatcher
+            ]));
+      });
+    });
+  });
+}
+
+final constructorDefinitionMatcher = equalsIgnoringWhitespace('''
+augment class MyClass {
+  augment MyClass.myConstructor() {
+    print('definingClass: MyClass');
+    print('isFactory: false');
+    print('isAbstract: false');
+    print('isExternal: false');
+    print('isGetter: false');
+    print('isSetter: false');
+    print('returnType: MyClass');
+    return augment super();
+  }
+}''');
+
+final fieldDefinitionMatcher = equalsIgnoringWhitespace('''
+augment class MyClass {
+  augment String get myField {
+    print('parentClass: MyClass');
+    print('isExternal: false');
+    print('isFinal: false');
+    print('isLate: false');
+    return augment super;
+  }
+  augment set myField(String value) {
+    augment super = value;
+  }
+}''');
+
+final methodDefinitionMatchers = [
+  equalsIgnoringWhitespace('''
+    augment class MyClass {
+      augment String myMethod() {
+        print('definingClass: MyClass');
+        print('isAbstract: false');
+        print('isExternal: false');
+        print('isGetter: false');
+        print('isSetter: false');
+        print('returnType: String');
+        return augment super();
+      }
+    }
+    '''),
+  equalsIgnoringWhitespace('''
+    augment class MyClass {
+      augment String myMethod() {
+        print('x: 1, y: 2');
+        print('parentClass: MyClass');
+        print('superClass: MySuperclass');
+        print('interface: MyInterface');
+        print('mixin: MyMixin');
+        print('field: myField');
+        print('method: myMethod');
+        print('constructor: myConstructor');
+        return augment super();
+      }
+    }'''),
+];
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
new file mode 100644
index 0000000..610c83e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
@@ -0,0 +1,402 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. 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:_fe_analyzer_shared/src/macros/api.dart';
+
+/// A very simple macro that augments any declaration it is given, usually
+/// adding print statements and inlining values from the declaration object
+/// for comparision with expected values in tests.
+///
+/// When applied to [MethodDeclaration]s there is some extra work that happens
+/// to validate the introspection APIs work as expected.
+class SimpleMacro
+    implements
+        ClassTypesMacro,
+        ClassDeclarationsMacro,
+        ClassDefinitionMacro,
+        ConstructorTypesMacro,
+        ConstructorDeclarationsMacro,
+        ConstructorDefinitionMacro,
+        FieldTypesMacro,
+        FieldDeclarationsMacro,
+        FieldDefinitionMacro,
+        FunctionTypesMacro,
+        FunctionDeclarationsMacro,
+        FunctionDefinitionMacro,
+        MethodTypesMacro,
+        MethodDeclarationsMacro,
+        MethodDefinitionMacro,
+        VariableTypesMacro,
+        VariableDeclarationsMacro,
+        VariableDefinitionMacro {
+  final int? x;
+  final int? y;
+
+  SimpleMacro([this.x, this.y]);
+
+  SimpleMacro.named({this.x, this.y});
+
+  @override
+  FutureOr<void> buildDeclarationsForClass(
+      ClassDeclaration clazz, ClassMemberDeclarationBuilder builder) async {
+    var fields = await builder.fieldsOf(clazz);
+    builder.declareInClass(DeclarationCode.fromParts([
+      'static const List<String> fieldNames = [',
+      for (var field in fields) "'${field.identifier.name}',",
+      '];',
+    ]));
+  }
+
+  @override
+  FutureOr<void> buildDeclarationsForConstructor(
+      ConstructorDeclaration constructor,
+      ClassMemberDeclarationBuilder builder) {
+    if (constructor.positionalParameters.isNotEmpty ||
+        constructor.namedParameters.isNotEmpty) {
+      throw new UnsupportedError(
+          'Can only run on constructors with no parameters!');
+    }
+    var className = constructor.definingClass.name;
+    var constructorName = constructor.identifier.name;
+    builder.declareInClass(DeclarationCode.fromString(
+        'factory $className.${constructorName}Delegate() => '
+        '$className.$constructorName();'));
+  }
+
+  @override
+  FutureOr<void> buildDeclarationsForFunction(
+      FunctionDeclaration function, DeclarationBuilder builder) {
+    if (!function.isSetter &&
+        (function.positionalParameters.isNotEmpty ||
+            function.namedParameters.isNotEmpty)) {
+      throw new UnsupportedError(
+          'Can only run on functions with no parameters!');
+    }
+    var functionName = function.identifier.name;
+    builder.declareInLibrary(DeclarationCode.fromParts([
+      function.returnType.code,
+      if (function.isGetter) ' get' else if (function.isSetter) ' set ',
+      ' delegate${functionName.capitalize()}',
+      if (!function.isGetter) ...[
+        '(',
+        if (function.isSetter) ...[
+          function.positionalParameters.first.type.code,
+          ' value',
+        ],
+        ')',
+      ],
+      ' => ${functionName}',
+      function.isGetter
+          ? ''
+          : function.isSetter
+              ? ' = value'
+              : '()',
+      ';',
+    ]));
+  }
+
+  @override
+  FutureOr<void> buildDeclarationsForMethod(
+      MethodDeclaration method, ClassMemberDeclarationBuilder builder) {
+    if (method.positionalParameters.isNotEmpty ||
+        method.namedParameters.isNotEmpty) {
+      throw new UnsupportedError('Can only run on method with no parameters!');
+    }
+    var methodName = method.identifier.name;
+    builder.declareInLibrary(DeclarationCode.fromParts([
+      method.returnType.code,
+      ' delegateMember${methodName.capitalize()}() => $methodName();',
+    ]));
+  }
+
+  @override
+  FutureOr<void> buildDeclarationsForVariable(
+      VariableDeclaration variable, DeclarationBuilder builder) {
+    var variableName = variable.identifier.name;
+    builder.declareInLibrary(DeclarationCode.fromParts([
+      variable.type.code,
+      ' get delegate${variableName.capitalize()} => $variableName;',
+    ]));
+  }
+
+  @override
+  FutureOr<void> buildDeclarationsForField(
+      FieldDeclaration field, ClassMemberDeclarationBuilder builder) {
+    var fieldName = field.identifier.name;
+    builder.declareInClass(DeclarationCode.fromParts([
+      field.type.code,
+      ' get delegate${fieldName.capitalize()} => $fieldName;',
+    ]));
+  }
+
+  @override
+  Future<void> buildDefinitionForClass(
+      ClassDeclaration clazz, ClassDefinitionBuilder builder) async {
+    // Apply ourself to all our members
+    var fields = (await builder.fieldsOf(clazz));
+    for (var field in fields) {
+      await buildDefinitionForField(
+          field, await builder.buildField(field.identifier));
+    }
+    var methods = (await builder.methodsOf(clazz));
+    for (var method in methods) {
+      await buildDefinitionForMethod(
+          method, await builder.buildMethod(method.identifier));
+    }
+    var constructors = (await builder.constructorsOf(clazz));
+    for (var constructor in constructors) {
+      await buildDefinitionForConstructor(
+          constructor, await builder.buildConstructor(constructor.identifier));
+    }
+  }
+
+  @override
+  Future<void> buildDefinitionForConstructor(ConstructorDeclaration constructor,
+      ConstructorDefinitionBuilder builder) async {
+    var clazz = await builder.declarationOf(constructor.definingClass)
+        as ClassDeclaration;
+    var fields = (await builder.fieldsOf(clazz));
+
+    builder.augment(
+      body: _buildFunctionAugmentation(constructor),
+      initializers: [
+        for (var field in fields)
+          // TODO: Compare against actual `int` type.
+          if (field.isFinal &&
+              (field.type as NamedTypeAnnotation).identifier.name == 'int')
+            Code.fromParts([field.identifier, ' = ${x!}']),
+      ],
+    );
+  }
+
+  @override
+  Future<void> buildDefinitionForField(
+          FieldDeclaration field, VariableDefinitionBuilder builder) async =>
+      buildDefinitionForVariable(field, builder);
+
+  @override
+  Future<void> buildDefinitionForFunction(
+      FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
+    builder.augment(_buildFunctionAugmentation(function));
+  }
+
+  @override
+  Future<void> buildDefinitionForMethod(
+      MethodDeclaration method, FunctionDefinitionBuilder builder) async {
+    await buildDefinitionForFunction(method, builder);
+
+    // Test the type declaration resolver
+    var parentClass =
+        await builder.declarationOf(method.definingClass) as ClassDeclaration;
+    // Should be able to find ourself in the methods of the parent class.
+    (await builder.methodsOf(parentClass))
+        .singleWhere((m) => m.identifier == method.identifier);
+
+    // Test the class introspector
+    var superClass = (await builder.superclassOf(parentClass))!;
+    var interfaces = (await builder.interfacesOf(parentClass));
+    var mixins = (await builder.mixinsOf(parentClass));
+    var fields = (await builder.fieldsOf(parentClass));
+    var methods = (await builder.methodsOf(parentClass));
+    var constructors = (await builder.constructorsOf(parentClass));
+
+    // Test the type resolver and static type interfaces
+    var staticReturnType = await builder.instantiateType(method.returnType);
+    if (!(await staticReturnType.isExactly(staticReturnType))) {
+      throw StateError('The return type should be exactly equal to itself!');
+    }
+    if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
+      throw StateError('The return type should be a subtype of itself!');
+    }
+
+    // TODO: Use `builder.instantiateCode` instead once implemented.
+    var classType =
+        await builder.instantiateType(constructors.first.returnType);
+    if (await staticReturnType.isExactly(classType)) {
+      throw StateError(
+          'The return type should not be exactly equal to the class type');
+    }
+    if (await staticReturnType.isSubtypeOf(classType)) {
+      throw StateError(
+          'The return type should not be a subtype of the class type!');
+    }
+
+    builder.augment(FunctionBodyCode.fromParts([
+      '''{
+      print('x: $x, y: $y');
+      print('parentClass: ${parentClass.identifier.name}');
+      print('superClass: ${superClass.identifier.name}');''',
+      for (var interface in interfaces)
+        "\n      print('interface: ${interface.identifier.name}');",
+      for (var mixin in mixins)
+        "\n      print('mixin: ${mixin.identifier.name}');",
+      for (var field in fields)
+        "\n      print('field: ${field.identifier.name}');",
+      for (var method in methods)
+        "\n      print('method: ${method.identifier.name}');",
+      for (var constructor in constructors)
+        "\n      print('constructor: ${constructor.identifier.name}');",
+      '''
+\n      return augment super();
+    }''',
+    ]));
+  }
+
+  @override
+  Future<void> buildDefinitionForVariable(
+      VariableDeclaration variable, VariableDefinitionBuilder builder) async {
+    var definingClass =
+        variable is FieldDeclaration ? variable.definingClass.name : '';
+    builder.augment(
+      getter: DeclarationCode.fromParts([
+        variable.type.code,
+        ' get ',
+        variable.identifier.name,
+        ''' {
+          print('parentClass: $definingClass');
+          print('isExternal: ${variable.isExternal}');
+          print('isFinal: ${variable.isFinal}');
+          print('isLate: ${variable.isLate}');
+          return augment super;
+        }''',
+      ]),
+      setter: DeclarationCode.fromParts([
+        'set ',
+        variable.identifier.name,
+        '(',
+        variable.type.code,
+        ' value) { augment super = value; }'
+      ]),
+      initializer: variable.initializer,
+    );
+  }
+
+  @override
+  FutureOr<void> buildTypesForClass(
+      ClassDeclaration clazz, TypeBuilder builder) {
+    List<Object> _buildTypeParam(
+        TypeParameterDeclaration typeParam, bool isFirst) {
+      return [
+        if (!isFirst) ', ',
+        typeParam.identifier.name,
+        if (typeParam.bounds != null) ...[
+          ' extends ',
+          typeParam.bounds!.code,
+        ]
+      ];
+    }
+
+    builder.declareType(DeclarationCode.fromParts([
+      'class ${clazz.identifier.name}Builder',
+      if (clazz.typeParameters.isNotEmpty) ...[
+        '<',
+        ..._buildTypeParam(clazz.typeParameters.first, true),
+        for (var typeParam in clazz.typeParameters.skip(1))
+          ..._buildTypeParam(typeParam, false),
+        '>',
+      ],
+      ' implements Builder<',
+      clazz.identifier,
+      if (clazz.typeParameters.isNotEmpty) ...[
+        '<',
+        clazz.typeParameters.first.identifier.name,
+        for (var typeParam in clazz.typeParameters)
+          ', ${typeParam.identifier.name}',
+        '>',
+      ],
+      '> {}'
+    ]));
+  }
+
+  @override
+  FutureOr<void> buildTypesForConstructor(
+      ConstructorDeclaration constructor, TypeBuilder builder) {
+    builder.declareType(DeclarationCode.fromString(
+        'class GeneratedBy${constructor.identifier.name.capitalize()} {}'));
+  }
+
+  @override
+  FutureOr<void> buildTypesForField(
+      FieldDeclaration field, TypeBuilder builder) {
+    builder.declareType(DeclarationCode.fromString(
+        'class GeneratedBy${field.identifier.name.capitalize()} {}'));
+  }
+
+  @override
+  FutureOr<void> buildTypesForFunction(
+      FunctionDeclaration function, TypeBuilder builder) {
+    var suffix = function.isGetter
+        ? 'Getter'
+        : function.isSetter
+            ? 'Setter'
+            : '';
+    builder.declareType(DeclarationCode.fromString(
+        'class GeneratedBy${function.identifier.name.capitalize()}'
+        '$suffix {}'));
+  }
+
+  @override
+  FutureOr<void> buildTypesForMethod(
+      MethodDeclaration method, TypeBuilder builder) {
+    builder.declareType(DeclarationCode.fromString(
+        'class GeneratedBy${method.identifier.name.capitalize()} {}'));
+  }
+
+  @override
+  FutureOr<void> buildTypesForVariable(
+      VariableDeclaration variable, TypeBuilder builder) {
+    builder.declareType(DeclarationCode.fromString(
+        'class GeneratedBy${variable.identifier.name.capitalize()} {}'));
+  }
+}
+
+FunctionBodyCode _buildFunctionAugmentation(FunctionDeclaration function) =>
+    FunctionBodyCode.fromParts([
+      '{\n',
+      if (function is MethodDeclaration)
+        "print('definingClass: ${function.definingClass.name}');\n",
+      if (function is ConstructorDeclaration)
+        "print('isFactory: ${function.isFactory}');\n",
+      '''
+      print('isAbstract: ${function.isAbstract}');
+      print('isExternal: ${function.isExternal}');
+      print('isGetter: ${function.isGetter}');
+      print('isSetter: ${function.isSetter}');
+      print('returnType: ''',
+      function.returnType.code,
+      "');\n",
+      for (var param in function.positionalParameters) ...[
+        "print('positionalParam: ",
+        param.type.code,
+        ' ${param.identifier.name}',
+        if (param.defaultValue != null) ...[' = ', param.defaultValue!],
+        "');\n",
+      ],
+      for (var param in function.namedParameters) ...[
+        "print('namedParam: ",
+        param.type.code,
+        ' ${param.identifier.name}',
+        if (param.defaultValue != null) ...[' = ', param.defaultValue!],
+        "');\n",
+      ],
+      for (var param in function.typeParameters) ...[
+        "print('typeParam: ${param.identifier.name} ",
+        if (param.bounds != null) param.bounds!.code,
+        "');\n",
+      ],
+      'return augment super',
+      if (function.isSetter) ...[
+        ' = ',
+        function.positionalParameters.first.identifier,
+      ],
+      if (!function.isGetter && !function.isSetter) '()',
+      ''';
+    }''',
+    ]);
+
+extension _ on String {
+  String capitalize() => '${this[0].toUpperCase()}${substring(1)}';
+}
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
new file mode 100644
index 0000000..831a4f8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -0,0 +1,418 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. 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:mirrors';
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+
+import 'package:test/fake.dart';
+import 'package:test/test.dart';
+
+class FakeClassIntrospector extends Fake implements ClassIntrospector {}
+
+class TestClassIntrospector implements ClassIntrospector {
+  final Map<ClassDeclaration, List<ConstructorDeclaration>> constructors;
+  final Map<ClassDeclaration, List<FieldDeclaration>> fields;
+  final Map<ClassDeclaration, List<ClassDeclarationImpl>> interfaces;
+  final Map<ClassDeclaration, List<ClassDeclarationImpl>> mixins;
+  final Map<ClassDeclaration, List<MethodDeclaration>> methods;
+  final Map<ClassDeclaration, ClassDeclaration?> superclass;
+
+  TestClassIntrospector({
+    required this.constructors,
+    required this.fields,
+    required this.interfaces,
+    required this.mixins,
+    required this.methods,
+    required this.superclass,
+  });
+
+  @override
+  Future<List<ConstructorDeclaration>> constructorsOf(
+          covariant ClassDeclaration clazz) async =>
+      constructors[clazz]!;
+
+  @override
+  Future<List<FieldDeclaration>> fieldsOf(
+          covariant ClassDeclaration clazz) async =>
+      fields[clazz]!;
+
+  @override
+  Future<List<ClassDeclaration>> interfacesOf(
+          covariant ClassDeclaration clazz) async =>
+      interfaces[clazz]!;
+
+  @override
+  Future<List<MethodDeclaration>> methodsOf(
+          covariant ClassDeclaration clazz) async =>
+      methods[clazz]!;
+
+  @override
+  Future<List<ClassDeclaration>> mixinsOf(
+          covariant ClassDeclaration clazz) async =>
+      mixins[clazz]!;
+
+  @override
+  Future<ClassDeclaration?> superclassOf(
+          covariant ClassDeclaration clazz) async =>
+      superclass[clazz];
+}
+
+class FakeTypeDeclarationResolver extends Fake
+    implements TypeDeclarationResolver {}
+
+class TestTypeDeclarationResolver implements TypeDeclarationResolver {
+  final Map<Identifier, TypeDeclaration> typeDeclarations;
+
+  TestTypeDeclarationResolver(this.typeDeclarations);
+
+  @override
+  Future<TypeDeclaration> declarationOf(
+          covariant Identifier identifier) async =>
+      typeDeclarations[identifier]!;
+}
+
+class TestTypeResolver implements TypeResolver {
+  final Map<TypeAnnotation, StaticType> staticTypes;
+
+  TestTypeResolver(this.staticTypes);
+
+  @override
+  Future<StaticType> instantiateType(
+      covariant TypeAnnotation typeAnnotation) async {
+    return staticTypes[typeAnnotation]!;
+  }
+
+  @override
+  Future<StaticType> instantiateCode(ExpressionCode code) {
+    // TODO: implement instantiateCode
+    throw UnimplementedError();
+  }
+}
+
+// Doesn't handle generics etc but thats ok for now
+class TestNamedStaticType implements NamedStaticType {
+  final IdentifierImpl identifier;
+  final String library;
+  final List<TestNamedStaticType> superTypes;
+
+  TestNamedStaticType(this.identifier, this.library, this.superTypes);
+
+  @override
+  Future<bool> isExactly(TestNamedStaticType other) async => _isExactly(other);
+
+  @override
+  Future<bool> isSubtypeOf(TestNamedStaticType other) async =>
+      _isExactly(other) ||
+      superTypes.any((superType) => superType._isExactly(other));
+
+  bool _isExactly(TestNamedStaticType other) =>
+      identical(other, this) ||
+      (library == other.library && identifier.name == other.identifier.name);
+}
+
+extension DebugCodeString on Code {
+  StringBuffer debugString([StringBuffer? buffer]) {
+    buffer ??= StringBuffer();
+    for (var part in parts) {
+      if (part is Code) {
+        part.debugString(buffer);
+      } else if (part is IdentifierImpl) {
+        buffer.write(part.name);
+      } else {
+        buffer.write(part as String);
+      }
+    }
+    return buffer;
+  }
+}
+
+/// Checks if two [Code] objectss are of the same type and all their fields are
+/// equal.
+Matcher deepEqualsCode(Code other) => _DeepEqualityMatcher(other);
+
+/// Checks if two [Declaration]s are of the same type and all their fields are
+/// equal.
+Matcher deepEqualsDeclaration(Declaration declaration) =>
+    _DeepEqualityMatcher(declaration);
+
+/// Checks if two [TypeAnnotation]s are of the same type and all their fields
+/// are equal.
+Matcher deepEqualsTypeAnnotation(TypeAnnotation declaration) =>
+    _DeepEqualityMatcher(declaration);
+
+/// Checks if two [Declaration]s, [TypeAnnotation]s, or [Code] objects are of
+/// the same type and all their fields are equal.
+class _DeepEqualityMatcher extends Matcher {
+  final Object? instance;
+
+  _DeepEqualityMatcher(this.instance);
+
+  @override
+  Description describe(Description description) => description;
+
+  @override
+  bool matches(item, Map matchState) {
+    if (item.runtimeType != instance.runtimeType) {
+      return false;
+    }
+
+    if (instance is Declaration || instance is TypeAnnotation) {
+      var instanceReflector = reflect(instance);
+      var itemReflector = reflect(item);
+
+      var type = instanceReflector.type;
+      for (var getter
+          in type.instanceMembers.values.where((member) => member.isGetter)) {
+        // We only care about synthetic field getters
+        if (!getter.isSynthetic) continue;
+
+        var instanceField = instanceReflector.getField(getter.simpleName);
+        var itemField = itemReflector.getField(getter.simpleName);
+        var instanceValue = instanceField.reflectee;
+        var itemValue = itemField.reflectee;
+
+        // Handle lists of things
+        if (instanceValue is List) {
+          if (!_listEquals(instanceValue, itemValue, matchState)) {
+            return false;
+          }
+        } else if (instanceValue is Declaration ||
+            instanceValue is Code ||
+            instanceValue is TypeAnnotation) {
+          // Handle nested declarations and code objects
+          if (!_DeepEqualityMatcher(instanceValue)
+              .matches(itemValue, matchState)) {
+            return false;
+          }
+        } else {
+          // Handles basic values and identity
+          if (instanceValue != itemValue) {
+            return false;
+          }
+        }
+      }
+    } else if (instance is Code) {
+      if (!_listEquals(
+          (instance as Code).parts, (item as Code).parts, matchState)) {
+        return false;
+      }
+    } else {
+      // Handles basic values and identity
+      if (instance != item) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool _listEquals(List instanceValue, List itemValue, Map matchState) {
+    if (instanceValue.length != itemValue.length) {
+      return false;
+    }
+    for (var i = 0; i < instanceValue.length; i++) {
+      if (!_DeepEqualityMatcher(instanceValue[i])
+          .matches(itemValue[i], matchState)) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
+
+class Fixtures {
+  static final stringType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'String'),
+      isNullable: false,
+      typeArguments: const []);
+  static final voidType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'void'),
+      isNullable: false,
+      typeArguments: const []);
+
+  // Top level, non-class declarations.
+  static final myFunction = FunctionDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myFunction'),
+      isAbstract: false,
+      isExternal: false,
+      isGetter: false,
+      isSetter: false,
+      namedParameters: [],
+      positionalParameters: [],
+      returnType: stringType,
+      typeParameters: []);
+  static final myVariable = VariableDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: '_myVariable'),
+      initializer: ExpressionCode.fromString("''"),
+      isExternal: false,
+      isFinal: true,
+      isLate: false,
+      type: stringType);
+  static final myVariableGetter = FunctionDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myVariable'),
+      isAbstract: false,
+      isExternal: false,
+      isGetter: true,
+      isSetter: false,
+      namedParameters: [],
+      positionalParameters: [],
+      returnType: stringType,
+      typeParameters: []);
+  static final myVariableSetter = FunctionDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myVariable'),
+      isAbstract: false,
+      isExternal: false,
+      isGetter: false,
+      isSetter: true,
+      namedParameters: [],
+      positionalParameters: [
+        ParameterDeclarationImpl(
+            id: RemoteInstance.uniqueId,
+            identifier:
+                IdentifierImpl(id: RemoteInstance.uniqueId, name: 'value'),
+            defaultValue: null,
+            isNamed: false,
+            isRequired: true,
+            type: stringType)
+      ],
+      returnType: voidType,
+      typeParameters: []);
+
+  // Class and member declarations
+  static final myInterfaceType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyInterface'),
+      isNullable: false,
+      typeArguments: const []);
+  static final myMixinType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyMixin'),
+      isNullable: false,
+      typeArguments: const []);
+  static final mySuperclassType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MySuperclass'),
+      isNullable: false,
+      typeArguments: const []);
+  static final myClassType = NamedTypeAnnotationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'MyClass'),
+      isNullable: false,
+      typeArguments: const []);
+  static final myClass = ClassDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: myClassType.identifier,
+      typeParameters: [],
+      interfaces: [myInterfaceType],
+      isAbstract: false,
+      isExternal: false,
+      mixins: [myMixinType],
+      superclass: mySuperclassType);
+  static final myConstructor = ConstructorDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier:
+          IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myConstructor'),
+      isAbstract: false,
+      isExternal: false,
+      isGetter: false,
+      isSetter: false,
+      namedParameters: [],
+      positionalParameters: [],
+      returnType: myClassType,
+      typeParameters: [],
+      definingClass: myClassType.identifier,
+      isFactory: false);
+  static final myField = FieldDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
+      initializer: null,
+      isExternal: false,
+      isFinal: false,
+      isLate: false,
+      type: stringType,
+      definingClass: myClassType.identifier);
+  static final myInterface = ClassDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: myInterfaceType.identifier,
+      typeParameters: [],
+      interfaces: [],
+      isAbstract: false,
+      isExternal: false,
+      mixins: [],
+      superclass: null);
+  static final myMethod = MethodDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myMethod'),
+      isAbstract: false,
+      isExternal: false,
+      isGetter: false,
+      isSetter: false,
+      namedParameters: [],
+      positionalParameters: [],
+      returnType: stringType,
+      typeParameters: [],
+      definingClass: myClassType.identifier);
+  static final myMixin = ClassDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: myMixinType.identifier,
+      typeParameters: [],
+      interfaces: [],
+      isAbstract: false,
+      isExternal: false,
+      mixins: [],
+      superclass: null);
+  static final mySuperclass = ClassDeclarationImpl(
+      id: RemoteInstance.uniqueId,
+      identifier: mySuperclassType.identifier,
+      typeParameters: [],
+      interfaces: [],
+      isAbstract: false,
+      isExternal: false,
+      mixins: [],
+      superclass: null);
+
+  static final myClassStaticType = TestNamedStaticType(
+      myClassType.identifier, 'package:my_package/my_package.dart', []);
+
+  static final testTypeResolver = TestTypeResolver({
+    stringType: TestNamedStaticType(stringType.identifier, 'dart:core', []),
+    myClassType: myClassStaticType,
+  });
+  static final testClassIntrospector = TestClassIntrospector(
+    constructors: {
+      myClass: [myConstructor],
+    },
+    fields: {
+      myClass: [myField],
+    },
+    interfaces: {
+      myClass: [myInterface],
+    },
+    methods: {
+      myClass: [myMethod],
+    },
+    mixins: {
+      myClass: [myMixin],
+    },
+    superclass: {
+      myClass: mySuperclass,
+    },
+  );
+  static final testTypeDeclarationResolver =
+      TestTypeDeclarationResolver({myClass.identifier: myClass});
+}
diff --git a/pkg/_fe_analyzer_shared/test/mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart
index 85ae066..0c71378 100644
--- a/pkg/_fe_analyzer_shared/test/mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart
@@ -963,6 +963,7 @@
 
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    assignedVariables.declare(variable);
     initializer?._preVisit(assignedVariables);
   }
 
diff --git a/pkg/_fe_analyzer_shared/test/util/libraries_specification_test.dart b/pkg/_fe_analyzer_shared/test/util/libraries_specification_test.dart
index 10f9717..990f989c 100644
--- a/pkg/_fe_analyzer_shared/test/util/libraries_specification_test.dart
+++ b/pkg/_fe_analyzer_shared/test/util/libraries_specification_test.dart
@@ -5,56 +5,102 @@
 import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart';
 import 'package:test/test.dart';
 
+bool Function(dynamic) checkException(String expectedMessage) {
+  return (exception) {
+    print(exception);
+    if (exception is LibrariesSpecificationException) {
+      expect(exception.error, expectedMessage);
+      return true;
+    }
+    return false;
+  };
+}
+
 void main() {
+  String notFoundMessage = 'File not found';
+
+  Uri specUri = Uri.parse('org-dartlang-test:///f.json');
+
+  Future<String> Function(Uri) read(Map<Uri, String> map) {
+    return (Uri uri) async {
+      String? jsonString = map[uri];
+      if (jsonString == null) {
+        throw notFoundMessage;
+      }
+      return jsonString;
+    };
+  }
+
   group('parse', () {
     test('top-level must be a map', () async {
       var jsonString = '[]';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageTopLevelIsNotAMap(specUri))));
       jsonString = '""';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageTopLevelIsNotAMap(specUri))));
     });
 
     test('target entry must be a map', () async {
       var jsonString = '{"vm" : []}';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageTargetIsNotAMap('vm', specUri))));
       jsonString = '{"vm" : ""}';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageTargetIsNotAMap('vm', specUri))));
     });
 
     test('library entry must exist', () async {
       var jsonString = '{"vm" : {}}';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageTargetLibrariesMissing('vm', specUri))));
     });
 
     test('library entry must be a map', () async {
       var jsonString = '{"vm" : {"libraries": []}}';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageLibrariesEntryIsNotAMap('vm', specUri))));
+    });
+
+    test('library data must be a map', () async {
+      var jsonString = '{"vm" : {"libraries": { "foo": [] }}}';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageLibraryDataIsNotAMap('foo', 'vm', specUri))));
+    });
+
+    test('library uri must be supplied', () async {
+      var jsonString = '{"vm" : {"libraries": {"core": {}}}}';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageLibraryUriMissing('core', 'vm', specUri))));
     });
 
     test('uri must be a string', () async {
-      var jsonString = '{"vm" : {"libraries": {"core": {"uri": 3}}}';
+      var jsonString = '{"vm" : {"libraries": {"core": {"uri": 3}}}}';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageLibraryUriIsNotAString(3, 'core', 'vm', specUri))));
     });
 
     test('patches must be a string or list of string', () async {
@@ -71,9 +117,9 @@
       }
       ''';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messagePatchesMustBeListOrString('c'))));
 
       jsonString = '''
       { 
@@ -87,8 +133,8 @@
         }
       }
       ''';
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///f.json'), jsonString);
+      var spec = await LibrariesSpecification.load(
+          specUri, read({specUri: jsonString}));
       expect(spec.specificationFor("none").libraryInfoFor("c")!.patches.first,
           Uri.parse('org-dartlang-test:///a.dart'));
 
@@ -104,8 +150,8 @@
         }
       }
       ''';
-      spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///f.json'), jsonString);
+      spec = await LibrariesSpecification.load(
+          specUri, read({specUri: jsonString}));
       expect(spec.specificationFor("none").libraryInfoFor("c")!.patches.first,
           Uri.parse('org-dartlang-test:///a.dart'));
     });
@@ -114,8 +160,9 @@
       var jsonString = '''
       { "none": { "libraries": {"c" : { "uri": "c/main.dart" }}}}
       ''';
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       expect(spec, isNotNull);
       expect(
           spec.specificationFor('none').libraryInfoFor('c')!.patches, isEmpty);
@@ -125,9 +172,9 @@
       var jsonString = '''
       { "none": { "libraries": {"c" : { "uri": "c/main.dart" }}}}
       ''';
-
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       expect(spec.specificationFor('none').libraryInfoFor('c')!.uri,
           Uri.parse('org-dartlang-test:///one/two/c/main.dart'));
     });
@@ -148,9 +195,9 @@
         }
       }
       ''';
-
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       expect(spec.specificationFor('none').libraryInfoFor('c')!.patches[0],
           Uri.parse('org-dartlang-test:///one/a/p1.dart'));
       expect(spec.specificationFor('none').libraryInfoFor('c')!.patches[1],
@@ -186,9 +233,9 @@
         }
       }
       ''';
-
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
 
       expect(spec.specificationFor('vm').libraryInfoFor('foo')!.uri,
           Uri.parse('org-dartlang-test:///one/two/a/main.dart'));
@@ -199,12 +246,23 @@
     });
 
     test('supported entry must be bool', () async {
-      var jsonString = '{"vm" : {"libraries": {"core": '
-          '{"uri": "main.dart", "supported": 3}},';
+      var jsonString = '''
+      {
+        "vm": 
+        {
+          "libraries": 
+          {
+            "core": {
+              "uri": "main.dart", 
+              "supported": 3
+            }
+          }
+        }
+      }''';
       expect(
-          () => LibrariesSpecification.parse(
-              Uri.parse('org-dartlang-test:///f.json'), jsonString),
-          throwsA((e) => e is LibrariesSpecificationException));
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageSupportedIsNotABool(3))));
     });
 
     test('supported entry is copied correctly when parsing', () async {
@@ -238,8 +296,9 @@
         }
       }
       ''';
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       expect(spec.specificationFor('vm').libraryInfoFor('foo')!.isSupported,
           false);
       expect(
@@ -249,6 +308,399 @@
     });
   });
 
+  group('nested', () {
+    test('include must be a list', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": "", 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageIncludeIsNotAList('target', specUri))));
+    });
+
+    test('include entry must be a map', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [""], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageIncludeEntryIsNotAMap('target', specUri))));
+    });
+
+    test('include entry must have a target string', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageIncludeTargetMissing('target', specUri))));
+
+      jsonString = '''
+      {
+        "target": {
+          "include": [{"path": "dummy"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageIncludeTargetMissing('target', specUri))));
+
+      jsonString = '''
+      {
+        "target": {
+          "include": [{"path": 0, "target": 0}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageIncludeTargetIsNotAString('target', specUri))));
+    });
+
+    test('include entry path must be a string', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{"path": 0, "target": "dummy"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageIncludePathIsNotAString('target', specUri))));
+
+      jsonString = '''
+      {
+        "target": {
+          "include": [{"path": "dummy", "target": 0}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageIncludeTargetIsNotAString('target', specUri))));
+    });
+
+    test('include entry path scheme can only be file', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{"path": "http://foo.dart", "target": "none"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageUnsupportedUriScheme("http://foo.dart", specUri))));
+    });
+
+    test('include entry must be a existing path and target', () async {
+      var otherFile = 'g.json';
+      var otherUri = specUri.resolve(otherFile);
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{"path": "$otherFile", "target": "none"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(
+              messageIncludePathCouldNotBeRead(otherUri, notFoundMessage))));
+
+      var otherJsonString = '''
+      {
+        "target": {
+          "libraries": {}
+        }
+      }''';
+      expect(
+          () => LibrariesSpecification.load(
+              specUri, read({specUri: jsonString, otherUri: otherJsonString})),
+          throwsA(checkException(messageMissingTarget('none', otherUri))));
+    });
+
+    test('internal include target must exist', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{"target": "none"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageMissingTarget('none', specUri))));
+    });
+
+    test('include entry cannot be cyclic', () async {
+      var thisFile = 'f.json';
+      var thisUri = specUri.resolve(thisFile);
+      var otherFile = 'g.json';
+      var otherUri = thisUri.resolve(otherFile);
+      var thisJsonString = '''
+      {
+        "target": {
+          "include": [{"path": "$thisFile", "target": "target"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () => LibrariesSpecification.load(
+              thisUri, read({thisUri: thisJsonString})),
+          throwsA(checkException(messageCyclicSpec(thisUri))));
+
+      thisJsonString = '''
+      {
+        "target": {
+          "include": [{"path": "$otherFile", "target": "none"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      var otherJsonString = '''
+      {
+        "none": {
+          "include": [{"path": "$thisFile", "target": "target"}],
+          "libraries": {}
+        }
+      }''';
+      expect(
+          () => LibrariesSpecification.load(thisUri,
+              read({thisUri: thisJsonString, otherUri: otherJsonString})),
+          throwsA(checkException(messageCyclicSpec(thisUri))));
+    });
+
+    test('include entry cannot be cyclic internally', () async {
+      var jsonString = '''
+      {
+        "target": {
+          "include": [{"target": "target"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(
+              checkException(messageCyclicInternalInclude('target', specUri))));
+
+      jsonString = '''
+      {
+        "a": {
+          "include": [{"target": "b"}], 
+          "libraries": {}
+        },
+        "b": {
+          "include": [{"target": "a"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      expect(
+          () =>
+              LibrariesSpecification.load(specUri, read({specUri: jsonString})),
+          throwsA(checkException(messageCyclicInternalInclude('a', specUri))));
+    });
+
+    test('include works transitively', () async {
+      var thisFile = 'f.json';
+      var thisUri = specUri.resolve(thisFile);
+      var otherFile1 = 'g.json';
+      var otherUri1 = thisUri.resolve(otherFile1);
+      var otherFile2 = 'subfolder/h.json';
+      var otherUri2 = thisUri.resolve(otherFile2);
+      var otherFile3 = '../i.json';
+      var otherUri3 = otherUri2.resolve(otherFile3);
+      var thisJsonString = '''
+      {
+        "foo": {
+          "include": [
+            {
+              "path": "$otherFile1", 
+              "target": "foo"
+            },
+            {
+              "path": "$otherFile2", 
+              "target": "foo"
+            }
+          ], 
+          "libraries": {}
+        },
+        "bar": {
+          "include": [{"path": "$otherFile2", "target": "bar"}], 
+          "libraries": {}
+        }
+      }
+      ''';
+      var otherJsonString1 = '''
+      {
+        "foo": {
+          "libraries": {
+            "foo": {
+              "uri": "foo.dart"
+            }
+          }
+        }
+      }''';
+      var otherJsonString2 = '''
+      {
+        "foo": {
+          "libraries": {
+            "foo_extra": {
+              "uri": "foo_extra.dart"
+            }
+          }
+        },
+        "bar": {
+          "include": [{"path": "$otherFile3", "target": "baz"}],
+          "libraries": {
+            "bar": {
+              "uri": "bar/baz.dart"
+            }
+          }
+        }
+      }''';
+      var otherJsonString3 = '''
+      {
+        "baz": {
+          "libraries": {
+            "baz": {
+              "uri": "bar/baz.dart"
+            }
+          }
+        }
+      }''';
+      var spec = await LibrariesSpecification.load(
+          thisUri,
+          read({
+            thisUri: thisJsonString,
+            otherUri1: otherJsonString1,
+            otherUri2: otherJsonString2,
+            otherUri3: otherJsonString3,
+          }));
+
+      expect(spec.specificationFor('foo').libraryInfoFor('foo')!.uri,
+          otherUri1.resolve('foo.dart'));
+      expect(spec.specificationFor('foo').libraryInfoFor('foo_extra')!.uri,
+          otherUri2.resolve('foo_extra.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('bar')!.uri,
+          otherUri2.resolve('bar/baz.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('baz')!.uri,
+          otherUri3.resolve('bar/baz.dart'));
+    });
+
+    test('internal include works transitively', () async {
+      var jsonString = '''
+      {
+        "foo": {
+          "include": [{"target": "common"}], 
+          "libraries": {
+            "foo": {
+              "uri": "foo.dart"
+            }
+          }
+        },
+        "bar": {
+          "include": [
+            {
+               "target": "common"
+            }, 
+            {
+               "target": "baz"
+            }
+          ], 
+          "libraries": {
+            "bar": {
+              "uri": "bar.dart"
+            }
+          }
+        },
+        "common": {
+          "libraries": {
+            "common": {
+              "uri": "common.dart"
+            }
+          }
+        },
+        "baz": {
+          "include": [{"target": "boz"}],
+          "libraries": {
+            "baz": {
+              "uri": "bar/baz.dart"
+            }
+          }
+        },
+        "boz": {
+          "libraries": {
+            "boz": {
+              "uri": "bar/boz.dart"
+            }
+          }
+        }        
+      }
+      ''';
+      var spec = await LibrariesSpecification.load(
+          specUri, read({specUri: jsonString}));
+
+      expect(spec.specificationFor('foo').libraryInfoFor('foo')!.uri,
+          specUri.resolve('foo.dart'));
+      expect(spec.specificationFor('foo').libraryInfoFor('common')!.uri,
+          specUri.resolve('common.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('bar')!.uri,
+          specUri.resolve('bar.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('common')!.uri,
+          specUri.resolve('common.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('baz')!.uri,
+          specUri.resolve('bar/baz.dart'));
+      expect(spec.specificationFor('bar').libraryInfoFor('boz')!.uri,
+          specUri.resolve('bar/boz.dart'));
+    });
+  });
+
   group('toJson', () {
     test('serialization produces same data that was parsed', () async {
       var jsonString = '''
@@ -282,11 +734,12 @@
       }
       ''';
 
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       var newJson =
           spec.toJsonString(Uri.parse('org-dartlang-test:///one/two/g.json'));
-      expect(jsonString.replaceAll(new RegExp('\\s'), ''), newJson);
+      expect(newJson, jsonString.replaceAll(new RegExp('\\s'), ''));
     });
 
     test('serialization can adapt to new file location', () async {
@@ -319,8 +772,9 @@
       }
       ''';
 
-      var spec = LibrariesSpecification.parse(
-          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var spec =
+          await LibrariesSpecification.load(uri, read({uri: jsonString}));
       var newJson =
           spec.toJsonString(Uri.parse('org-dartlang-test:///one/g.json'));
 
@@ -354,7 +808,71 @@
       }
       ''';
 
-      expect(expected.replaceAll(new RegExp('\\s'), ''), newJson);
+      expect(newJson, expected.replaceAll(new RegExp('\\s'), ''));
+    });
+
+    test('serialization of nested specs inlines data', () async {
+      var jsonString = '''
+      {
+        "vm": {
+          "include": [
+            {
+              "path": "g.json",
+              "target": "vm"
+            }
+          ],
+          "libraries": {
+            "foo" : {
+              "uri": "a/main.dart"
+            }
+          }
+        }
+      }
+      ''';
+      var otherJsonString = '''
+      {
+        "vm": {
+          "libraries": {
+            "bar" : {
+              "uri": "b/main.dart"
+            }
+          }
+        },
+        "unused": {
+          "libraries": {
+            "foo" : {
+              "uri": "c/main.dart"
+            }
+          }
+        }
+      }
+      ''';
+
+      var uri = Uri.parse('org-dartlang-test:///one/two/f.json');
+      var otherUri = Uri.parse('org-dartlang-test:///one/two/g.json');
+      var spec = await LibrariesSpecification.load(
+          uri, read({uri: jsonString, otherUri: otherJsonString}));
+      var newJson =
+          spec.toJsonString(Uri.parse('org-dartlang-test:///one/two/h.json'));
+      expect(
+          newJson,
+          '''
+      {
+        "vm": {
+          "libraries": {
+            "bar" : {
+              "uri": "b/main.dart",
+              "patches": []
+            },
+            "foo" : {
+              "uri": "a/main.dart",
+              "patches": []
+            }
+          }
+        }
+      }      
+      '''
+              .replaceAll(new RegExp('\\s'), ''));
     });
   });
 }
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 1bb0ba8..560c08b 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.32.8
+  1.32.9
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -3117,6 +3117,7 @@
   
   
   
+  
 <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
@@ -3484,7 +3485,23 @@
       An identifier used to associate completion results with a
       completion request.
     </p>
-  </dd><dt class="typeDefinition"><a name="type_CompletionService">CompletionService: String</a></dt><dd>
+  </dd><dt class="typeDefinition"><a name="type_CompletionMode">CompletionMode: String</a></dt><dd>
+    <p>
+      An enumeration of the kinds of code completion that users can invoke.
+    </p>
+    
+  <dl><dt class="value">BASIC</dt><dd>
+        
+        <p>
+          Basic code completion invocation type, and the default for this
+          enumeration.
+        </p>
+      </dd><dt class="value">SMART</dt><dd>
+        
+        <p>
+          Smart code completion, currently not implemented.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionService">CompletionService: String</a></dt><dd>
     <p>
       An enumeration of the completion services to which a client can subscribe.
     </p>
@@ -4375,7 +4392,7 @@
   <dl><dt class="value">ANNOTATION</dt><dt class="value">BUILT_IN</dt><dt class="value">CLASS</dt><dt class="value">COMMENT_BLOCK</dt><dt class="value">COMMENT_DOCUMENTATION</dt><dt class="value">COMMENT_END_OF_LINE</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_TEAR_OFF</dt><dt class="value">DIRECTIVE</dt><dt class="value">DYNAMIC_TYPE</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
-      </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">FIELD</dt><dd>
+      </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
       </dd><dt class="value">FIELD_STATIC</dt><dd>
@@ -6098,7 +6115,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><li><a href="#request_server.cancelRequest">cancelRequest</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.log">log</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getPostfixCompletion">getPostfixCompletion</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><h4>flutter (<a href="#domain_flutter">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_flutter.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_flutter.outline">outline</a></li></ul></div></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_BulkFix">BulkFix</a></li><li><a href="#type_BulkFixDetail">BulkFixDetail</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FlutterOutline">FlutterOutline</a></li><li><a href="#type_FlutterOutlineAttribute">FlutterOutlineAttribute</a></li><li><a href="#type_FlutterOutlineKind">FlutterOutlineKind</a></li><li><a href="#type_FlutterService">FlutterService</a></li><li><a href="#type_FlutterWidgetProperty">FlutterWidgetProperty</a></li><li><a href="#type_FlutterWidgetPropertyEditor">FlutterWidgetPropertyEditor</a></li><li><a href="#type_FlutterWidgetPropertyEditorKind">FlutterWidgetPropertyEditorKind</a></li><li><a href="#type_FlutterWidgetPropertyValue">FlutterWidgetPropertyValue</a></li><li><a href="#type_FlutterWidgetPropertyValueEnumItem">FlutterWidgetPropertyValueEnumItem</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<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><li><a href="#request_server.cancelRequest">cancelRequest</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.log">log</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getPostfixCompletion">getPostfixCompletion</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><h4>flutter (<a href="#domain_flutter">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_flutter.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_flutter.outline">outline</a></li></ul></div></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_BulkFix">BulkFix</a></li><li><a href="#type_BulkFixDetail">BulkFixDetail</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_CompletionMode">CompletionMode</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FlutterOutline">FlutterOutline</a></li><li><a href="#type_FlutterOutlineAttribute">FlutterOutlineAttribute</a></li><li><a href="#type_FlutterOutlineKind">FlutterOutlineKind</a></li><li><a href="#type_FlutterService">FlutterService</a></li><li><a href="#type_FlutterWidgetProperty">FlutterWidgetProperty</a></li><li><a href="#type_FlutterWidgetPropertyEditor">FlutterWidgetPropertyEditor</a></li><li><a href="#type_FlutterWidgetPropertyEditorKind">FlutterWidgetPropertyEditorKind</a></li><li><a href="#type_FlutterWidgetPropertyValue">FlutterWidgetPropertyValue</a></li><li><a href="#type_FlutterWidgetPropertyValueEnumItem">FlutterWidgetPropertyValueEnumItem</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index 5c222c3..7d095d7 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -169,29 +169,167 @@
       CompletionItemResolutionInfo.canParse,
       CompletionItemResolutionInfo.fromJson);
 
-  CompletionItemResolutionInfo({required this.file, required this.offset});
   static CompletionItemResolutionInfo fromJson(Map<String, Object?> json) {
-    if (DartCompletionItemResolutionInfo.canParse(json, nullLspJsonReporter)) {
-      return DartCompletionItemResolutionInfo.fromJson(json);
+    if (DartSuggestionSetCompletionItemResolutionInfo.canParse(
+        json, nullLspJsonReporter)) {
+      return DartSuggestionSetCompletionItemResolutionInfo.fromJson(json);
     }
     if (PubPackageCompletionItemResolutionInfo.canParse(
         json, nullLspJsonReporter)) {
       return PubPackageCompletionItemResolutionInfo.fromJson(json);
     }
+    return CompletionItemResolutionInfo();
+  }
+
+  Map<String, Object?> toJson() {
+    var __result = <String, Object?>{};
+    return __result;
+  }
+
+  static bool canParse(Object? obj, LspJsonReporter reporter) {
+    if (obj is Map<String, Object?>) {
+      return true;
+    } else {
+      reporter.reportError('must be of type CompletionItemResolutionInfo');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CompletionItemResolutionInfo &&
+        other.runtimeType == CompletionItemResolutionInfo) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => 42;
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class DartDiagnosticServer implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      DartDiagnosticServer.canParse, DartDiagnosticServer.fromJson);
+
+  DartDiagnosticServer({required this.port});
+  static DartDiagnosticServer fromJson(Map<String, Object?> json) {
+    final portJson = json['port'];
+    final port = portJson as int;
+    return DartDiagnosticServer(port: port);
+  }
+
+  final int port;
+
+  Map<String, Object?> toJson() {
+    var __result = <String, Object?>{};
+    __result['port'] = port;
+    return __result;
+  }
+
+  static bool canParse(Object? obj, LspJsonReporter reporter) {
+    if (obj is Map<String, Object?>) {
+      reporter.push('port');
+      try {
+        if (!obj.containsKey('port')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        final port = obj['port'];
+        if (port == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(port is int)) {
+          reporter.reportError('must be of type int');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type DartDiagnosticServer');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is DartDiagnosticServer &&
+        other.runtimeType == DartDiagnosticServer) {
+      return port == other.port && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => port.hashCode;
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class DartSuggestionSetCompletionItemResolutionInfo
+    implements CompletionItemResolutionInfo, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      DartSuggestionSetCompletionItemResolutionInfo.canParse,
+      DartSuggestionSetCompletionItemResolutionInfo.fromJson);
+
+  DartSuggestionSetCompletionItemResolutionInfo(
+      {required this.file,
+      required this.offset,
+      required this.libId,
+      required this.displayUri,
+      required this.rOffset,
+      required this.iLength,
+      required this.rLength});
+  static DartSuggestionSetCompletionItemResolutionInfo fromJson(
+      Map<String, Object?> json) {
     final fileJson = json['file'];
     final file = fileJson as String;
     final offsetJson = json['offset'];
     final offset = offsetJson as int;
-    return CompletionItemResolutionInfo(file: file, offset: offset);
+    final libIdJson = json['libId'];
+    final libId = libIdJson as int;
+    final displayUriJson = json['displayUri'];
+    final displayUri = displayUriJson as String;
+    final rOffsetJson = json['rOffset'];
+    final rOffset = rOffsetJson as int;
+    final iLengthJson = json['iLength'];
+    final iLength = iLengthJson as int;
+    final rLengthJson = json['rLength'];
+    final rLength = rLengthJson as int;
+    return DartSuggestionSetCompletionItemResolutionInfo(
+        file: file,
+        offset: offset,
+        libId: libId,
+        displayUri: displayUri,
+        rOffset: rOffset,
+        iLength: iLength,
+        rLength: rLength);
   }
 
+  final String displayUri;
   final String file;
+  final int iLength;
+  final int libId;
   final int offset;
+  final int rLength;
+  final int rOffset;
 
   Map<String, Object?> toJson() {
     var __result = <String, Object?>{};
     __result['file'] = file;
     __result['offset'] = offset;
+    __result['libId'] = libId;
+    __result['displayUri'] = displayUri;
+    __result['rOffset'] = rOffset;
+    __result['iLength'] = iLength;
+    __result['rLength'] = rLength;
     return __result;
   }
 
@@ -233,90 +371,6 @@
       } finally {
         reporter.pop();
       }
-      return true;
-    } else {
-      reporter.reportError('must be of type CompletionItemResolutionInfo');
-      return false;
-    }
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (other is CompletionItemResolutionInfo &&
-        other.runtimeType == CompletionItemResolutionInfo) {
-      return file == other.file && offset == other.offset && true;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode => Object.hash(file, offset);
-
-  @override
-  String toString() => jsonEncoder.convert(toJson());
-}
-
-class DartCompletionItemResolutionInfo
-    implements CompletionItemResolutionInfo, ToJsonable {
-  static const jsonHandler = LspJsonHandler(
-      DartCompletionItemResolutionInfo.canParse,
-      DartCompletionItemResolutionInfo.fromJson);
-
-  DartCompletionItemResolutionInfo(
-      {required this.libId,
-      required this.displayUri,
-      required this.rOffset,
-      required this.iLength,
-      required this.rLength,
-      required this.file,
-      required this.offset});
-  static DartCompletionItemResolutionInfo fromJson(Map<String, Object?> json) {
-    final libIdJson = json['libId'];
-    final libId = libIdJson as int;
-    final displayUriJson = json['displayUri'];
-    final displayUri = displayUriJson as String;
-    final rOffsetJson = json['rOffset'];
-    final rOffset = rOffsetJson as int;
-    final iLengthJson = json['iLength'];
-    final iLength = iLengthJson as int;
-    final rLengthJson = json['rLength'];
-    final rLength = rLengthJson as int;
-    final fileJson = json['file'];
-    final file = fileJson as String;
-    final offsetJson = json['offset'];
-    final offset = offsetJson as int;
-    return DartCompletionItemResolutionInfo(
-        libId: libId,
-        displayUri: displayUri,
-        rOffset: rOffset,
-        iLength: iLength,
-        rLength: rLength,
-        file: file,
-        offset: offset);
-  }
-
-  final String displayUri;
-  final String file;
-  final int iLength;
-  final int libId;
-  final int offset;
-  final int rLength;
-  final int rOffset;
-
-  Map<String, Object?> toJson() {
-    var __result = <String, Object?>{};
-    __result['libId'] = libId;
-    __result['displayUri'] = displayUri;
-    __result['rOffset'] = rOffset;
-    __result['iLength'] = iLength;
-    __result['rLength'] = rLength;
-    __result['file'] = file;
-    __result['offset'] = offset;
-    return __result;
-  }
-
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    if (obj is Map<String, Object?>) {
       reporter.push('libId');
       try {
         if (!obj.containsKey('libId')) {
@@ -407,60 +461,25 @@
       } finally {
         reporter.pop();
       }
-      reporter.push('file');
-      try {
-        if (!obj.containsKey('file')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final file = obj['file'];
-        if (file == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!(file is String)) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      reporter.push('offset');
-      try {
-        if (!obj.containsKey('offset')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final offset = obj['offset'];
-        if (offset == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!(offset is int)) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
       return true;
     } else {
-      reporter.reportError('must be of type DartCompletionItemResolutionInfo');
+      reporter.reportError(
+          'must be of type DartSuggestionSetCompletionItemResolutionInfo');
       return false;
     }
   }
 
   @override
   bool operator ==(Object other) {
-    if (other is DartCompletionItemResolutionInfo &&
-        other.runtimeType == DartCompletionItemResolutionInfo) {
-      return libId == other.libId &&
+    if (other is DartSuggestionSetCompletionItemResolutionInfo &&
+        other.runtimeType == DartSuggestionSetCompletionItemResolutionInfo) {
+      return file == other.file &&
+          offset == other.offset &&
+          libId == other.libId &&
           displayUri == other.displayUri &&
           rOffset == other.rOffset &&
           iLength == other.iLength &&
           rLength == other.rLength &&
-          file == other.file &&
-          offset == other.offset &&
           true;
     }
     return false;
@@ -468,69 +487,7 @@
 
   @override
   int get hashCode =>
-      Object.hash(libId, displayUri, rOffset, iLength, rLength, file, offset);
-
-  @override
-  String toString() => jsonEncoder.convert(toJson());
-}
-
-class DartDiagnosticServer implements ToJsonable {
-  static const jsonHandler = LspJsonHandler(
-      DartDiagnosticServer.canParse, DartDiagnosticServer.fromJson);
-
-  DartDiagnosticServer({required this.port});
-  static DartDiagnosticServer fromJson(Map<String, Object?> json) {
-    final portJson = json['port'];
-    final port = portJson as int;
-    return DartDiagnosticServer(port: port);
-  }
-
-  final int port;
-
-  Map<String, Object?> toJson() {
-    var __result = <String, Object?>{};
-    __result['port'] = port;
-    return __result;
-  }
-
-  static bool canParse(Object? obj, LspJsonReporter reporter) {
-    if (obj is Map<String, Object?>) {
-      reporter.push('port');
-      try {
-        if (!obj.containsKey('port')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final port = obj['port'];
-        if (port == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!(port is int)) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      return true;
-    } else {
-      reporter.reportError('must be of type DartDiagnosticServer');
-      return false;
-    }
-  }
-
-  @override
-  bool operator ==(Object other) {
-    if (other is DartDiagnosticServer &&
-        other.runtimeType == DartDiagnosticServer) {
-      return port == other.port && true;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode => port.hashCode;
+      Object.hash(file, offset, libId, displayUri, rOffset, iLength, rLength);
 
   @override
   String toString() => jsonEncoder.convert(toJson());
@@ -1211,29 +1168,19 @@
       PubPackageCompletionItemResolutionInfo.canParse,
       PubPackageCompletionItemResolutionInfo.fromJson);
 
-  PubPackageCompletionItemResolutionInfo(
-      {required this.packageName, required this.file, required this.offset});
+  PubPackageCompletionItemResolutionInfo({required this.packageName});
   static PubPackageCompletionItemResolutionInfo fromJson(
       Map<String, Object?> json) {
     final packageNameJson = json['packageName'];
     final packageName = packageNameJson as String;
-    final fileJson = json['file'];
-    final file = fileJson as String;
-    final offsetJson = json['offset'];
-    final offset = offsetJson as int;
-    return PubPackageCompletionItemResolutionInfo(
-        packageName: packageName, file: file, offset: offset);
+    return PubPackageCompletionItemResolutionInfo(packageName: packageName);
   }
 
-  final String file;
-  final int offset;
   final String packageName;
 
   Map<String, Object?> toJson() {
     var __result = <String, Object?>{};
     __result['packageName'] = packageName;
-    __result['file'] = file;
-    __result['offset'] = offset;
     return __result;
   }
 
@@ -1257,42 +1204,6 @@
       } finally {
         reporter.pop();
       }
-      reporter.push('file');
-      try {
-        if (!obj.containsKey('file')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final file = obj['file'];
-        if (file == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!(file is String)) {
-          reporter.reportError('must be of type String');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
-      reporter.push('offset');
-      try {
-        if (!obj.containsKey('offset')) {
-          reporter.reportError('must not be undefined');
-          return false;
-        }
-        final offset = obj['offset'];
-        if (offset == null) {
-          reporter.reportError('must not be null');
-          return false;
-        }
-        if (!(offset is int)) {
-          reporter.reportError('must be of type int');
-          return false;
-        }
-      } finally {
-        reporter.pop();
-      }
       return true;
     } else {
       reporter.reportError(
@@ -1305,16 +1216,13 @@
   bool operator ==(Object other) {
     if (other is PubPackageCompletionItemResolutionInfo &&
         other.runtimeType == PubPackageCompletionItemResolutionInfo) {
-      return packageName == other.packageName &&
-          file == other.file &&
-          offset == other.offset &&
-          true;
+      return packageName == other.packageName && true;
     }
     return false;
   }
 
   @override
-  int get hashCode => Object.hash(packageName, file, offset);
+  int get hashCode => packageName.hashCode;
 
   @override
   String toString() => jsonEncoder.convert(toJson());
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index e8de391..3222ce8 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -628,7 +628,7 @@
     final kind = SymbolKind.fromJson(kindJson as int);
     final tagsJson = json['tags'];
     final tags = (tagsJson as List<Object?>?)
-        ?.map((item) => SymbolTag.fromJson(item as num))
+        ?.map((item) => SymbolTag.fromJson(item as int))
         .toList();
     final detailJson = json['detail'];
     final detail = detailJson as String?;
@@ -5528,7 +5528,7 @@
       Map<String, Object?> json) {
     final valueSetJson = json['valueSet'];
     final valueSet = (valueSetJson as List<Object?>)
-        .map((item) => InsertTextMode.fromJson(item as num))
+        .map((item) => InsertTextMode.fromJson(item as int))
         .toList();
     return CompletionClientCapabilitiesInsertTextModeSupport(
         valueSet: valueSet);
@@ -5743,7 +5743,7 @@
   CompletionContext({required this.triggerKind, this.triggerCharacter});
   static CompletionContext fromJson(Map<String, Object?> json) {
     final triggerKindJson = json['triggerKind'];
-    final triggerKind = CompletionTriggerKind.fromJson(triggerKindJson as num);
+    final triggerKind = CompletionTriggerKind.fromJson(triggerKindJson as int);
     final triggerCharacterJson = json['triggerCharacter'];
     final triggerCharacter = triggerCharacterJson as String?;
     return CompletionContext(
@@ -5879,7 +5879,7 @@
         : null;
     final insertTextModeJson = json['insertTextMode'];
     final insertTextMode = insertTextModeJson != null
-        ? InsertTextMode.fromJson(insertTextModeJson as num)
+        ? InsertTextMode.fromJson(insertTextModeJson as int)
         : null;
     final textEditJson = json['textEdit'];
     final textEdit = textEditJson == null
@@ -7041,7 +7041,7 @@
   const CompletionTriggerKind._(this._value);
   const CompletionTriggerKind.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
     switch (obj) {
@@ -8606,7 +8606,7 @@
     final range = Range.fromJson(rangeJson as Map<String, Object?>);
     final severityJson = json['severity'];
     final severity = severityJson != null
-        ? DiagnosticSeverity.fromJson(severityJson as num)
+        ? DiagnosticSeverity.fromJson(severityJson as int)
         : null;
     final codeJson = json['code'];
     final code = codeJson as String?;
@@ -8620,7 +8620,7 @@
     final message = messageJson as String;
     final tagsJson = json['tags'];
     final tags = (tagsJson as List<Object?>?)
-        ?.map((item) => DiagnosticTag.fromJson(item as num))
+        ?.map((item) => DiagnosticTag.fromJson(item as int))
         .toList();
     final relatedInformationJson = json['relatedInformation'];
     final relatedInformation = (relatedInformationJson as List<Object?>?)
@@ -8953,10 +8953,10 @@
   const DiagnosticSeverity(this._value);
   const DiagnosticSeverity.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// Reports an error.
@@ -8988,10 +8988,10 @@
   const DiagnosticTag(this._value);
   const DiagnosticTag.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// Unused or unnecessary code.
@@ -12384,7 +12384,7 @@
     final kind = SymbolKind.fromJson(kindJson as int);
     final tagsJson = json['tags'];
     final tags = (tagsJson as List<Object?>?)
-        ?.map((item) => SymbolTag.fromJson(item as num))
+        ?.map((item) => SymbolTag.fromJson(item as int))
         .toList();
     final deprecatedJson = json['deprecated'];
     final deprecated = deprecatedJson as bool?;
@@ -12864,7 +12864,7 @@
       Map<String, Object?> json) {
     final valueSetJson = json['valueSet'];
     final valueSet = (valueSetJson as List<Object?>)
-        .map((item) => SymbolTag.fromJson(item as num))
+        .map((item) => SymbolTag.fromJson(item as int))
         .toList();
     return DocumentSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
   }
@@ -16348,7 +16348,8 @@
         final trace = obj['trace'];
         if (trace != null &&
             !((trace == 'off' || trace == 'message' || trace == 'verbose'))) {
-          reporter.reportError('must be of type String');
+          reporter.reportError(
+              'must be one of the literals \'off\', \'message\', \'verbose\'');
           return false;
         }
       } finally {
@@ -16870,10 +16871,10 @@
   const InsertTextMode(this._value);
   const InsertTextMode.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// The insertion or replace strings is taken as it is. If the value is multi
@@ -19567,10 +19568,10 @@
   const PrepareSupportDefaultBehavior(this._value);
   const PrepareSupportDefaultBehavior.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// The client's default behavior is to select the identifier according the to
@@ -19834,7 +19835,7 @@
       Map<String, Object?> json) {
     final valueSetJson = json['valueSet'];
     final valueSet = (valueSetJson as List<Object?>)
-        .map((item) => DiagnosticTag.fromJson(item as num))
+        .map((item) => DiagnosticTag.fromJson(item as int))
         .toList();
     return PublishDiagnosticsClientCapabilitiesTagSupport(valueSet: valueSet);
   }
@@ -20906,7 +20907,7 @@
     final prepareSupportDefaultBehavior =
         prepareSupportDefaultBehaviorJson != null
             ? PrepareSupportDefaultBehavior.fromJson(
-                prepareSupportDefaultBehaviorJson as num)
+                prepareSupportDefaultBehaviorJson as int)
             : null;
     final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
     final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
@@ -26030,7 +26031,8 @@
           return false;
         }
         if (!((value == 'off' || value == 'message' || value == 'verbose'))) {
-          reporter.reportError('must be of type String');
+          reporter.reportError(
+              'must be one of the literals \'off\', \'message\', \'verbose\'');
           return false;
         }
       } finally {
@@ -27116,7 +27118,7 @@
   static SignatureHelpContext fromJson(Map<String, Object?> json) {
     final triggerKindJson = json['triggerKind'];
     final triggerKind =
-        SignatureHelpTriggerKind.fromJson(triggerKindJson as num);
+        SignatureHelpTriggerKind.fromJson(triggerKindJson as int);
     final triggerCharacterJson = json['triggerCharacter'];
     final triggerCharacter = triggerCharacterJson as String?;
     final isRetriggerJson = json['isRetrigger'];
@@ -27683,10 +27685,10 @@
   const SignatureHelpTriggerKind(this._value);
   const SignatureHelpTriggerKind.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// Signature help was invoked manually by the user or by a command.
@@ -27972,7 +27974,7 @@
     final kind = SymbolKind.fromJson(kindJson as int);
     final tagsJson = json['tags'];
     final tags = (tagsJson as List<Object?>?)
-        ?.map((item) => SymbolTag.fromJson(item as num))
+        ?.map((item) => SymbolTag.fromJson(item as int))
         .toList();
     final deprecatedJson = json['deprecated'];
     final deprecated = deprecatedJson as bool?;
@@ -28209,10 +28211,10 @@
   const SymbolTag(this._value);
   const SymbolTag.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object? obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// Render a symbol as obsolete, usually using a strike-out.
@@ -32991,7 +32993,7 @@
       Map<String, Object?> json) {
     final valueSetJson = json['valueSet'];
     final valueSet = (valueSetJson as List<Object?>)
-        .map((item) => SymbolTag.fromJson(item as num))
+        .map((item) => SymbolTag.fromJson(item as int))
         .toList();
     return WorkspaceSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
   }
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index 5e3a9c5..ffba325 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -36,6 +36,7 @@
     aliasedType: aliasedType,
     parameters: elementParameters,
     returnType: elementReturnType,
+    libraryUri: element.library?.source.uri.toString(),
   );
 }
 
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 00b690a..3baa946 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.32.8';
+const String PROTOCOL_VERSION = '1.32.9';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -138,7 +138,11 @@
 const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_MODE =
+    'completionMode';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_INVOCATION_COUNT =
+    'invocationCount';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_MAX_RESULTS = 'maxResults';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_TIMEOUT = 'timeout';
@@ -167,8 +171,6 @@
     'subscriptions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_IS_INCOMPLETE =
     'isIncomplete';
-const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_LIBRARY_URIS_TO_IMPORT =
-    'libraryUrisToImport';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 8d9f921..98395e9 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -4698,6 +4698,15 @@
   /// to true.
   int maxResults;
 
+  /// The mode of code completion being invoked. If no value is provided, BASIC
+  /// will be assumed. BASIC is also the only currently supported.
+  CompletionMode? completionMode;
+
+  /// The number of times that the user has invoked code completion at the same
+  /// code location, counting from 1. If no value is provided, 1 will be
+  /// assumed.
+  int? invocationCount;
+
   /// The approximate time in milliseconds that the server should spend. The
   /// server will perform some steps anyway, even if it takes longer than the
   /// specified timeout. This field is intended to be used for benchmarking,
@@ -4705,7 +4714,7 @@
   int? timeout;
 
   CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults,
-      {this.timeout});
+      {this.completionMode, this.invocationCount, this.timeout});
 
   factory CompletionGetSuggestions2Params.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4730,11 +4739,23 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'maxResults');
       }
+      CompletionMode? completionMode;
+      if (json.containsKey('completionMode')) {
+        completionMode = CompletionMode.fromJson(
+            jsonDecoder, jsonPath + '.completionMode', json['completionMode']);
+      }
+      int? invocationCount;
+      if (json.containsKey('invocationCount')) {
+        invocationCount = jsonDecoder.decodeInt(
+            jsonPath + '.invocationCount', json['invocationCount']);
+      }
       int? timeout;
       if (json.containsKey('timeout')) {
         timeout = jsonDecoder.decodeInt(jsonPath + '.timeout', json['timeout']);
       }
       return CompletionGetSuggestions2Params(file, offset, maxResults,
+          completionMode: completionMode,
+          invocationCount: invocationCount,
           timeout: timeout);
     } else {
       throw jsonDecoder.mismatch(
@@ -4753,6 +4774,14 @@
     result['file'] = file;
     result['offset'] = offset;
     result['maxResults'] = maxResults;
+    var completionMode = this.completionMode;
+    if (completionMode != null) {
+      result['completionMode'] = completionMode.toJson();
+    }
+    var invocationCount = this.invocationCount;
+    if (invocationCount != null) {
+      result['invocationCount'] = invocationCount;
+    }
     var timeout = this.timeout;
     if (timeout != null) {
       result['timeout'] = timeout;
@@ -4774,6 +4803,8 @@
       return file == other.file &&
           offset == other.offset &&
           maxResults == other.maxResults &&
+          completionMode == other.completionMode &&
+          invocationCount == other.invocationCount &&
           timeout == other.timeout;
     }
     return false;
@@ -4784,6 +4815,8 @@
         file,
         offset,
         maxResults,
+        completionMode,
+        invocationCount,
         timeout,
       );
 }
@@ -4794,7 +4827,6 @@
 ///   "replacementOffset": int
 ///   "replacementLength": int
 ///   "suggestions": List<CompletionSuggestion>
-///   "libraryUrisToImport": List<String>
 ///   "isIncomplete": bool
 /// }
 ///
@@ -4820,31 +4852,16 @@
   /// (if isIncomplete was true).
   ///
   /// This list contains suggestions from both imported, and not yet imported
-  /// libraries. Items from not yet imported libraries will have
-  /// libraryUriToImportIndex set, which is an index into the
-  /// libraryUrisToImport in this response.
+  /// libraries. Items from not yet imported libraries will have isNotImported
+  /// set to true.
   List<CompletionSuggestion> suggestions;
 
-  /// The list of libraries with declarations that are not yet available in the
-  /// file where completion was requested, most often because the library is
-  /// not yet imported. The declarations still might be included into the
-  /// suggestions, and the client should use getSuggestionDetails2 on selection
-  /// to make the library available in the file.
-  ///
-  /// Each item is the URI of a library, such as package:foo/bar.dart or
-  /// file:///home/me/workspace/foo/test/bar_test.dart.
-  List<String> libraryUrisToImport;
-
   /// True if the number of suggestions after filtering was greater than the
   /// requested maxResults.
   bool isIncomplete;
 
-  CompletionGetSuggestions2Result(
-      this.replacementOffset,
-      this.replacementLength,
-      this.suggestions,
-      this.libraryUrisToImport,
-      this.isIncomplete);
+  CompletionGetSuggestions2Result(this.replacementOffset,
+      this.replacementLength, this.suggestions, this.isIncomplete);
 
   factory CompletionGetSuggestions2Result.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4874,15 +4891,6 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'suggestions');
       }
-      List<String> libraryUrisToImport;
-      if (json.containsKey('libraryUrisToImport')) {
-        libraryUrisToImport = jsonDecoder.decodeList(
-            jsonPath + '.libraryUrisToImport',
-            json['libraryUrisToImport'],
-            jsonDecoder.decodeString);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'libraryUrisToImport');
-      }
       bool isIncomplete;
       if (json.containsKey('isIncomplete')) {
         isIncomplete = jsonDecoder.decodeBool(
@@ -4890,8 +4898,8 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'isIncomplete');
       }
-      return CompletionGetSuggestions2Result(replacementOffset,
-          replacementLength, suggestions, libraryUrisToImport, isIncomplete);
+      return CompletionGetSuggestions2Result(
+          replacementOffset, replacementLength, suggestions, isIncomplete);
     } else {
       throw jsonDecoder.mismatch(
           jsonPath, 'completion.getSuggestions2 result', json);
@@ -4913,7 +4921,6 @@
     result['suggestions'] = suggestions
         .map((CompletionSuggestion value) => value.toJson())
         .toList();
-    result['libraryUrisToImport'] = libraryUrisToImport;
     result['isIncomplete'] = isIncomplete;
     return result;
   }
@@ -4933,8 +4940,6 @@
           replacementLength == other.replacementLength &&
           listEqual(suggestions, other.suggestions,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
-          listEqual(libraryUrisToImport, other.libraryUrisToImport,
-              (String a, String b) => a == b) &&
           isIncomplete == other.isIncomplete;
     }
     return false;
@@ -4945,7 +4950,6 @@
         replacementOffset,
         replacementLength,
         suggestions,
-        libraryUrisToImport,
         isIncomplete,
       );
 }
@@ -5090,6 +5094,58 @@
   int get hashCode => id.hashCode;
 }
 
+/// CompletionMode
+///
+/// enum {
+///   BASIC
+///   SMART
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionMode implements Enum {
+  /// Basic code completion invocation type, and the default for this
+  /// enumeration.
+  static const CompletionMode BASIC = CompletionMode._('BASIC');
+
+  /// Smart code completion, currently not implemented.
+  static const CompletionMode SMART = CompletionMode._('SMART');
+
+  /// A list containing all of the enum values that are defined.
+  static const List<CompletionMode> VALUES = <CompletionMode>[BASIC, SMART];
+
+  @override
+  final String name;
+
+  const CompletionMode._(this.name);
+
+  factory CompletionMode(String name) {
+    switch (name) {
+      case 'BASIC':
+        return BASIC;
+      case 'SMART':
+        return SMART;
+    }
+    throw Exception('Illegal enum value: $name');
+  }
+
+  factory CompletionMode.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    if (json is String) {
+      try {
+        return CompletionMode(json);
+      } catch (_) {
+        // Fall through
+      }
+    }
+    throw jsonDecoder.mismatch(jsonPath, 'CompletionMode', json);
+  }
+
+  @override
+  String toString() => 'CompletionMode.$name';
+
+  String toJson() => name;
+}
+
 /// completion.registerLibraryPaths params
 ///
 /// {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 4c8b529..1350c46 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -410,11 +410,11 @@
   ///
   /// So, we can start working in parallel on adding services and improving
   /// projects/contexts support.
-  void setAnalysisRoots(String requestId, List<String> includedPaths,
-      List<String> excludedPaths) {
+  Future<void> setAnalysisRoots(String requestId, List<String> includedPaths,
+      List<String> excludedPaths) async {
     notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
     try {
-      contextManager.setRoots(includedPaths, excludedPaths);
+      await contextManager.setRoots(includedPaths, excludedPaths);
     } on UnimplementedError catch (e) {
       throw RequestFailure(Response.unsupportedFeature(
           requestId, e.message ?? 'Unsupported feature.'));
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index b94ee3f..b60182d 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -459,8 +459,8 @@
 
   /// Read all files, resolve all URIs, and perform required analysis in
   /// all current analysis drivers.
-  void reanalyze() {
-    contextManager.refresh();
+  Future<void> reanalyze() async {
+    await contextManager.refresh();
   }
 
   ResolvedForCompletionResultImpl? resolveForCompletion({
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index cd4ec1f..df18a65 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -242,30 +242,14 @@
       return false;
     }
 
-    // TODO(dantup): Right now there is no highlight type for extension, so
-    // bail out and do the default thing (which will be to return
-    // IDENTIFIER_DEFAULT). Adding EXTENSION requires coordination with
-    // IntelliJ + bumping protocol version.
-    if (!_computeSemanticTokens) {
-      return false;
-    }
-
     return _addRegion_node(
       node,
-      // TODO(dantup): Change this to EXTENSION and add to LSP mapping when
-      // we have it, but for now use CLASS (which is probably what we'll map it
-      // to for LSP semantic tokens anyway).
-      HighlightRegionType.CLASS,
+      HighlightRegionType.EXTENSION,
     );
   }
 
   bool _addIdentifierRegion_field(SimpleIdentifier node) {
     var element = node.writeOrReadElement;
-    if (element is FieldFormalParameterElement) {
-      if (node.parent is FieldFormalParameter) {
-        element = element.field;
-      }
-    }
     // prepare type
     HighlightRegionType? type;
     if (element is FieldElement) {
@@ -790,6 +774,18 @@
   void visitFieldFormalParameter(FieldFormalParameter node) {
     computer._addRegion_token(
         node.requiredKeyword, HighlightRegionType.KEYWORD);
+
+    var element = node.declaredElement;
+    if (element is FieldFormalParameterElement) {
+      var field = element.field;
+      if (field != null) {
+        computer._addRegion_node(
+          node.identifier,
+          HighlightRegionType.INSTANCE_FIELD_REFERENCE,
+        );
+      }
+    }
+
     super.visitFieldFormalParameter(node);
   }
 
@@ -1108,6 +1104,23 @@
   }
 
   @override
+  void visitSuperFormalParameter(SuperFormalParameter node) {
+    computer._addRegion_token(
+      node.superKeyword,
+      HighlightRegionType.KEYWORD,
+    );
+
+    computer._addRegion_node(
+      node.identifier,
+      HighlightRegionType.PARAMETER_DECLARATION,
+    );
+
+    node.type?.accept(this);
+    node.typeParameters?.accept(this);
+    node.parameters?.accept(this);
+  }
+
+  @override
   void visitSwitchCase(SwitchCase node) {
     computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD,
         semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index ceb6b14..6dc9295 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_parser.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -81,11 +82,11 @@
 
   /// Rebuild the set of contexts from scratch based on the data last sent to
   /// [setRoots].
-  void refresh();
+  Future<void> refresh();
 
   /// Change the set of paths which should be used as starting points to
   /// determine the context directories.
-  void setRoots(List<String> includedPaths, List<String> excludedPaths);
+  Future<void> setRoots(List<String> includedPaths, List<String> excludedPaths);
 }
 
 /// Callback interface used by [ContextManager] to (a) request that contexts be
@@ -182,10 +183,6 @@
   final Map<Folder, AnalysisDriver> driverMap =
       HashMap<Folder, AnalysisDriver>();
 
-  /// The timer that is started after creating analysis contexts, to check
-  /// for in-between changes to configuration files.
-  Timer? _collectionConsistencyCheckTimer;
-
   /// Stream subscription we are using to watch each analysis root directory for
   /// changes.
   final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions =
@@ -211,6 +208,12 @@
   /// clean up when we destroy a context.
   final bazelWatchedPathsPerFolder = <Folder, _BazelWatchedFiles>{};
 
+  /// Information about the current/last queued context rebuild.
+  ///
+  /// This is used when a new build is requested to cancel any in-progress
+  /// rebuild and wait for it to terminate before starting the next.
+  final _CancellingTaskQueue currentContextRebuild = _CancellingTaskQueue();
+
   ContextManagerImpl(
       this.resourceProvider,
       this.sdkManager,
@@ -255,13 +258,18 @@
     );
   }
 
+  /// Starts (an asynchronous) rebuild of analysis contexts.
   @override
-  void refresh() {
-    _createAnalysisContexts();
+  Future<void> refresh() async {
+    await _createAnalysisContexts();
   }
 
+  /// Updates the analysis roots and waits for the contexts to rebuild.
+  ///
+  /// If the roots have not changed, exits early without performing any work.
   @override
-  void setRoots(List<String> includedPaths, List<String> excludedPaths) {
+  Future<void> setRoots(
+      List<String> includedPaths, List<String> excludedPaths) async {
     if (_rootsAreUnchanged(includedPaths, excludedPaths)) {
       return;
     }
@@ -269,7 +277,7 @@
     this.includedPaths = includedPaths;
     this.excludedPaths = excludedPaths;
 
-    _createAnalysisContexts();
+    await _createAnalysisContexts();
   }
 
   /// Use the given analysis [driver] to analyze the content of the analysis
@@ -412,65 +420,156 @@
     }
   }
 
-  void _createAnalysisContexts() {
-    _destroyAnalysisContexts();
-    _fileContentCache.invalidateAll();
+  /// Recreates all analysis contexts.
+  ///
+  /// If an existing rebuild is in progress, it will be cancelled and this
+  /// rebuild will occur only once it has exited.
+  ///
+  /// Returns a [Future] that completes once the requested rebuild completes.
+  Future<void> _createAnalysisContexts() async {
+    /// A helper that performs a context rebuild while monitoring the included
+    /// paths for changes until the contexts file watchers are ready.
+    ///
+    /// If changes are detected during the rebuild, the rebuild will be
+    /// restarted.
+    Future<void> performContextRebuildGuarded(
+      CancellationToken cancellationToken,
+    ) async {
+      /// A helper that performs the context rebuild and waits for all watchers
+      /// to be fully initialized.
+      Future<void> performContextRebuild() async {
+        _destroyAnalysisContexts();
+        _fileContentCache.invalidateAll();
 
-    var collection = _collection = AnalysisContextCollectionImpl(
-      includedPaths: includedPaths,
-      excludedPaths: excludedPaths,
-      byteStore: _byteStore,
-      drainStreams: false,
-      enableIndex: true,
-      performanceLog: _performanceLog,
-      resourceProvider: resourceProvider,
-      scheduler: _scheduler,
-      sdkPath: sdkManager.defaultSdkDirectory,
-      packagesFile: packagesFile,
-      fileContentCache: _fileContentCache,
-    );
+        var watchers = <ResourceWatcher>[];
+        var collection = _collection = AnalysisContextCollectionImpl(
+          includedPaths: includedPaths,
+          excludedPaths: excludedPaths,
+          byteStore: _byteStore,
+          drainStreams: false,
+          enableIndex: true,
+          performanceLog: _performanceLog,
+          resourceProvider: resourceProvider,
+          scheduler: _scheduler,
+          sdkPath: sdkManager.defaultSdkDirectory,
+          packagesFile: packagesFile,
+          fileContentCache: _fileContentCache,
+        );
 
-    for (var analysisContext in collection.contexts) {
-      var driver = analysisContext.driver;
+        for (var analysisContext in collection.contexts) {
+          var driver = analysisContext.driver;
 
-      callbacks.listenAnalysisDriver(driver);
+          callbacks.listenAnalysisDriver(driver);
 
-      var rootFolder = analysisContext.contextRoot.root;
-      driverMap[rootFolder] = driver;
+          var rootFolder = analysisContext.contextRoot.root;
+          driverMap[rootFolder] = driver;
 
-      changeSubscriptions[rootFolder] = rootFolder.changes
-          .listen(_handleWatchEvent, onError: _handleWatchInterruption);
+          var watcher = rootFolder.watch();
+          watchers.add(watcher);
+          changeSubscriptions[rootFolder] = watcher.changes
+              .listen(_handleWatchEvent, onError: _handleWatchInterruption);
 
-      _watchBazelFilesIfNeeded(rootFolder, driver);
+          _watchBazelFilesIfNeeded(rootFolder, driver);
 
-      for (var file in analysisContext.contextRoot.analyzedFiles()) {
-        if (file_paths.isAndroidManifestXml(pathContext, file)) {
-          _analyzeAndroidManifestXml(driver, file);
-        } else if (file_paths.isDart(pathContext, file)) {
-          driver.addFile(file);
+          for (var file in analysisContext.contextRoot.analyzedFiles()) {
+            if (file_paths.isAndroidManifestXml(pathContext, file)) {
+              _analyzeAndroidManifestXml(driver, file);
+            } else if (file_paths.isDart(pathContext, file)) {
+              driver.addFile(file);
+            }
+          }
+
+          var optionsFile = analysisContext.contextRoot.optionsFile;
+          if (optionsFile != null) {
+            _analyzeAnalysisOptionsYaml(driver, optionsFile.path);
+          }
+
+          var fixDataYamlFile = rootFolder
+              .getChildAssumingFolder('lib')
+              .getChildAssumingFile(file_paths.fixDataYaml);
+          if (fixDataYamlFile.exists) {
+            _analyzeFixDataYaml(driver, fixDataYamlFile.path);
+          }
+
+          var pubspecFile =
+              rootFolder.getChildAssumingFile(file_paths.pubspecYaml);
+          if (pubspecFile.exists) {
+            _analyzePubspecYaml(driver, pubspecFile.path);
+          }
         }
+
+        // Finally, wait for the new contexts watchers to all become ready so we
+        // can ensure they will not lose any future events before we continue.
+        await Future.wait(watchers.map((watcher) => watcher.ready));
       }
 
-      var optionsFile = analysisContext.contextRoot.optionsFile;
-      if (optionsFile != null) {
-        _analyzeAnalysisOptionsYaml(driver, optionsFile.path);
+      /// A helper that returns whether a change to the file at [path] should
+      /// restart any in-progress rebuild.
+      bool shouldRestartBuild(String path) {
+        return file_paths.isDart(pathContext, path) ||
+            file_paths.isAnalysisOptionsYaml(pathContext, path) ||
+            file_paths.isPubspecYaml(pathContext, path) ||
+            file_paths.isDotPackages(pathContext, path) ||
+            file_paths.isPackageConfigJson(pathContext, path);
       }
 
-      var fixDataYamlFile = rootFolder
-          .getChildAssumingFolder('lib')
-          .getChildAssumingFile(file_paths.fixDataYaml);
-      if (fixDataYamlFile.exists) {
-        _analyzeFixDataYaml(driver, fixDataYamlFile.path);
+      if (cancellationToken.isCancellationRequested) {
+        return;
       }
 
-      var pubspecFile = rootFolder.getChildAssumingFile(file_paths.pubspecYaml);
-      if (pubspecFile.exists) {
-        _analyzePubspecYaml(driver, pubspecFile.path);
+      // Create temporary watchers before we start the context build so we can
+      // tell if any files were modified while waiting for the "real" watchers to
+      // become ready and start the process again.
+      final temporaryWatchers = includedPaths
+          .map((path) => resourceProvider.getResource(path))
+          .map((resource) => resource.watch())
+          .toList();
+
+      // If any watcher picks up an important change while we're running the
+      // rest of this method, we will need to start again.
+      var needsBuild = true;
+      final temporaryWatcherSubscriptions = temporaryWatchers
+          .map((watcher) => watcher.changes.listen((event) {
+                if (shouldRestartBuild(event.path)) {
+                  needsBuild = true;
+                }
+              }))
+          .toList();
+
+      try {
+        // Ensure all watchers are ready before we begin any rebuild.
+        await Future.wait(temporaryWatchers.map((watcher) => watcher.ready));
+
+        // Max number of attempts to rebuild if changes.
+        var remainingBuilds = 5;
+        while (needsBuild && remainingBuilds-- > 0) {
+          // Reset the flag, as we'll only need to rebuild if a temporary
+          // watcher fires after this point.
+          needsBuild = false;
+
+          if (cancellationToken.isCancellationRequested) {
+            return;
+          }
+
+          // Attempt a context rebuild. This call will wait for all required
+          // watchers to be ready before returning.
+          await performContextRebuild();
+        }
+      } finally {
+        // Cancel the temporary watcher subscriptions.
+        await Future.wait(
+          temporaryWatcherSubscriptions.map((sub) => sub.cancel()),
+        );
       }
+
+      if (cancellationToken.isCancellationRequested) {
+        return;
+      }
+
+      callbacks.afterContextsCreated();
     }
 
-    callbacks.afterContextsCreated();
-    _scheduleCollectionConsistencyCheck(collection);
+    return currentContextRebuild.queue(performContextRebuildGuarded);
   }
 
   /// Clean up and destroy the context associated with the given folder.
@@ -492,7 +591,6 @@
   void _destroyAnalysisContexts() {
     var collection = _collection;
     if (collection != null) {
-      _collectionConsistencyCheckTimer?.cancel();
       for (var analysisContext in collection.contexts) {
         _destroyAnalysisContext(analysisContext);
       }
@@ -577,15 +675,16 @@
         file_paths.isPackageConfigJson(pathContext, path) ||
         isPubspec ||
         false) {
-      _createAnalysisContexts();
-
-      if (isPubspec) {
-        if (type == ChangeType.REMOVE) {
-          callbacks.pubspecRemoved(path);
-        } else {
-          callbacks.pubspecChanged(path);
+      _createAnalysisContexts().then((_) {
+        if (isPubspec) {
+          if (type == ChangeType.REMOVE) {
+            callbacks.pubspecRemoved(path);
+          } else {
+            callbacks.pubspecChanged(path);
+          }
         }
-      }
+      });
+
       return;
     }
 
@@ -652,28 +751,6 @@
         existingExcludedSet.containsAll(excludedPaths);
   }
 
-  /// We create analysis contexts, and then start watching the file system
-  /// for modifications to Dart files, and to configuration files, e.g.
-  /// `pubspec.yaml` file Pub workspaces.
-  ///
-  /// So, it is possible that one of these files will be changed between the
-  /// moment when we read it, and the moment when we started watching for
-  /// changes. Using `package:watcher` before creating analysis contexts
-  /// was still not reliable enough.
-  ///
-  /// To work around this we check after a short timeout, and hope that
-  /// any subsequent changes will be noticed by `package:watcher`.
-  void _scheduleCollectionConsistencyCheck(
-    AnalysisContextCollectionImpl collection,
-  ) {
-    _collectionConsistencyCheckTimer = Timer(Duration(seconds: 1), () {
-      _collectionConsistencyCheckTimer = null;
-      if (!collection.areWorkspacesConsistent) {
-        _createAnalysisContexts();
-      }
-    });
-  }
-
   /// Starts watching for the `bazel-bin` and `blaze-bin` symlinks.
   ///
   /// This is important since these symlinks might not be present when the
@@ -755,3 +832,50 @@
   final paths = <String>{};
   _BazelWatchedFiles(this.workspace);
 }
+
+/// Handles a task queue of tasks that cannot run concurrently.
+///
+/// Queueing a new task will signal for any in-progress task to cancel and
+/// wait for it to complete before starting the new task.
+class _CancellingTaskQueue {
+  /// A cancellation token for current/last queued task.
+  ///
+  /// This token is replaced atomically with [_complete] and
+  /// together they allow cancelling a task and chaining a new task on
+  /// to the end.
+  CancelableToken? _cancellationToken;
+
+  /// A [Future] that completes when the current/last queued task finishes.
+  ///
+  /// This future is replaced atomically with [_cancellationToken] and together
+  /// they allow cancelling a task and chaining a new task on to the end.
+  Future<void> _complete = Future.value();
+
+  /// Requests that [performTask] is called after first cancelling any
+  /// in-progress task and waiting for it to complete.
+  ///
+  /// Returns a future that completes once the new task has completed.
+  Future<void> queue(
+    Future<void> Function(CancellationToken cancellationToken) performTask,
+  ) {
+    // Signal for any in-progress task to cancel.
+    _cancellationToken?.cancel();
+
+    // Chain the new task onto the end of any existing one, so the new
+    // task never starts until the previous (cancelled) one finishes (which
+    // may be by aborting early because of the cancellation signal).
+    final token = _cancellationToken = CancelableToken();
+    _complete = _complete
+        .then((_) => performTask(token))
+        .then((_) => _clearTokenIfCurrent(token));
+
+    return _complete;
+  }
+
+  /// Clears the current cancellation token if it is [token].
+  void _clearTokenIfCurrent(CancelableToken token) {
+    if (token == _cancellationToken) {
+      _cancellationToken = null;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index d079a6b..af16242 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -279,9 +279,11 @@
         getSignature(request);
         return Response.DELAYED_RESPONSE;
       } else if (requestName == ANALYSIS_REQUEST_REANALYZE) {
-        return reanalyze(request);
+        reanalyze(request);
+        return Response.DELAYED_RESPONSE;
       } else if (requestName == ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS) {
-        return setAnalysisRoots(request);
+        setAnalysisRoots(request);
+        return Response.DELAYED_RESPONSE;
       } else if (requestName == ANALYSIS_REQUEST_SET_GENERAL_SUBSCRIPTIONS) {
         return setGeneralSubscriptions(request);
       } else if (requestName == ANALYSIS_REQUEST_SET_PRIORITY_FILES) {
@@ -300,10 +302,10 @@
   }
 
   /// Implement the 'analysis.reanalyze' request.
-  Response reanalyze(Request request) {
+  void reanalyze(Request request) async {
     server.options.analytics?.sendEvent('analysis', 'reanalyze');
 
-    server.reanalyze();
+    await server.reanalyze();
 
     //
     // Restart all of the plugins. This is an async operation that will happen
@@ -313,11 +315,11 @@
     //
     // Send the response.
     //
-    return AnalysisReanalyzeResult().toResponse(request.id);
+    server.sendResponse(AnalysisReanalyzeResult().toResponse(request.id));
   }
 
   /// Implement the 'analysis.setAnalysisRoots' request.
-  Response setAnalysisRoots(Request request) {
+  void setAnalysisRoots(Request request) async {
     var params = AnalysisSetAnalysisRootsParams.fromRequest(request);
     var includedPathList = params.included;
     var excludedPathList = params.excluded;
@@ -328,12 +330,14 @@
     // validate
     for (var path in includedPathList) {
       if (!server.isValidFilePath(path)) {
-        return Response.invalidFilePathFormat(request, path);
+        server.sendResponse(Response.invalidFilePathFormat(request, path));
+        return;
       }
     }
     for (var path in excludedPathList) {
       if (!server.isValidFilePath(path)) {
-        return Response.invalidFilePathFormat(request, path);
+        server.sendResponse(Response.invalidFilePathFormat(request, path));
+        return;
       }
     }
 
@@ -343,9 +347,11 @@
       detachableFileSystemManager
           .setAnalysisRoots(request.id, includedPathList, excludedPathList, {});
     } else {
-      server.setAnalysisRoots(request.id, includedPathList, excludedPathList);
+      await server.setAnalysisRoots(
+          request.id, includedPathList, excludedPathList);
     }
-    return AnalysisSetAnalysisRootsResult().toResponse(request.id);
+    return server
+        .sendResponse(AnalysisSetAnalysisRootsResult().toResponse(request.id));
   }
 
   /// Implement the 'analysis.setGeneralSubscriptions' request.
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 661049b..45ccc9b 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
@@ -76,7 +75,7 @@
     Set<ElementKind>? includedElementKinds,
     Set<String>? includedElementNames,
     List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags,
-    Map<CompletionSuggestion, Uri>? notImportedSuggestions,
+    NotImportedSuggestions? notImportedSuggestions,
   }) async {
     //
     // Allow plugins to start computing fixes.
@@ -289,7 +288,6 @@
           suggestions.replacementOffset,
           suggestions.replacementLength,
           suggestions.suggestions,
-          [],
           false,
         ).toResponse(request.id),
       );
@@ -298,7 +296,7 @@
 
     if (!file_paths.isDart(pathContext, file)) {
       server.sendResponse(
-        CompletionGetSuggestions2Result(offset, 0, [], [], false)
+        CompletionGetSuggestions2Result(offset, 0, [], false)
             .toResponse(request.id),
       );
       return;
@@ -358,8 +356,7 @@
         );
         setNewRequest(completionRequest);
 
-        var notImportedSuggestions =
-            HashMap<CompletionSuggestion, Uri>.identity();
+        var notImportedSuggestions = NotImportedSuggestions();
         var suggestions = <CompletionSuggestion>[];
         try {
           suggestions = await computeSuggestions(
@@ -374,7 +371,6 @@
               completionRequest.replacementOffset,
               completionRequest.replacementLength,
               [],
-              [],
               true,
             ).toResponse(request.id),
           );
@@ -390,33 +386,27 @@
         });
 
         var lengthRestricted = suggestions.take(params.maxResults).toList();
-        var isIncomplete = lengthRestricted.length < suggestions.length;
         completionPerformance.suggestionCount = lengthRestricted.length;
 
-        // Update `libraryUriToImportIndex` for not yet imported.
-        // Gather referenced unique libraries to import.
-        var librariesToImport = <Uri, int>{};
+        // Update `isNotImported` for not yet imported.
         for (var i = 0; i < lengthRestricted.length; i++) {
           var suggestion = lengthRestricted[i];
-          var libraryToImport = notImportedSuggestions[suggestion];
-          if (libraryToImport != null) {
-            var index = librariesToImport.putIfAbsent(
-              libraryToImport,
-              () => librariesToImport.length,
-            );
+          if (notImportedSuggestions.set.contains(suggestion)) {
             lengthRestricted[i] = suggestion.copyWith(
-              libraryUriToImportIndex: CopyWithValue(index),
+              isNotImported: CopyWithValue(true),
             );
           }
         }
 
+        var isIncomplete = notImportedSuggestions.isIncomplete ||
+            lengthRestricted.length < suggestions.length;
+
         performance.run('sendResponse', (_) {
           server.sendResponse(
             CompletionGetSuggestions2Result(
               completionRequest.replacementOffset,
               completionRequest.replacementLength,
               lengthRestricted,
-              librariesToImport.keys.map((e) => '$e').toList(),
               isIncomplete,
             ).toResponse(request.id),
           );
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index e8838ce..3c7bbac 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -155,7 +155,7 @@
     case DeclarationKind.FUNCTION:
       return protocol.ElementKind.FUNCTION;
     case DeclarationKind.FUNCTION_TYPE_ALIAS:
-      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+      return protocol.ElementKind.TYPE_ALIAS;
     case DeclarationKind.GETTER:
       return protocol.ElementKind.GETTER;
     case DeclarationKind.METHOD:
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index d8cc97f..a782782 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -134,6 +134,10 @@
   /// of the expression would show through the simple-colorings "string" colors.
   static const interpolation = SemanticTokenModifiers('interpolation');
 
+  /// A modifier applied to instance field/getter/setter/method references and
+  /// declarations to distinguish them from top-levels.
+  static const instance = SemanticTokenModifiers('instance');
+
   /// A modifier applied to the void keyword to allow users to color it
   /// differently (for example as a type).
   static const void_ = SemanticTokenModifiers('void');
@@ -147,6 +151,7 @@
     annotation,
     control,
     importPrefix,
+    instance,
     label,
     constructor,
     escape,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index d2bd74d..736ab90 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -31,13 +31,14 @@
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 
-class CompletionHandler
-    extends MessageHandler<CompletionParams, List<CompletionItem>>
+class CompletionHandler extends MessageHandler<CompletionParams, CompletionList>
     with LspPluginRequestHandlerMixin {
+  /// Whether to include symbols from libraries that have not been imported.
   final bool suggestFromUnimportedLibraries;
-  CompletionHandler(
-      LspAnalysisServer server, this.suggestFromUnimportedLibraries)
-      : super(server);
+
+  CompletionHandler(LspAnalysisServer server, LspInitializationOptions options)
+      : suggestFromUnimportedLibraries = options.suggestFromUnimportedLibraries,
+        super(server);
 
   @override
   Method get handlesMessage => Method.textDocument_completion;
@@ -47,7 +48,7 @@
       CompletionParams.jsonHandler;
 
   @override
-  Future<ErrorOr<List<CompletionItem>>> handle(
+  Future<ErrorOr<CompletionList>> handle(
       CompletionParams params, CancellationToken token) async {
     final clientCapabilities = server.clientCapabilities;
     if (clientCapabilities == null) {
@@ -56,9 +57,6 @@
           'Requests not before server is initilized');
     }
 
-    final includeSuggestionSets =
-        suggestFromUnimportedLibraries && clientCapabilities.applyEdit;
-
     final triggerCharacter = params.context?.triggerCharacter;
     final pos = params.position;
     final path = pathOfDoc(params.textDocument);
@@ -75,14 +73,13 @@
         await lineInfo.mapResult((lineInfo) => toOffset(lineInfo, pos));
 
     return offset.mapResult((offset) async {
-      Future<ErrorOr<List<CompletionItem>>>? serverResultsFuture;
+      Future<ErrorOr<CompletionList>>? serverResultsFuture;
       final pathContext = server.resourceProvider.pathContext;
       final fileExtension = pathContext.extension(path.result);
 
       if (fileExtension == '.dart' && !unit.isError) {
         serverResultsFuture = _getServerDartItems(
           clientCapabilities,
-          includeSuggestionSets,
           unit.result,
           offset,
           triggerCharacter,
@@ -110,7 +107,8 @@
         }
       }
 
-      serverResultsFuture ??= Future.value(success(const <CompletionItem>[]));
+      serverResultsFuture ??=
+          Future.value(success(CompletionList(isIncomplete: false, items: [])));
 
       final pluginResultsFuture = _getPluginResults(
           clientCapabilities, lineInfo.result, path.result, offset);
@@ -125,9 +123,15 @@
       if (serverResults.isError) return serverResults;
       if (pluginResults.isError) return pluginResults;
 
-      return success(
-        serverResults.result.followedBy(pluginResults.result).toList(),
-      );
+      return success(CompletionList(
+        // If any set of the results is incomplete, the whole batch must be
+        // marked as such.
+        isIncomplete: serverResults.result.isIncomplete ||
+            pluginResults.result.isIncomplete,
+        items: serverResults.result.items
+            .followedBy(pluginResults.result.items)
+            .toList(),
+      ));
     });
   }
 
@@ -174,7 +178,7 @@
   String _createImportedSymbolKey(String name, Uri declaringUri) =>
       '$name/$declaringUri';
 
-  Future<ErrorOr<List<CompletionItem>>> _getPluginResults(
+  Future<ErrorOr<CompletionList>> _getPluginResults(
     LspClientCapabilities capabilities,
     LineInfo lineInfo,
     String path,
@@ -188,22 +192,27 @@
         .map((e) => plugin.CompletionGetSuggestionsResult.fromResponse(e))
         .toList();
 
-    return success(_pluginResultsToItems(
-      capabilities,
-      lineInfo,
-      offset,
-      pluginResults,
-    ).toList());
+    return success(CompletionList(
+      isIncomplete: false,
+      items: _pluginResultsToItems(
+        capabilities,
+        lineInfo,
+        offset,
+        pluginResults,
+      ).toList(),
+    ));
   }
 
-  Future<ErrorOr<List<CompletionItem>>> _getServerDartItems(
+  Future<ErrorOr<CompletionList>> _getServerDartItems(
     LspClientCapabilities capabilities,
-    bool includeSuggestionSets,
     ResolvedUnitResult unit,
     int offset,
     String? triggerCharacter,
     CancellationToken token,
   ) async {
+    final useSuggestionSets =
+        suggestFromUnimportedLibraries && capabilities.applyEdit;
+
     var performance = OperationPerformanceImpl('<root>');
     return await performance.runAsync(
       'request',
@@ -226,14 +235,14 @@
 
         if (triggerCharacter != null) {
           if (!_triggerCharacterValid(offset, triggerCharacter, target)) {
-            return success([]);
+            return success(CompletionList(isIncomplete: false, items: []));
           }
         }
 
         Set<ElementKind>? includedElementKinds;
         Set<String>? includedElementNames;
         List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
-        if (includeSuggestionSets) {
+        if (useSuggestionSets) {
           includedElementKinds = <ElementKind>{};
           includedElementNames = <String>{};
           includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
@@ -284,18 +293,22 @@
                     offset, itemReplacementOffset, itemInsertLength);
               }
 
+              // Convert to LSP ranges using the LineInfo.
+              Range? replacementRange = toRange(
+                  unit.lineInfo, itemReplacementOffset, itemReplacementLength);
+              Range? insertionRange = toRange(
+                  unit.lineInfo, itemReplacementOffset, itemInsertLength);
+
               return toCompletionItem(
                 capabilities,
                 unit.lineInfo,
                 item,
-                itemReplacementOffset,
-                itemInsertLength,
-                itemReplacementLength,
-                // TODO(dantup): Including commit characters in every completion
-                // increases the payload size. The LSP spec is ambigious
-                // about how this should be handled (and VS Code requires it) but
-                // this should be removed (or made conditional based on a capability)
-                // depending on how the spec is updated.
+                replacementRange: replacementRange,
+                insertionRange: insertionRange,
+                // TODO(dantup): Move commit characters to the main response
+                // and remove from each individual item (to reduce payload size)
+                // once the following change ships (and the Dart VS Code
+                // extension is updated to use it).
                 // https://github.com/microsoft/vscode-languageserver-node/issues/673
                 includeCommitCharacters:
                     server.clientConfiguration.global.previewCommitCharacters,
@@ -390,11 +403,10 @@
                         completionRequest.replacementOffset,
                         insertLength,
                         completionRequest.replacementLength,
-                        // TODO(dantup): Including commit characters in every completion
-                        // increases the payload size. The LSP spec is ambigious
-                        // about how this should be handled (and VS Code requires it) but
-                        // this should be removed (or made conditional based on a capability)
-                        // depending on how the spec is updated.
+                        // TODO(dantup): Move commit characters to the main response
+                        // and remove from each individual item (to reduce payload size)
+                        // once the following change ships (and the Dart VS Code
+                        // extension is updated to use it).
                         // https://github.com/microsoft/vscode-languageserver-node/issues/673
                         includeCommitCharacters: server
                             .clientConfiguration.global.previewCommitCharacters,
@@ -415,15 +427,16 @@
 
           completionPerformance.suggestionCount = results.length;
 
-          return success(matchingResults);
+          return success(
+              CompletionList(isIncomplete: false, items: matchingResults));
         } on AbortCompletion {
-          return success([]);
+          return success(CompletionList(isIncomplete: false, items: []));
         }
       },
     );
   }
 
-  Future<ErrorOr<List<CompletionItem>>> _getServerYamlItems(
+  Future<ErrorOr<CompletionList>> _getServerYamlItems(
     YamlCompletionGenerator generator,
     LspClientCapabilities capabilities,
     String path,
@@ -437,23 +450,25 @@
       suggestions.replacementOffset,
       suggestions.replacementLength,
     );
+    final replacementRange = toRange(
+        lineInfo, suggestions.replacementOffset, suggestions.replacementLength);
+    final insertionRange =
+        toRange(lineInfo, suggestions.replacementOffset, insertLength);
+
     final completionItems = suggestions.suggestions
         .map(
           (item) => toCompletionItem(
             capabilities,
             lineInfo,
             item,
-            suggestions.replacementOffset,
-            insertLength,
-            suggestions.replacementLength,
+            replacementRange: replacementRange,
+            insertionRange: insertionRange,
             includeCommitCharacters: false,
             completeFunctionCalls: false,
             // Add on any completion-kind-specific resolution data that will be
             // used during resolve() calls to provide additional information.
             resolutionData: item.kind == CompletionSuggestionKind.PACKAGE_NAME
                 ? PubPackageCompletionItemResolutionInfo(
-                    file: path,
-                    offset: offset,
                     // The completion for package names may contain a trailing
                     // ': ' for convenience, so if it's there, trim it off.
                     packageName: item.completion.split(':').first,
@@ -462,7 +477,7 @@
           ),
         )
         .toList();
-    return success(completionItems);
+    return success(CompletionList(isIncomplete: false, items: completionItems));
   }
 
   /// Returns true if [node] is part of an invocation and already has an argument
@@ -495,18 +510,23 @@
     List<plugin.CompletionGetSuggestionsResult> pluginResults,
   ) {
     return pluginResults.expand((result) {
+      final insertLength = _computeInsertLength(
+        offset,
+        result.replacementOffset,
+        result.replacementLength,
+      );
+      final replacementRange =
+          toRange(lineInfo, result.replacementOffset, result.replacementLength);
+      final insertionRange =
+          toRange(lineInfo, result.replacementOffset, insertLength);
+
       return result.results.map(
         (item) => toCompletionItem(
           capabilities,
           lineInfo,
           item,
-          result.replacementOffset,
-          _computeInsertLength(
-            offset,
-            result.replacementOffset,
-            result.replacementLength,
-          ),
-          result.replacementLength,
+          replacementRange: replacementRange,
+          insertionRange: insertionRange,
           // Plugins cannot currently contribute commit characters and we should
           // not assume that the Dart ones would be correct for all of their
           // completions.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 72903a8..d2d2bec 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -2,16 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
+    hide Element;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart' as analyzer;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/util/comment.dart' as analyzer;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 
@@ -39,8 +42,8 @@
   ) async {
     final resolutionInfo = item.data;
 
-    if (resolutionInfo is DartCompletionItemResolutionInfo) {
-      return resolveDartCompletion(item, resolutionInfo, token);
+    if (resolutionInfo is DartSuggestionSetCompletionItemResolutionInfo) {
+      return resolveDartSuggestionSetCompletion(item, resolutionInfo, token);
     } else if (resolutionInfo is PubPackageCompletionItemResolutionInfo) {
       return resolvePubPackageCompletion(item, resolutionInfo, token);
     } else {
@@ -50,51 +53,14 @@
 
   Future<ErrorOr<CompletionItem>> resolveDartCompletion(
     CompletionItem item,
-    DartCompletionItemResolutionInfo data,
-    CancellationToken token,
-  ) async {
-    final clientCapabilities = server.clientCapabilities;
-    if (clientCapabilities == null) {
-      // This should not happen unless a client misbehaves.
-      return error(ErrorCodes.ServerNotInitialized,
-          'Requests not before server is initilized');
-    }
-
-    final file = data.file;
-    final lineInfo = server.getLineInfo(file);
-    if (lineInfo == null) {
-      return error(
-        ErrorCodes.InternalError,
-        'Line info not available for $file',
-        null,
-      );
-    }
-
-    // TODO(dantup): This logic is all repeated from domain_completion and needs
-    // extracting (with support for the different types of responses between
-    // the servers). Where is an appropriate place to put it?
-
-    var library = server.declarationsTracker?.getLibrary(data.libId);
-    if (library == null) {
-      return error(
-        ErrorCodes.InvalidParams,
-        'Library ID is not valid: ${data.libId}',
-        data.libId.toString(),
-      );
-    }
-
-    // If filterText is different to the label, it's because label has parens/args
-    // appended and we should take the basic label. We cannot use insertText as
-    // it may include snippets, whereas filterText is always just the pure string.
-    var requestedName = item.filterText ?? item.label;
-    // The label might be `MyEnum.myValue`, but we import only `MyEnum`.
-    if (requestedName.contains('.')) {
-      requestedName = requestedName.substring(
-        0,
-        requestedName.indexOf('.'),
-      );
-    }
-
+    LspClientCapabilities clientCapabilities,
+    LineInfo lineInfo,
+    CancellationToken token, {
+    required String file,
+    required Uri libraryUri,
+    required Range insertionRange,
+    required Range replacementRange,
+  }) async {
     const timeout = Duration(milliseconds: 1000);
     var timer = Stopwatch()..start();
     _latestCompletionItem = item;
@@ -110,38 +76,23 @@
           return cancelled();
         }
 
-        analyzer.LibraryElement requestedLibraryElement;
-        {
-          final result = await session.getLibraryByUri(library.uriStr);
-          if (result is LibraryElementResult) {
-            requestedLibraryElement = result.element;
-          } else {
-            return error(
-              ErrorCodes.InvalidParams,
-              'Invalid library URI: ${library.uriStr}',
-              '${result.runtimeType}',
-            );
-          }
+        final element = await _getElement(session, libraryUri, item);
+        if (element == null) {
+          return error(
+            ErrorCodes.InvalidParams,
+            'No such element: ${item.label} in $libraryUri',
+            item.label,
+          );
         }
 
         if (token.isCancellationRequested) {
           return cancelled();
         }
 
-        var requestedElement =
-            requestedLibraryElement.exportNamespace.get(requestedName);
-        if (requestedElement == null) {
-          return error(
-            ErrorCodes.InvalidParams,
-            'No such element: $requestedName in ${library.uriStr}',
-            requestedName,
-          );
-        }
-
         var newInsertText = item.insertText ?? item.label;
         final builder = ChangeBuilder(session: session);
         await builder.addDartFileEdit(file, (builder) {
-          final result = builder.importLibraryElement(library.uri);
+          final result = builder.importLibraryElement(libraryUri);
           if (result.prefix != null) {
             newInsertText = '${result.prefix}.$newInsertText';
           }
@@ -169,21 +120,30 @@
               arguments: [workspaceEdit]);
         }
 
-        // Documentation is added on during resolve for LSP.
         final formats = clientCapabilities.completionDocumentationFormats;
-        final supportsInsertReplace =
-            clientCapabilities.insertReplaceCompletionRanges;
         final dartDoc =
-            analyzer.getDartDocPlainText(requestedElement.documentationComment);
+            analyzer.getDartDocPlainText(element.documentationComment);
         final documentation =
             dartDoc != null ? asStringOrMarkupContent(formats, dartDoc) : null;
+        final supportsInsertReplace =
+            clientCapabilities.insertReplaceCompletionRanges;
+
+        // If the only URI we have is a file:// URI, display it as relative to
+        // the file we're importing into, rather than the full URI.
+        final pathContext = server.resourceProvider.pathContext;
+        final autoImportDisplayUri = libraryUri.isScheme('file')
+            ? pathContext.relative(
+                libraryUri.toFilePath(),
+                from: pathContext.dirname(file),
+              )
+            : libraryUri.toString();
 
         return success(CompletionItem(
           label: item.label,
           kind: item.kind,
           tags: item.tags,
           detail: thisFilesChanges.isNotEmpty
-              ? "Auto import from '${data.displayUri}'\n\n${item.detail ?? ''}"
+              ? "Auto import from '$autoImportDisplayUri'\n\n${item.detail ?? ''}"
                   .trim()
               : item.detail,
           documentation: documentation,
@@ -193,17 +153,17 @@
           filterText: item.filterText,
           insertText: newInsertText,
           insertTextFormat: item.insertTextFormat,
-          textEdit: supportsInsertReplace && data.iLength != data.rLength
+          textEdit: supportsInsertReplace && insertionRange != replacementRange
               ? Either2<TextEdit, InsertReplaceEdit>.t2(
                   InsertReplaceEdit(
-                    insert: toRange(lineInfo, data.rOffset, data.iLength),
-                    replace: toRange(lineInfo, data.rOffset, data.rLength),
+                    insert: insertionRange,
+                    replace: replacementRange,
                     newText: newInsertText,
                   ),
                 )
               : Either2<TextEdit, InsertReplaceEdit>.t1(
                   TextEdit(
-                    range: toRange(lineInfo, data.rOffset, data.rLength),
+                    range: replacementRange,
                     newText: newInsertText,
                   ),
                 ),
@@ -229,6 +189,52 @@
     );
   }
 
+  Future<ErrorOr<CompletionItem>> resolveDartSuggestionSetCompletion(
+    CompletionItem item,
+    DartSuggestionSetCompletionItemResolutionInfo data,
+    CancellationToken token,
+  ) async {
+    final clientCapabilities = server.clientCapabilities;
+    if (clientCapabilities == null) {
+      // This should not happen unless a client misbehaves.
+      return error(ErrorCodes.ServerNotInitialized,
+          'Requests not before server is initilized');
+    }
+
+    final file = data.file;
+    final lineInfo = server.getLineInfo(file);
+    if (lineInfo == null) {
+      return error(
+        ErrorCodes.InternalError,
+        'Line info not available for $file',
+        null,
+      );
+    }
+
+    var library = server.declarationsTracker?.getLibrary(data.libId);
+    if (library == null) {
+      return error(
+        ErrorCodes.InvalidParams,
+        'Library ID is not valid: ${data.libId}',
+        data.libId.toString(),
+      );
+    }
+
+    final insertionRange = toRange(lineInfo, data.rOffset, data.iLength);
+    final replacementRange = toRange(lineInfo, data.rOffset, data.rLength);
+
+    return resolveDartCompletion(
+      item,
+      clientCapabilities,
+      lineInfo,
+      token,
+      file: file,
+      libraryUri: library.uri,
+      insertionRange: insertionRange,
+      replacementRange: replacementRange,
+    );
+  }
+
   Future<ErrorOr<CompletionItem>> resolvePubPackageCompletion(
     CompletionItem item,
     PubPackageCompletionItemResolutionInfo data,
@@ -265,4 +271,31 @@
       data: item.data,
     ));
   }
+
+  /// Gets the [Element] for the completion item [item] in [libraryUri].
+  Future<Element?> _getElement(
+    AnalysisSession session,
+    Uri libraryUri,
+    CompletionItem item,
+  ) async {
+    // If filterText is different to the label, it's because label has
+    // parens/args appended so we should take the filterText to get the
+    // elements name without. We cannot use insertText as it may include
+    // snippets, whereas filterText is always just the pure string.
+    var name = item.filterText ?? item.label;
+
+    // The label might be `MyEnum.myValue`, but we need to find `MyEnum`.
+    if (name.contains('.')) {
+      name = name.substring(0, name.indexOf('.'));
+    }
+
+    // TODO(dantup): This is not handling default constructors or enums
+    // correctly, so they will both show dart docs from the class/enum and not
+    // the constructor/enum member.
+
+    final result = await session.getLibraryByUri(libraryUri.toString());
+    return result is LibraryElementResult
+        ? result.element.exportNamespace.get(name)
+        : null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index 68e112e..b5d7f7d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -50,16 +50,22 @@
     final content = StringBuffer();
     const divider = '---';
 
-    // Description.
-    if (hover.elementDescription != null) {
+    // Description + Types.
+    final elementDescription = hover.elementDescription;
+    final staticType = hover.staticType;
+    final isDeprecated = hover.isDeprecated ?? false;
+    if (elementDescription != null) {
       content.writeln('```dart');
-      if (hover.isDeprecated ?? false) {
+      if (isDeprecated) {
         content.write('(deprecated) ');
       }
       content
-        ..writeln(hover.elementDescription)
+        ..writeln(elementDescription)
         ..writeln('```');
     }
+    if (staticType != null) {
+      content.writeln('Type: `$staticType`');
+    }
 
     // Source library.
     final containingLibraryName = hover.containingLibraryName;
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 146b2c1..290bdc4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -29,7 +29,7 @@
       params.initializationOptions,
     );
 
-    final openWorkspacePaths = <String>[];
+    final unnormalisedWorkspacePaths = <String>[];
     final workspaceFolders = params.workspaceFolders;
     final rootUri = params.rootUri;
     final rootPath = params.rootPath;
@@ -43,23 +43,30 @@
           // Only file URIs are supported, but there's no way to signal this to
           // the LSP client (and certainly not before initialization).
           if (uri.isScheme('file')) {
-            openWorkspacePaths.add(uri.toFilePath());
+            unnormalisedWorkspacePaths.add(uri.toFilePath());
           }
         });
       }
       if (rootUri != null) {
         final uri = Uri.parse(rootUri);
         if (uri.isScheme('file')) {
-          openWorkspacePaths.add(uri.toFilePath());
+          unnormalisedWorkspacePaths.add(uri.toFilePath());
         }
       } else if (rootPath != null) {
-        openWorkspacePaths.add(rootPath);
+        unnormalisedWorkspacePaths.add(rootPath);
       }
     }
 
+    final pathContext = server.resourceProvider.pathContext;
+    // Normalise all potential workspace folder paths as these may contain
+    // trailing slashes (the LSP spec does not specific if folders
+    // should/should not have them) and the analysis roots must be normalized.
+    final workspacePaths =
+        unnormalisedWorkspacePaths.map(pathContext.normalize).toList();
+
     server.messageHandler = InitializingStateMessageHandler(
       server,
-      openWorkspacePaths,
+      workspacePaths,
     );
 
     final capabilities = server.capabilitiesComputer
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 0d9eb19..abc53cf 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -61,6 +61,7 @@
   InitializedStateMessageHandler(
     LspAnalysisServer server,
   ) : super(server) {
+    final options = server.initializationOptions;
     reject(Method.initialize, ServerErrorCodes.ServerAlreadyInitialized,
         'Server already initialized');
     reject(Method.initialized, ServerErrorCodes.ServerAlreadyInitialized,
@@ -75,13 +76,10 @@
       TextDocumentCloseHandler(server),
     );
     registerHandler(HoverHandler(server));
-    registerHandler(CompletionHandler(
-      server,
-      server.initializationOptions.suggestFromUnimportedLibraries,
-    ));
+    registerHandler(CompletionHandler(server, options));
+    registerHandler(CompletionResolveHandler(server));
     registerHandler(DocumentColorHandler(server));
     registerHandler(DocumentColorPresentationHandler(server));
-    registerHandler(CompletionResolveHandler(server));
     registerHandler(SignatureHelpHandler(server));
     registerHandler(DefinitionHandler(server));
     registerHandler(SuperHandler(server));
@@ -94,12 +92,8 @@
     registerHandler(DocumentSymbolHandler(server));
     registerHandler(CodeActionHandler(server));
     registerHandler(ExecuteCommandHandler(server));
-    registerHandler(
-      WorkspaceFoldersHandler(
-        server,
-        !server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles,
-      ),
-    );
+    registerHandler(WorkspaceFoldersHandler(
+        server, !options.onlyAnalyzeProjectsWithOpenFiles));
     registerHandler(PrepareRenameHandler(server));
     registerHandler(RenameHandler(server));
     registerHandler(FoldingHandler(server));
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index 003917f..8e5f7c6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -70,8 +70,8 @@
   FutureOr<ErrorOr<Null>> handle(
       DidCloseTextDocumentParams params, CancellationToken token) {
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) {
-      server.removePriorityFile(path);
+    return path.mapResult((path) async {
+      await server.removePriorityFile(path);
       server.documentVersions.remove(path);
       server.onOverlayDestroyed(path);
 
@@ -96,7 +96,7 @@
       DidOpenTextDocumentParams params, CancellationToken token) {
     final doc = params.textDocument;
     final path = pathOfDocItem(doc);
-    return path.mapResult((path) {
+    return path.mapResult((path) async {
       // We don't get a OptionalVersionedTextDocumentIdentifier with a didOpen but we
       // do get the necessary info to create one.
       server.documentVersions[path] = VersionedTextDocumentIdentifier(
@@ -109,7 +109,7 @@
       // analyzed. Add it to driver to which it should have been added.
       server.contextManager.getDriverFor(path)?.addFile(path);
 
-      server.addPriorityFile(path);
+      await server.addPriorityFile(path);
 
       return success(null);
     });
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index e4e8d17..d0300bb 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -186,7 +186,7 @@
   RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
       RefactoringWorkspace(driverMap.values, searchEngine);
 
-  void addPriorityFile(String filePath) {
+  Future<void> addPriorityFile(String filePath) async {
     // When pubspecs are opened, trigger pre-loading of pub package names and
     // versions.
     if (file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
@@ -197,7 +197,7 @@
     assert(didAdd);
     if (didAdd) {
       _updateDriversAndPluginsPriorityFiles();
-      _refreshAnalysisRoots();
+      await _refreshAnalysisRoots();
     }
   }
 
@@ -251,7 +251,7 @@
         clientConfiguration.replace(newGlobalConfig, workspaceFolderConfig);
 
         if (clientConfiguration.affectsAnalysisRoots(oldGlobalConfig)) {
-          _refreshAnalysisRoots();
+          await _refreshAnalysisRoots();
         }
       }
     }
@@ -497,12 +497,12 @@
     sendNotification(message);
   }
 
-  void removePriorityFile(String path) {
+  Future<void> removePriorityFile(String path) async {
     final didRemove = priorityFiles.remove(path);
     assert(didRemove);
     if (didRemove) {
       _updateDriversAndPluginsPriorityFiles();
-      _refreshAnalysisRoots();
+      await _refreshAnalysisRoots();
     }
   }
 
@@ -680,7 +680,7 @@
 
     await fetchClientConfigurationAndPerformDynamicRegistration();
 
-    _refreshAnalysisRoots();
+    await _refreshAnalysisRoots();
   }
 
   void _afterOverlayChanged(String path, plugin.HasToJson changeForPlugins) {
@@ -725,7 +725,7 @@
     capabilitiesComputer.performDynamicRegistration();
   }
 
-  void _refreshAnalysisRoots() {
+  Future<void> _refreshAnalysisRoots() async {
     // When there are open folders, they are always the roots. If there are no
     // open workspace folders, then we use the open (priority) files to compute
     // roots.
@@ -747,7 +747,8 @@
 
     notificationManager.setAnalysisRoots(
         includedPaths.toList(), excludedPaths.toList());
-    contextManager.setRoots(includedPaths.toList(), excludedPaths.toList());
+    await contextManager.setRoots(
+        includedPaths.toList(), excludedPaths.toList());
   }
 
   void _updateDriversAndPluginsPriorityFiles() {
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 8a26c20..c182eee 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -418,7 +418,7 @@
         ? InsertTextMode.asIs
         : null,
     // data, used for completionItem/resolve.
-    data: lsp.DartCompletionItemResolutionInfo(
+    data: lsp.DartSuggestionSetCompletionItemResolutionInfo(
         file: file,
         offset: offset,
         libId: includedSuggestionSet.id,
@@ -683,6 +683,36 @@
 bool isDartDocument(lsp.TextDocumentIdentifier? doc) =>
     doc?.uri.endsWith('.dart') ?? false;
 
+/// Converts a [server.Location] to an [lsp.Range] by translating the
+/// offset/length using a `LineInfo`.
+///
+/// This function ignores any line/column info on the
+/// [server.Location] assuming it is either not available not unreliable.
+lsp.Range locationOffsetLenToRange(
+        server.LineInfo lineInfo, server.Location location) =>
+    toRange(lineInfo, location.offset, location.length);
+
+/// Converts a [server.Location] to an [lsp.Range] if all line and column
+/// values are available.
+///
+/// Returns null if any values are -1 or null.
+lsp.Range? locationToRange(server.Location location) {
+  final startLine = location.startLine;
+  final startColumn = location.startColumn;
+  final endLine = location.endLine ?? -1;
+  final endColumn = location.endColumn ?? -1;
+  if (startLine == -1 ||
+      startColumn == -1 ||
+      endLine == -1 ||
+      endColumn == -1) {
+    return null;
+  }
+  // LSP positions are 0-based but Location is 1-based.
+  return Range(
+      start: Position(line: startLine - 1, character: startColumn - 1),
+      end: Position(line: endLine - 1, character: endColumn - 1));
+}
+
 /// Merges two [WorkspaceEdit]s into a single one.
 ///
 /// Will throw if given [WorkspaceEdit]s that do not use documentChanges.
@@ -800,10 +830,12 @@
     message = '$message\n${error.correction}';
   }
 
-  var lineInfo = getLineInfo(error.location.file);
+  final range = locationToRange(error.location) ??
+      locationOffsetLenToRange(
+          getLineInfo(error.location.file), error.location);
   var documentationUrl = error.url;
   return lsp.Diagnostic(
-    range: toRange(lineInfo, error.location.offset, error.location.length),
+    range: range,
     severity: pluginToDiagnosticSeverity(error.severity),
     code: error.code,
     source: languageSourceName,
@@ -831,6 +863,9 @@
   return lsp.DiagnosticRelatedInformation(
       location: lsp.Location(
         uri: Uri.file(file).toString(),
+        // TODO(dantup): Switch to using line/col information from the context
+        // message once confirmed that AnalyzerConverter is not using the wrong
+        // LineInfo.
         range: toRange(
           lineInfo,
           message.location.offset,
@@ -972,10 +1007,9 @@
 lsp.CompletionItem toCompletionItem(
   LspClientCapabilities capabilities,
   server.LineInfo lineInfo,
-  server.CompletionSuggestion suggestion,
-  int replacementOffset,
-  int insertLength,
-  int replacementLength, {
+  server.CompletionSuggestion suggestion, {
+  Range? replacementRange,
+  Range? insertionRange,
   required bool includeCommitCharacters,
   required bool completeFunctionCalls,
   CompletionItemResolutionInfo? resolutionData,
@@ -1092,20 +1126,22 @@
     insertTextMode: supportsAsIsInsertMode && isMultilineCompletion
         ? InsertTextMode.asIs
         : null,
-    textEdit: supportsInsertReplace && insertLength != replacementLength
-        ? Either2<TextEdit, InsertReplaceEdit>.t2(
-            InsertReplaceEdit(
-              insert: toRange(lineInfo, replacementOffset, insertLength),
-              replace: toRange(lineInfo, replacementOffset, replacementLength),
-              newText: insertText,
-            ),
-          )
-        : Either2<TextEdit, InsertReplaceEdit>.t1(
-            TextEdit(
-              range: toRange(lineInfo, replacementOffset, replacementLength),
-              newText: insertText,
-            ),
-          ),
+    textEdit: (insertionRange == null || replacementRange == null)
+        ? null
+        : supportsInsertReplace && insertionRange != replacementRange
+            ? Either2<TextEdit, InsertReplaceEdit>.t2(
+                InsertReplaceEdit(
+                  insert: insertionRange,
+                  replace: replacementRange,
+                  newText: insertText,
+                ),
+              )
+            : Either2<TextEdit, InsertReplaceEdit>.t1(
+                TextEdit(
+                  range: replacementRange,
+                  newText: insertText,
+                ),
+              ),
   );
 }
 
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
index 18b0a43..68e43fd 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -25,16 +25,35 @@
     CustomSemanticTokenModifiers.importPrefix,
   },
   HighlightRegionType.INSTANCE_FIELD_DECLARATION: {
-    SemanticTokenModifiers.declaration
+    SemanticTokenModifiers.declaration,
+    CustomSemanticTokenModifiers.instance
+  },
+  HighlightRegionType.INSTANCE_FIELD_REFERENCE: {
+    CustomSemanticTokenModifiers.instance
   },
   HighlightRegionType.INSTANCE_GETTER_DECLARATION: {
-    SemanticTokenModifiers.declaration
+    SemanticTokenModifiers.declaration,
+    CustomSemanticTokenModifiers.instance
+  },
+  HighlightRegionType.INSTANCE_GETTER_REFERENCE: {
+    CustomSemanticTokenModifiers.instance
   },
   HighlightRegionType.INSTANCE_METHOD_DECLARATION: {
-    SemanticTokenModifiers.declaration
+    SemanticTokenModifiers.declaration,
+    CustomSemanticTokenModifiers.instance
+  },
+  HighlightRegionType.INSTANCE_METHOD_REFERENCE: {
+    CustomSemanticTokenModifiers.instance
+  },
+  HighlightRegionType.INSTANCE_METHOD_TEAR_OFF: {
+    CustomSemanticTokenModifiers.instance
   },
   HighlightRegionType.INSTANCE_SETTER_DECLARATION: {
-    SemanticTokenModifiers.declaration
+    SemanticTokenModifiers.declaration,
+    CustomSemanticTokenModifiers.instance
+  },
+  HighlightRegionType.INSTANCE_SETTER_REFERENCE: {
+    CustomSemanticTokenModifiers.instance
   },
   HighlightRegionType.LOCAL_FUNCTION_DECLARATION: {
     SemanticTokenModifiers.declaration
@@ -104,6 +123,7 @@
   HighlightRegionType.DYNAMIC_PARAMETER_REFERENCE: SemanticTokenTypes.parameter,
   HighlightRegionType.ENUM: SemanticTokenTypes.enum_,
   HighlightRegionType.ENUM_CONSTANT: SemanticTokenTypes.enumMember,
+  HighlightRegionType.EXTENSION: SemanticTokenTypes.class_,
   HighlightRegionType.FUNCTION_TYPE_ALIAS: SemanticTokenTypes.type,
   HighlightRegionType.IDENTIFIER_DEFAULT: CustomSemanticTokenTypes.source,
   HighlightRegionType.IMPORT_PREFIX: SemanticTokenTypes.variable,
diff --git a/pkg/analysis_server/lib/src/server/debounce_requests.dart b/pkg/analysis_server/lib/src/server/debounce_requests.dart
index 4ee01d6..35845fc 100644
--- a/pkg/analysis_server/lib/src/server/debounce_requests.dart
+++ b/pkg/analysis_server/lib/src/server/debounce_requests.dart
@@ -68,7 +68,7 @@
           var params = CompletionGetSuggestions2Params.fromRequest(request);
           var offset = params.offset;
           channel.sendResponse(
-            CompletionGetSuggestions2Result(offset, 0, [], [], true)
+            CompletionGetSuggestions2Result(offset, 0, [], true)
                 .toResponse(request.id),
           );
           continue;
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 4193128..b2ef7d6d 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
@@ -26,6 +26,7 @@
 import 'package:analysis_server/src/services/completion/dart/relevance_tables.g.dart';
 import 'package:analysis_server/src/services/completion/dart/static_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/dart/super_formal_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
@@ -96,7 +97,7 @@
   /// that are not yet imported, but could be imported into the requested
   /// target. It is up to the client to make copies of [CompletionSuggestion]s
   /// with the import index property updated.
-  final Map<protocol.CompletionSuggestion, Uri>? notImportedSuggestions;
+  final NotImportedSuggestions? notImportedSuggestions;
 
   /// Initialize a newly created completion manager. The parameters
   /// [includedElementKinds], [includedElementNames], and
@@ -153,6 +154,7 @@
       if (enableOverrideContributor) OverrideContributor(request, builder),
       RedirectingContributor(request, builder),
       StaticMemberContributor(request, builder),
+      SuperFormalContributor(request, builder),
       TypeMemberContributor(request, builder),
       if (enableUriContributor) UriContributor(request, builder),
       VariableNameContributor(request, builder),
@@ -498,3 +500,12 @@
     }
   }
 }
+
+/// Information provided by [NotImportedContributor] in addition to suggestions.
+class NotImportedSuggestions {
+  final Set<protocol.CompletionSuggestion> set = Set.identity();
+
+  /// This flag is set to `true` if the contributor decided to stop before it
+  /// processed all available libraries, e.g. we ran out of budget.
+  bool isIncomplete = false;
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 3b4f5f2..acfcb38 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -37,29 +37,23 @@
         return;
       }
 
-      var classOrMixin = request.target.containingNode
-          .thisOrAncestorOfType<ClassOrMixinDeclaration>();
-      if (classOrMixin != null) {
-        var type = classOrMixin.declaredElement?.thisType;
-        if (type != null) {
-          _addExtensionMembers(extensions, defaultKind, type);
-        }
+      var thisClassType = request.target.enclosingClassElement?.thisType;
+      if (thisClassType != null) {
+        _addExtensionMembers(extensions, defaultKind, thisClassType);
       } else {
-        var extension = request.target.containingNode
-            .thisOrAncestorOfType<ExtensionDeclaration>();
-        if (extension != null) {
-          var extendedType = extension.extendedType.type;
-          if (extendedType is InterfaceType) {
-            var types = [extendedType, ...extendedType.allSupertypes];
-            for (var type in types) {
-              var inheritanceDistance = memberBuilder.request.featureComputer
-                  .inheritanceDistanceFeature(
-                      extendedType.element, type.element);
-              _addTypeMembers(type, defaultKind, inheritanceDistance);
-            }
-            _addExtensionMembers(extensions, defaultKind, extendedType);
+        var thisExtendedType =
+            request.target.enclosingExtensionElement?.extendedType;
+        if (thisExtendedType is InterfaceType) {
+          var types = [thisExtendedType, ...thisExtendedType.allSupertypes];
+          for (var type in types) {
+            var inheritanceDistance = memberBuilder.request.featureComputer
+                .inheritanceDistanceFeature(
+                    thisExtendedType.element, type.element);
+            _addTypeMembers(type, defaultKind, inheritanceDistance);
           }
+          _addExtensionMembers(extensions, defaultKind, thisExtendedType);
         }
+        // TODO(scheglov) It seems that we don't support non-interface types.
       }
       return;
     }
@@ -114,7 +108,7 @@
   }
 
   void _addExtensionMembers(List<ExtensionElement> extensions,
-      CompletionSuggestionKind? kind, DartType type) {
+      CompletionSuggestionKind kind, DartType type) {
     var applicableExtensions = extensions.applicableTo(
       targetLibrary: request.libraryElement,
       targetType: type,
@@ -134,7 +128,7 @@
   }
 
   void _addInstanceMembers(ExtensionElement extension,
-      CompletionSuggestionKind? kind, double inheritanceDistance) {
+      CompletionSuggestionKind kind, double inheritanceDistance) {
     for (var method in extension.methods) {
       if (!method.isStatic) {
         memberBuilder.addSuggestionForMethod(
@@ -151,7 +145,7 @@
     }
   }
 
-  void _addTypeMembers(InterfaceType type, CompletionSuggestionKind? kind,
+  void _addTypeMembers(InterfaceType type, CompletionSuggestionKind kind,
       double inheritanceDistance) {
     for (var method in type.methods) {
       memberBuilder.addSuggestionForMethod(
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 1dd0f73..983ff52 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -14,18 +14,7 @@
 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'
-    show
-        ClassElement,
-        ConstructorElement,
-        Element,
-        ElementKind,
-        FieldElement,
-        FunctionElement,
-        LibraryElement,
-        LocalVariableElement,
-        PropertyAccessorElement,
-        TopLevelVariableElement;
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/dart/element/type_system.dart';
@@ -60,6 +49,7 @@
     double hasDeprecated = 0.0,
     double isConstant = 0.0,
     double isNoSuchMethod = 0.0,
+    double isNotImported = 0.0,
     double keyword = 0.0,
     double startsWithDollar = 0.0,
     double superMatches = 0.0}) {
@@ -68,6 +58,7 @@
   assert(hasDeprecated.between(-1.0, 0.0));
   assert(isConstant.between(0.0, 1.0));
   assert(isNoSuchMethod.between(-1.0, 0.0));
+  assert(isNotImported.between(-1.0, 0.0));
   assert(keyword.between(0.0, 1.0));
   assert(startsWithDollar.between(-1.0, 0.0));
   assert(superMatches.between(0.0, 1.0));
@@ -77,6 +68,7 @@
     hasDeprecated,
     isConstant,
     isNoSuchMethod,
+    isNotImported,
     keyword,
     startsWithDollar,
     superMatches,
@@ -147,6 +139,7 @@
     0.50, // hasDeprecated
     1.00, // isConstant
     1.00, // isNoSuchMethod
+    1.00, // isNotImported
     1.00, // keyword
     0.50, // startsWithDollar
     1.00, // superMatches
@@ -328,6 +321,11 @@
         : 0.0;
   }
 
+  /// Return the feature for the not-yet-imported property.
+  double isNotImportedFeature(bool isNotImported) {
+    return isNotImported ? -1.0 : 0.0;
+  }
+
   /// Return the value of the _keyword_ feature for the [keyword] when
   /// completing at the given [completionLocation].
   double keywordFeature(String keyword, String? completionLocation) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 864f1f9..1dbfe52 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -352,6 +352,9 @@
     var constructorDeclaration =
         node.thisOrAncestorOfType<ConstructorDeclaration>();
     if (constructorDeclaration != null) {
+      if (request.featureSet.isEnabled(Feature.super_parameters)) {
+        _addSuggestion(Keyword.SUPER);
+      }
       _addSuggestion(Keyword.THIS);
     }
     final entity = this.entity;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 2441362..7659c35 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -46,7 +46,7 @@
   @override
   void visitClassElement(ClassElement element) {
     if (opType.includeTypeNameSuggestions) {
-      builder.suggestClass(element, kind: kind, prefix: prefix);
+      builder.suggestClass(element, prefix: prefix);
     }
     if (opType.includeConstructorSuggestions) {
       _addConstructorSuggestions(element);
@@ -135,12 +135,16 @@
   }
 
   /// Add constructor suggestions for the given class.
-  void _addConstructorSuggestions(ClassElement classElem) {
-    for (var constructor in classElem.constructors) {
+  void _addConstructorSuggestions(ClassElement element) {
+    if (element.isEnum) {
+      return;
+    }
+
+    for (var constructor in element.constructors) {
       if (constructor.isPrivate) {
         continue;
       }
-      if (classElem.isAbstract && !constructor.isFactory) {
+      if (element.isAbstract && !constructor.isFactory) {
         continue;
       }
       builder.suggestConstructor(constructor, kind: kind, prefix: prefix);
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 ca8280c..b3a1499 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
@@ -25,7 +25,7 @@
   late MemberSuggestionBuilder memberBuilder;
 
   /// The kind of suggestion to make.
-  CompletionSuggestionKind? classMemberSuggestionKind;
+  late CompletionSuggestionKind classMemberSuggestionKind;
 
   /// The [_VisibilityTracker] tracks the set of elements already added in the
   /// completion list, this object helps prevents suggesting elements that have
@@ -213,7 +213,7 @@
     var classElt = declaration.declaredElement;
     if (classElt != null && visibilityTracker._isVisible(classElt)) {
       if (opType.includeTypeNameSuggestions) {
-        builder.suggestClass(classElt, kind: _defaultKind);
+        builder.suggestClass(classElt);
       }
 
       // Generate the suggestions for the constructors. We are required to loop
@@ -234,7 +234,7 @@
   void declaredClassTypeAlias(ClassTypeAlias declaration) {
     var declaredElement = declaration.declaredElement;
     if (declaredElement != null && opType.includeTypeNameSuggestions) {
-      builder.suggestClass(declaredElement, kind: _defaultKind);
+      builder.suggestClass(declaredElement);
     }
   }
 
@@ -249,7 +249,7 @@
     if (declaredElement != null &&
         visibilityTracker._isVisible(declaredElement) &&
         opType.includeTypeNameSuggestions) {
-      builder.suggestClass(declaredElement, kind: _defaultKind);
+      builder.suggestClass(declaredElement);
       for (var enumConstant in declaration.constants) {
         if (!enumConstant.isSynthetic) {
           var constantElement = enumConstant.declaredElement;
@@ -314,8 +314,7 @@
       if (declaredElement is FunctionElement) {
         builder.suggestTopLevelFunction(declaredElement, kind: _defaultKind);
       } else if (declaredElement is PropertyAccessorElement) {
-        builder.suggestTopLevelPropertyAccessor(declaredElement,
-            kind: _defaultKind);
+        builder.suggestTopLevelPropertyAccessor(declaredElement);
       }
     }
   }
@@ -324,7 +323,7 @@
   void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
     var declaredElement = declaration.declaredElement;
     if (declaredElement != null && opType.includeTypeNameSuggestions) {
-      builder.suggestTypeAlias(declaredElement, kind: _defaultKind);
+      builder.suggestTypeAlias(declaredElement);
     }
   }
 
@@ -333,7 +332,7 @@
     var declaredElement = declaration.declaredElement;
     if (declaredElement is TypeAliasElement &&
         opType.includeTypeNameSuggestions) {
-      builder.suggestTypeAlias(declaredElement, kind: _defaultKind);
+      builder.suggestTypeAlias(declaredElement);
     }
   }
 
@@ -385,7 +384,7 @@
         declaredElement != null &&
         visibilityTracker._isVisible(declaredElement) &&
         opType.includeTypeNameSuggestions) {
-      builder.suggestClass(declaredElement, kind: _defaultKind);
+      builder.suggestClass(declaredElement);
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 070294f..8bbff4f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
@@ -16,13 +15,18 @@
 /// A contributor of suggestions from not yet imported libraries.
 class NotImportedContributor extends DartCompletionContributor {
   final CompletionBudget budget;
-  final Map<protocol.CompletionSuggestion, Uri> notImportedSuggestions;
+  final NotImportedSuggestions additionalData;
+
+  /// When a library is imported with combinators, we cannot skip it, there
+  /// might be elements that were excluded, but should be suggested. So, here
+  /// we record elements that are already imported.
+  final Set<Element> _importedElements = Set.identity();
 
   NotImportedContributor(
     DartCompletionRequest request,
     SuggestionBuilder builder,
     this.budget,
-    this.notImportedSuggestions,
+    this.additionalData,
   ) : super(request, builder);
 
   @override
@@ -37,15 +41,31 @@
     try {
       await analysisDriver.discoverAvailableFiles().timeout(budget.left);
     } on TimeoutException {
+      additionalData.isIncomplete = true;
       return;
     }
 
+    var importedLibraries = Set<LibraryElement>.identity();
+    for (var import in request.libraryElement.imports) {
+      var importedLibrary = import.importedLibrary;
+      if (importedLibrary != null) {
+        if (import.combinators.isEmpty) {
+          importedLibraries.add(importedLibrary);
+        } else {
+          _importedElements.addAll(
+            import.namespace.definedNames.values,
+          );
+        }
+      }
+    }
+
     // Use single instance to track getter / setter pairs.
     var extensionContributor = ExtensionMemberContributor(request, builder);
 
     var knownFiles = fsState.knownFiles.toList();
     for (var file in knownFiles) {
       if (budget.isEmpty) {
+        additionalData.isIncomplete = true;
         return;
       }
 
@@ -54,16 +74,17 @@
       }
 
       var element = analysisDriver.getLibraryByFile(file);
-      if (element == null) {
+      if (element == null || importedLibraries.contains(element)) {
         continue;
       }
 
       var exportNamespace = element.exportNamespace;
       var exportElements = exportNamespace.definedNames.values.toList();
 
+      builder.isNotImportedLibrary = true;
       builder.laterReplacesEarlier = false;
       builder.suggestionAdded = (suggestion) {
-        notImportedSuggestions[suggestion] = file.uri;
+        additionalData.set.add(suggestion);
       };
 
       if (request.includeIdentifiers) {
@@ -71,18 +92,34 @@
       }
 
       extensionContributor.addExtensions(
-        exportElements.whereType<ExtensionElement>().toList(),
+        _extensions(exportElements),
       );
-    }
 
-    builder.laterReplacesEarlier = true;
-    builder.suggestionAdded = null;
+      builder.isNotImportedLibrary = false;
+      builder.laterReplacesEarlier = true;
+      builder.suggestionAdded = null;
+    }
   }
 
   void _buildSuggestions(List<Element> elements) {
     var visitor = LibraryElementSuggestionBuilder(request, builder);
     for (var element in elements) {
-      element.accept(visitor);
+      if (!_importedElements.contains(element)) {
+        element.accept(visitor);
+      }
     }
   }
+
+  /// This function intentionally does not use `whereType` for performance.
+  ///
+  /// https://github.com/dart-lang/sdk/issues/47680
+  static List<ExtensionElement> _extensions(List<Element> elements) {
+    var extensions = <ExtensionElement>[];
+    for (var element in elements) {
+      if (element is ExtensionElement) {
+        extensions.add(element);
+      }
+    }
+    return extensions;
+  }
 }
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 72174fe..128ff49 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
@@ -71,6 +71,7 @@
 
   SimpleIdentifier? _getTargetIdFromVarList(VariableDeclarationList fields) {
     var variables = fields.variables;
+    var type = fields.type;
     if (variables.length == 1) {
       var variable = variables[0];
       var targetId = variable.name;
@@ -81,10 +82,23 @@
         //   where _s_ is a synthetic id inserted by the analyzer parser
         return targetId;
       } else if (fields.keyword == null &&
-          fields.type == null &&
+          type == null &&
           variable.initializer == null) {
         // fasta parser does not insert a synthetic identifier
         return targetId;
+      } else if (fields.keyword == null &&
+          type is NamedType &&
+          type.typeArguments == null &&
+          variable.initializer == null) {
+        //  class A extends B {
+        //    m^
+        //
+        //    String foo;
+        //  }
+        // Parses as a variable list where `m` is the type and `String` is a
+        // variable.
+        var name = type.name;
+        return name is SimpleIdentifier ? name : null;
       }
     }
     return null;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 62adabb..d0f8af8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
@@ -56,7 +57,11 @@
         }
         for (var method in element.methods) {
           if (method.isStatic && isVisible(method)) {
-            builder.suggestMethod(method, inheritanceDistance: 0.0);
+            builder.suggestMethod(
+              method,
+              kind: protocol.CompletionSuggestionKind.INVOCATION,
+              inheritanceDistance: 0.0,
+            );
           }
         }
       } else if (element is ExtensionElement) {
@@ -74,7 +79,11 @@
         }
         for (var method in element.methods) {
           if (method.isStatic && isVisible(method)) {
-            builder.suggestMethod(method, inheritanceDistance: 0.0);
+            builder.suggestMethod(
+              method,
+              kind: protocol.CompletionSuggestionKind.INVOCATION,
+              inheritanceDistance: 0.0,
+            );
           }
         }
       }
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 0e7d181..829a3e5 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
@@ -87,7 +87,7 @@
   /// Add a suggestion for the given [method].
   void addSuggestionForMethod(
       {required MethodElement method,
-      CompletionSuggestionKind? kind,
+      required CompletionSuggestionKind kind,
       required double inheritanceDistance}) {
     if (method.isAccessibleIn(request.libraryElement) &&
         _shouldAddSuggestion(method)) {
@@ -181,6 +181,10 @@
   final Map<String, CompletionSuggestion> _suggestionMap =
       <String, CompletionSuggestion>{};
 
+  /// This flag is set to `true` while adding suggestions for top-level
+  /// elements from not-yet-imported libraries.
+  bool isNotImportedLibrary = false;
+
   /// A flag indicating whether a suggestion should replace any earlier
   /// suggestions for the same completion (`true`) or whether earlier
   /// suggestions should take priority over more recent suggestions.
@@ -269,11 +273,19 @@
         elementKind: elementKind,
         hasDeprecated: hasDeprecated,
         isConstant: isConstant,
+        isNotImported:
+            request.featureComputer.isNotImportedFeature(isNotImportedLibrary),
         startsWithDollar: startsWithDollar,
         superMatches: superMatches,
         inheritanceDistance: inheritanceDistance,
       );
-      _add(_createSuggestion(accessor, relevance: relevance));
+      _add(
+        _createSuggestion(
+          accessor,
+          kind: CompletionSuggestionKind.IDENTIFIER,
+          relevance: relevance,
+        ),
+      );
     }
   }
 
@@ -291,20 +303,29 @@
       elementKind: elementKind,
       isConstant: isConstant,
     );
-    _add(_createSuggestion(parameter,
-        elementKind: protocol.ElementKind.PARAMETER, relevance: relevance));
+    _add(
+      _createSuggestion(
+        parameter,
+        elementKind: protocol.ElementKind.PARAMETER,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: relevance,
+      ),
+    );
   }
 
-  /// Add a suggestion for a [classElement]. If a [kind] is provided it will
-  /// be used as the kind for the suggestion. If the class can only be
+  /// Add a suggestion for a [classElement]. If the class can only be
   /// referenced using a prefix, then the [prefix] should be provided.
-  void suggestClass(ClassElement classElement,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      String? prefix}) {
+  void suggestClass(ClassElement classElement, {String? prefix}) {
     var relevance = _computeTopLevelRelevance(classElement,
         elementType: _instantiateClassElement(classElement));
-    _add(_createSuggestion(classElement,
-        kind: kind, prefix: prefix, relevance: relevance));
+    _add(
+      _createSuggestion(
+        classElement,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        prefix: prefix,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion to insert a closure matching the given function [type].
@@ -412,7 +433,7 @@
   void suggestElement(Element element,
       {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
     if (element is ClassElement) {
-      suggestClass(element, kind: kind);
+      suggestClass(element);
     } else if (element is ConstructorElement) {
       suggestConstructor(element, kind: kind);
     } else if (element is ExtensionElement) {
@@ -422,9 +443,9 @@
       suggestTopLevelFunction(element, kind: kind);
     } else if (element is PropertyAccessorElement &&
         element.enclosingElement is CompilationUnitElement) {
-      suggestTopLevelPropertyAccessor(element, kind: kind);
+      suggestTopLevelPropertyAccessor(element);
     } else if (element is TypeAliasElement) {
-      suggestTypeAlias(element, kind: kind);
+      suggestTypeAlias(element);
     } else {
       throw ArgumentError('Cannot suggest a ${element.runtimeType}');
     }
@@ -439,8 +460,15 @@
     var completion = '$enumName.$constantName';
     var relevance =
         _computeTopLevelRelevance(constant, elementType: constant.type);
-    _add(_createSuggestion(constant,
-        completion: completion, prefix: prefix, relevance: relevance));
+    _add(
+      _createSuggestion(
+        constant,
+        completion: completion,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        prefix: prefix,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for an [extension]. If a [kind] is provided it will be
@@ -481,14 +509,26 @@
       superMatches: superMatches,
       inheritanceDistance: inheritanceDistance,
     );
-    _add(_createSuggestion(field, relevance: relevance));
+    _add(
+      _createSuggestion(
+        field,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion to reference a [field] in a field formal parameter.
   void suggestFieldFormalParameter(FieldElement field) {
     // TODO(brianwilkerson) Add a parameter (`bool includePrefix`) indicating
     //  whether to include the `this.` prefix in the completion.
-    _add(_createSuggestion(field, relevance: Relevance.fieldFormalParameter));
+    _add(
+      _createSuggestion(
+        field,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: Relevance.fieldFormalParameter,
+      ),
+    );
   }
 
   /// Add a suggestion for the `call` method defined on functions.
@@ -558,7 +598,13 @@
     // TODO(brianwilkerson) This might want to use the context type rather than
     //  a fixed value.
     var relevance = Relevance.loadLibrary;
-    _add(_createSuggestion(function, relevance: relevance));
+    _add(
+      _createSuggestion(
+        function,
+        kind: CompletionSuggestionKind.INVOCATION,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for a local [variable].
@@ -582,7 +628,13 @@
       isConstant: isConstant,
       localVariableDistance: localVariableDistance,
     );
-    _add(_createSuggestion(variable, relevance: relevance));
+    _add(
+      _createSuggestion(
+        variable,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for a [method]. If the method is being invoked with a
@@ -591,7 +643,8 @@
   /// used as the kind for the suggestion. The [inheritanceDistance] is the
   /// value of the inheritance distance feature computed for the method.
   void suggestMethod(MethodElement method,
-      {CompletionSuggestionKind? kind, required double inheritanceDistance}) {
+      {required CompletionSuggestionKind kind,
+      required double inheritanceDistance}) {
     // TODO(brianwilkerson) Refactor callers so that we're passing in the type
     //  of the target (assuming we don't already have that type available via
     //  the [request]) and compute the [inheritanceDistance] in this method.
@@ -615,6 +668,8 @@
       hasDeprecated: hasDeprecated,
       isConstant: isConstant,
       isNoSuchMethod: isNoSuchMethod,
+      isNotImported:
+          request.featureComputer.isNotImportedFeature(isNotImportedLibrary),
       startsWithDollar: startsWithDollar,
       superMatches: superMatches,
       inheritanceDistance: inheritanceDistance,
@@ -806,7 +861,13 @@
       elementKind: elementKind,
       isConstant: isConstant,
     );
-    _add(_createSuggestion(parameter, relevance: relevance));
+    _add(
+      _createSuggestion(
+        parameter,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for a [prefix] associated with a [library].
@@ -824,6 +885,17 @@
         relevance: relevance));
   }
 
+  /// Add a suggestion to reference a [parameter] in a super formal parameter.
+  void suggestSuperFormalParameter(ParameterElement parameter) {
+    _add(
+      _createSuggestion(
+        parameter,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: Relevance.superFormalParameter,
+      ),
+    );
+  }
+
   /// Add a suggestion for a top-level [function]. If a [kind] is provided it
   /// will be used as the kind for the suggestion. If the function can only be
   /// referenced using a prefix, then the [prefix] should be provided.
@@ -841,8 +913,7 @@
   /// can only be referenced using a prefix, then the [prefix] should be
   /// provided.
   void suggestTopLevelPropertyAccessor(PropertyAccessorElement accessor,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      String? prefix}) {
+      {String? prefix}) {
     assert(
         accessor.enclosingElement is CompilationUnitElement,
         'Enclosing element of ${accessor.runtimeType} is '
@@ -854,7 +925,7 @@
       if (accessor.isGetter) {
         var variable = accessor.variable;
         if (variable is TopLevelVariableElement) {
-          suggestTopLevelVariable(variable, kind: kind);
+          suggestTopLevelVariable(variable);
         }
       }
     } else {
@@ -875,10 +946,19 @@
         elementKind: elementKind,
         hasDeprecated: hasDeprecated,
         isConstant: isConstant,
+        isNotImported:
+            request.featureComputer.isNotImportedFeature(isNotImportedLibrary),
         startsWithDollar: startsWithDollar,
         superMatches: superMatches,
       );
-      _add(_createSuggestion(accessor, prefix: prefix, relevance: relevance));
+      _add(
+        _createSuggestion(
+          accessor,
+          kind: CompletionSuggestionKind.IDENTIFIER,
+          prefix: prefix,
+          relevance: relevance,
+        ),
+      );
     }
   }
 
@@ -886,25 +966,34 @@
   /// will be used as the kind for the suggestion. If the variable can only be
   /// referenced using a prefix, then the [prefix] should be provided.
   void suggestTopLevelVariable(TopLevelVariableElement variable,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      String? prefix}) {
+      {String? prefix}) {
     assert(variable.enclosingElement is CompilationUnitElement);
     var relevance =
         _computeTopLevelRelevance(variable, elementType: variable.type);
-    _add(_createSuggestion(variable,
-        kind: kind, prefix: prefix, relevance: relevance));
+    _add(
+      _createSuggestion(
+        variable,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        prefix: prefix,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for a [typeAlias]. If a [kind] is provided it
   /// will be used as the kind for the suggestion. If the alias can only be
   /// referenced using a prefix, then the [prefix] should be provided.
-  void suggestTypeAlias(TypeAliasElement typeAlias,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      String? prefix}) {
+  void suggestTypeAlias(TypeAliasElement typeAlias, {String? prefix}) {
     var relevance = _computeTopLevelRelevance(typeAlias,
         elementType: _instantiateTypeAlias(typeAlias));
-    _add(_createSuggestion(typeAlias,
-        kind: kind, prefix: prefix, relevance: relevance));
+    _add(
+      _createSuggestion(
+        typeAlias,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        prefix: prefix,
+        relevance: relevance,
+      ),
+    );
   }
 
   /// Add a suggestion for a type [parameter].
@@ -970,6 +1059,7 @@
       double hasDeprecated = 0.0,
       double isConstant = 0.0,
       double isNoSuchMethod = 0.0,
+      double isNotImported = 0.0,
       double keyword = 0.0,
       double startsWithDollar = 0.0,
       double superMatches = 0.0,
@@ -982,6 +1072,7 @@
         hasDeprecated: hasDeprecated,
         isConstant: isConstant,
         isNoSuchMethod: isNoSuchMethod,
+        isNotImported: isNotImported,
         keyword: keyword,
         startsWithDollar: startsWithDollar,
         superMatches: superMatches);
@@ -992,6 +1083,7 @@
       hasDeprecated: hasDeprecated,
       isConstant: isConstant,
       isNoSuchMethod: isNoSuchMethod,
+      isNotImported: isNotImported,
       keyword: keyword,
       startsWithDollar: startsWithDollar,
       superMatches: superMatches,
@@ -1022,6 +1114,8 @@
       elementKind: elementKind,
       hasDeprecated: hasDeprecated,
       isConstant: isConstant,
+      isNotImported:
+          request.featureComputer.isNotImportedFeature(isNotImportedLibrary),
     );
   }
 
@@ -1035,7 +1129,7 @@
   CompletionSuggestion? _createSuggestion(Element element,
       {String? completion,
       protocol.ElementKind? elementKind,
-      CompletionSuggestionKind? kind,
+      required CompletionSuggestionKind kind,
       String? prefix,
       required int relevance}) {
     var inputs = _CompletionSuggestionInputs(
@@ -1078,7 +1172,7 @@
     Element element, {
     required String? completion,
     required protocol.ElementKind? elementKind,
-    required CompletionSuggestionKind? kind,
+    required CompletionSuggestionKind kind,
     required String? prefix,
     required int relevance,
   }) {
@@ -1093,7 +1187,6 @@
     if (prefix != null && prefix.isNotEmpty) {
       completion = '$prefix.$completion';
     }
-    kind ??= CompletionSuggestionKind.INVOCATION;
     var suggestion = CompletionSuggestion(kind, relevance, completion,
         completion.length, 0, element.hasOrInheritsDeprecated, false);
 
@@ -1218,6 +1311,7 @@
       double hasDeprecated,
       double isConstant,
       double isNoSuchMethod,
+      double isNotImported,
       double keyword,
       double startsWithDollar,
       double superMatches,
@@ -1253,7 +1347,7 @@
 class _CompletionSuggestionInputs {
   final String? completion;
   final protocol.ElementKind? elementKind;
-  final CompletionSuggestionKind? kind;
+  final CompletionSuggestionKind kind;
   final String? prefix;
 
   _CompletionSuggestionInputs({
@@ -1275,7 +1369,7 @@
 
 extension CompletionSuggestionExtension on CompletionSuggestion {
   CompletionSuggestion copyWith({
-    CopyWithValue<int?>? libraryUriToImportIndex,
+    CopyWithValue<bool?>? isNotImported,
   }) {
     return protocol.CompletionSuggestion(
       kind,
@@ -1301,9 +1395,7 @@
       hasNamedParameters: hasNamedParameters,
       parameterName: parameterName,
       parameterType: parameterType,
-      libraryUriToImportIndex: libraryUriToImportIndex.orElse(
-        this.libraryUriToImportIndex,
-      ),
+      isNotImported: isNotImported.orElse(this.isNotImported),
     );
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart
new file mode 100644
index 0000000..fdd99bf
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:collection/collection.dart';
+
+/// A contributor that produces suggestions for super formal parameters that
+/// are based on the parameters declared by the invoked super-constructor.
+/// The enclosing declaration is expected to be a constructor.
+class SuperFormalContributor extends DartCompletionContributor {
+  SuperFormalContributor(
+    DartCompletionRequest request,
+    SuggestionBuilder builder,
+  ) : super(request, builder);
+
+  @override
+  Future<void> computeSuggestions() async {
+    var node = request.target.containingNode;
+    if (node is! SuperFormalParameter) {
+      return;
+    }
+
+    var element = node.declaredElement as SuperFormalParameterElementImpl;
+
+    var constructor = node.thisOrAncestorOfType<ConstructorDeclaration>();
+    if (constructor == null) {
+      return;
+    }
+
+    var constructorElement = constructor.declaredElement;
+    constructorElement as ConstructorElementImpl;
+
+    var superConstructor = constructorElement.superConstructor;
+    if (superConstructor == null) {
+      return;
+    }
+
+    if (node.isNamed) {
+      var superConstructorInvocation = constructor.initializers
+          .whereType<SuperConstructorInvocation>()
+          .singleOrNull;
+      var specified = <String>{
+        ...constructorElement.parameters.map((e) => e.name),
+        ...?superConstructorInvocation?.argumentList.arguments
+            .whereType<NamedExpression>()
+            .map((e) => e.name.label.name),
+      };
+      for (var superParameter in superConstructor.parameters) {
+        if (superParameter.isNamed &&
+            !specified.contains(superParameter.name)) {
+          builder.suggestSuperFormalParameter(superParameter);
+        }
+      }
+    }
+
+    if (node.isPositional) {
+      var indexOfThis = element.indexIn(constructorElement);
+      var superPositionalList = superConstructor.parameters
+          .where((parameter) => parameter.isPositional)
+          .toList();
+      if (indexOfThis >= 0 && indexOfThis < superPositionalList.length) {
+        var superPositional = superPositionalList[indexOfThis];
+        builder.suggestSuperFormalParameter(superPositional);
+      }
+    }
+  }
+}
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 589c793..3717b9c 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
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
@@ -253,7 +254,10 @@
         // Exclude static methods when completion on an instance.
         if (!method.isStatic) {
           addSuggestionForMethod(
-              method: method, inheritanceDistance: inheritanceDistance);
+            method: method,
+            kind: protocol.CompletionSuggestionKind.INVOCATION,
+            inheritanceDistance: inheritanceDistance,
+          );
         }
       }
       for (var accessor in targetType.accessors) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart
index 4a1c1e4..c392597 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/error_verifier.dart';
@@ -35,16 +36,23 @@
     // Compute uninitialized final fields.
     var fields = ErrorVerifier.computeNotInitializedFields(constructor);
     fields.retainWhere((FieldElement field) => field.isFinal);
-
-    // Prepare new parameters code.
     fields.sort((a, b) => a.nameOffset - b.nameOffset);
-    var fieldParametersCode =
-        fields.map((field) => 'this.${field.name}').join(', ');
 
     // Specialize for Flutter widgets.
     if (flutter.isExactlyStatelessWidgetType(superType) ||
         flutter.isExactlyStatefulWidgetType(superType)) {
       if (parameters.isNotEmpty && parameters.last.isNamed) {
+        var isNullSafe =
+            libraryElement.featureSet.isEnabled(Feature.non_nullable);
+        String parameterForField(FieldElement field) {
+          var prefix = '';
+          if (isNullSafe && typeSystem.isPotentiallyNonNullable(field.type)) {
+            prefix = 'required ';
+          }
+          return '${prefix}this.${field.name}';
+        }
+
+        var fieldParametersCode = fields.map(parameterForField).join(', ');
         await builder.addDartFileEdit(file, (builder) {
           builder.addSimpleInsertion(
             parameters.last.end,
@@ -63,6 +71,8 @@
       }
     }
 
+    var fieldParametersCode =
+        fields.map((field) => 'this.${field.name}').join(', ');
     await builder.addDartFileEdit(file, (builder) {
       if (lastRequiredParameter != null) {
         builder.addSimpleInsertion(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_leading_newline_to_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_leading_newline_to_string.dart
new file mode 100644
index 0000000..d078389
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_leading_newline_to_string.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddLeadingNewlineToString extends CorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.ADD_LEADING_NEWLINE_TO_STRING;
+
+  @override
+  FixKind get multiFixKind => DartFixKind.ADD_LEADING_NEWLINE_TO_STRING_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var stringLiteral = coveredNode;
+    if (stringLiteral is! SimpleStringLiteral) {
+      return;
+    }
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addSimpleInsertion(stringLiteral.contentsOffset, eol);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static AddLeadingNewlineToString newInstance() => AddLeadingNewlineToString();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
index 029d157..f7c9e13 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
@@ -33,15 +33,17 @@
         importedUris.add(Uri.parse(uri));
       }
     }
-    var matcher = ElementMatcher.forNode(node);
-    if (matcher == null) {
-      // The node doesn't represent an element that can be transformed.
+    var matchers = ElementMatcher.matchersForNode(node);
+    if (matchers.isEmpty) {
+      // The node doesn't represent any element that can be transformed.
       return;
     }
     for (var set in _availableTransformSetsForLibrary(library)) {
-      for (var transform
-          in set.transformsFor(matcher, applyingBulkFixes: applyingBulkFixes)) {
-        yield DataDrivenFix(transform);
+      for (var matcher in matchers) {
+        for (var transform in set.transformsFor(matcher,
+            applyingBulkFixes: applyingBulkFixes)) {
+          yield DataDrivenFix(transform);
+        }
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/extract_local_variable.dart b/pkg/analysis_server/lib/src/services/correction/dart/extract_local_variable.dart
new file mode 100644
index 0000000..bdb9fc7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/extract_local_variable.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/util.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/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ExtractLocalVariable extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.EXTRACT_LOCAL_VARIABLE;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    final node = this.node;
+    if (node is! SimpleIdentifier) {
+      return;
+    }
+
+    var parent = node.parent;
+
+    if (parent is MethodInvocation && parent.methodName == node) {
+      await _rewrite(
+        builder: builder,
+        target: parent.target,
+      );
+    }
+
+    if (parent is PrefixedIdentifier && parent.identifier == node) {
+      await _rewrite(
+        builder: builder,
+        target: parent.prefix,
+      );
+    }
+
+    if (parent is PropertyAccess && parent.propertyName == node) {
+      await _rewrite(
+        builder: builder,
+        target: parent.target,
+      );
+    }
+  }
+
+  Future<void> _rewrite({
+    required ChangeBuilder builder,
+    required Expression? target,
+  }) async {
+    if (target is PrefixedIdentifier) {
+      await _rewriteProperty(
+        builder: builder,
+        target: target,
+        targetProperty: target.staticElement,
+      );
+    }
+
+    if (target is PropertyAccess) {
+      await _rewriteProperty(
+        builder: builder,
+        target: target,
+        targetProperty: target.propertyName.staticElement,
+      );
+    }
+
+    if (target is SimpleIdentifier) {
+      await _rewriteProperty(
+        builder: builder,
+        target: target,
+        targetProperty: target.staticElement,
+      );
+    }
+  }
+
+  Future<void> _rewriteProperty({
+    required ChangeBuilder builder,
+    required Expression target,
+    required Element? targetProperty,
+  }) async {
+    if (targetProperty is PropertyAccessorElement &&
+        targetProperty.isGetter &&
+        typeSystem.isPotentiallyNullable(targetProperty.returnType)) {
+      AstNode? enclosingNode = target;
+      while (true) {
+        if (enclosingNode == null || enclosingNode is FunctionBody) {
+          return;
+        }
+        if (enclosingNode is IfStatement) {
+          var condition = enclosingNode.condition;
+          if (condition is BinaryExpression &&
+              condition.rightOperand is NullLiteral &&
+              condition.operator.type == TokenType.BANG_EQ) {
+            var encoder = _ExpressionEncoder();
+            var leftCode = encoder.encode(condition.leftOperand);
+            var targetCode = encoder.encode(target);
+            if (leftCode == targetCode) {
+              var occurrences = <SourceRange>[];
+              enclosingNode.accept(
+                _OccurrencesVisitor(encoder, occurrences, leftCode),
+              );
+
+              var ifOffset = enclosingNode.offset;
+              var ifLineOffset = utils.getLineContentStart(ifOffset);
+              var prefix = utils.getLinePrefix(ifOffset);
+
+              var initializerCode = utils.getNodeText(target);
+              if (target is SimpleIdentifier) {
+                initializerCode = 'this.$initializerCode';
+              }
+
+              await builder.addDartFileEdit(file, (builder) {
+                var propertyName = targetProperty.name;
+                builder.addInsertion(ifLineOffset, (builder) {
+                  builder.write(prefix);
+                  builder.writeln('final $propertyName = $initializerCode;');
+                });
+                for (var occurrence in occurrences) {
+                  builder.addSimpleReplacement(occurrence, propertyName);
+                }
+              });
+              return;
+            }
+          }
+          break;
+        }
+        enclosingNode = enclosingNode.parent;
+      }
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static ExtractLocalVariable newInstance() => ExtractLocalVariable();
+}
+
+class _ExpressionEncoder {
+  final Map<Element, int> _elementIds = {};
+
+  String encode(Expression node) {
+    var tokens = TokenUtils.getNodeTokens(node);
+
+    var tokenToElementMap = Map<Token, Element>.identity();
+    node.accept(
+      _FunctionAstVisitor(
+        simpleIdentifier: (node) {
+          var element = node.staticElement;
+          if (element != null) {
+            tokenToElementMap[node.token] = element;
+          }
+        },
+      ),
+    );
+
+    var tokensWithId = tokens.map((token) {
+      var tokenString = token.lexeme;
+      var element = tokenToElementMap[token];
+      if (element != null) {
+        var elementId = _elementIds.putIfAbsent(
+          element,
+          () => _elementIds.length,
+        );
+        tokenString += '#$elementId';
+      }
+      return tokenString;
+    });
+
+    const separator = '\uFFFF';
+    return tokensWithId.join(separator) + separator;
+  }
+}
+
+/// [RecursiveAstVisitor] that delegates visit methods to functions.
+class _FunctionAstVisitor extends RecursiveAstVisitor<void> {
+  final void Function(SimpleIdentifier)? simpleIdentifier;
+
+  _FunctionAstVisitor({
+    this.simpleIdentifier,
+  });
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (simpleIdentifier != null) {
+      simpleIdentifier!(node);
+    }
+    super.visitSimpleIdentifier(node);
+  }
+}
+
+class _OccurrencesVisitor extends GeneralizingAstVisitor<void> {
+  final _ExpressionEncoder encoder;
+  final List<SourceRange> occurrences;
+  final String searchCode;
+
+  _OccurrencesVisitor(this.encoder, this.occurrences, this.searchCode);
+
+  @override
+  void visitExpression(Expression node) {
+    var nodeCode = encoder.encode(node);
+    if (nodeCode == searchCode) {
+      occurrences.add(range.node(node));
+    }
+    super.visitExpression(node);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart b/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
index 2a5b705..a9b1c89 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/make_final.dart
@@ -43,22 +43,30 @@
       return;
     }
 
-    if (node is SimpleFormalParameter) {
+    final AstNode normalParameter;
+    if (node is DefaultFormalParameter) {
+      normalParameter = node.parameter;
+    } else {
+      normalParameter = node;
+    }
+
+    if (normalParameter is SimpleFormalParameter) {
+      final simpleNode = normalParameter;
       await builder.addDartFileEdit(file, (builder) {
-        final keyword = node.keyword;
+        final keyword = simpleNode.keyword;
         if (keyword != null && keyword.keyword == Keyword.VAR) {
           builder.addSimpleReplacement(range.token(keyword), 'final');
         } else {
-          final type = node.type;
+          final type = simpleNode.type;
           if (type != null) {
             builder.addSimpleInsertion(type.offset, 'final ');
             return;
           }
-          final identifier = node.identifier;
+          final identifier = simpleNode.identifier;
           if (identifier != null) {
             builder.addSimpleInsertion(identifier.offset, 'final ');
           } else {
-            builder.addSimpleInsertion(node.offset, 'final ');
+            builder.addSimpleInsertion(simpleNode.offset, 'final ');
           }
         }
       });
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt b/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt
new file mode 100644
index 0000000..badc576
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.txt
@@ -0,0 +1,1079 @@
+This file contains, for each analysis code and lint name:
+* "has fix(es)", if the code has fix(es)
+* "needs evaluation", if the code has not been evaluated in terms of fixes
+* "needs fix", if the code needs a fix, with a possible issue link
+* "fixes infeasible", if it has been deemed infeasible to write a fix for this code
+
+TODO(srawlins): Add lint names not found in LintNames?
+
+Stats:
+* 808 "needs evaluation"
+* 253 "has fix(es)"
+
+AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR: needs evaluation
+AnalysisOptionsErrorCode.PARSE_ERROR: needs evaluation
+AnalysisOptionsHintCode.PREVIEW_DART_2_SETTING_DEPRECATED: needs evaluation
+AnalysisOptionsHintCode.STRONG_MODE_SETTING_DEPRECATED: needs evaluation
+AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED: needs evaluation
+AnalysisOptionsWarningCode.ANALYSIS_OPTION_DEPRECATED: needs evaluation
+AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND: needs evaluation
+AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING: needs evaluation
+AnalysisOptionsWarningCode.INVALID_OPTION: needs evaluation
+AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT: needs evaluation
+AnalysisOptionsWarningCode.SPEC_MODE_REMOVED: needs evaluation
+AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE: needs evaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE: needs evaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES: needs evaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES: needs evaluation
+AnalysisOptionsWarningCode.UNSUPPORTED_VALUE: needs evaluation
+CompileTimeErrorCode.ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER: needs evaluation
+CompileTimeErrorCode.ABSTRACT_FIELD_INITIALIZER: needs evaluation
+CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE: needs evaluation
+CompileTimeErrorCode.AMBIGUOUS_EXPORT: needs evaluation
+CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS: needs evaluation
+CompileTimeErrorCode.AMBIGUOUS_IMPORT: needs evaluation
+CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH: needs evaluation
+CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER: needs evaluation
+CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_CONST: needs evaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL: has fix(es)
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL: has fix(es)
+CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER: needs evaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION: needs evaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_METHOD: needs evaluation
+CompileTimeErrorCode.ASSIGNMENT_TO_TYPE: needs evaluation
+CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT: has fix(es)
+CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER: needs evaluation
+CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT: has fix(es)
+CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY: has fix(es)
+CompileTimeErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME: needs evaluation
+CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME: needs evaluation
+CompileTimeErrorCode.CASE_BLOCK_NOT_TERMINATED: needs evaluation
+CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS: needs evaluation
+CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE: needs evaluation
+CompileTimeErrorCode.CAST_TO_NON_TYPE: has fix(es)
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_INSTANCE_MEMBER: needs evaluation
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_STATIC_MEMBER: needs evaluation
+CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER: needs evaluation
+CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER: has fix(es)
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD: needs evaluation
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER: needs evaluation
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD: needs evaluation
+CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER: needs evaluation
+CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD: needs evaluation
+CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES: needs evaluation
+CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD: needs evaluation
+CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN: needs evaluation
+CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER: needs evaluation
+CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD: needs evaluation
+CompileTimeErrorCode.CONST_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_INT: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_NUM: needs evaluation
+CompileTimeErrorCode.CONST_EVAL_TYPE_TYPE: needs evaluation
+CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE: has fix(es)
+CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.CONST_INSTANCE_FIELD: has fix(es)
+CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS: needs evaluation
+CompileTimeErrorCode.CONST_NOT_INITIALIZED: needs evaluation
+CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS: needs evaluation
+CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET: needs evaluation
+CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP: needs evaluation
+CompileTimeErrorCode.CONST_WITH_NON_CONST: has fix(es)
+CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT: needs evaluation
+CompileTimeErrorCode.CONST_WITH_NON_TYPE: has fix(es)
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS: needs evaluation
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF: needs evaluation
+CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF: needs evaluation
+CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: needs evaluation
+CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH: needs evaluation
+CompileTimeErrorCode.COULD_NOT_INFER: needs evaluation
+CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR: has fix(es)
+CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER: needs evaluation
+CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION: needs evaluation
+CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE: needs evaluation
+CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION: needs evaluation
+CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT: needs evaluation
+CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME: needs evaluation
+CompileTimeErrorCode.DUPLICATE_DEFINITION: needs evaluation
+CompileTimeErrorCode.DUPLICATE_FIELD_FORMAL_PARAMETER: needs evaluation
+CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT: needs evaluation
+CompileTimeErrorCode.DUPLICATE_PART: needs evaluation
+CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING: needs evaluation
+CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET: needs evaluation
+CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP: needs evaluation
+CompileTimeErrorCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS: needs evaluation
+CompileTimeErrorCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS: needs evaluation
+CompileTimeErrorCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS: needs evaluation
+CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY: needs evaluation
+CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL: needs evaluation
+CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY: needs evaluation
+CompileTimeErrorCode.EXPRESSION_IN_MAP: needs evaluation
+CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS: needs evaluation
+CompileTimeErrorCode.EXTENDS_NON_CLASS: has fix(es)
+CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.EXTENSION_AS_EXPRESSION: needs evaluation
+CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE: needs evaluation
+CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT: needs evaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER: has fix(es)
+CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE: needs evaluation
+CompileTimeErrorCode.EXTENSION_OVERRIDE_WITHOUT_ACCESS: needs evaluation
+CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER: needs evaluation
+CompileTimeErrorCode.EXTERNAL_FIELD_INITIALIZER: needs evaluation
+CompileTimeErrorCode.EXTERNAL_VARIABLE_INITIALIZER: needs evaluation
+CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS: has fix(es)
+CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED: has fix(es)
+CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED: has fix(es)
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1: has fix(es)
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2: has fix(es)
+CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS: has fix(es)
+CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE: needs evaluation
+CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE: needs evaluation
+CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE: needs evaluation
+CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND: needs evaluation
+CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT: needs evaluation
+CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC: needs evaluation
+CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES: needs evaluation
+CompileTimeErrorCode.GETTER_NOT_SUBTYPE_SETTER_TYPES: needs evaluation
+CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE: has fix(es)
+CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE: has fix(es)
+CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE: has fix(es)
+CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS: needs evaluation
+CompileTimeErrorCode.IMPLEMENTS_NON_CLASS: has fix(es)
+CompileTimeErrorCode.IMPLEMENTS_REPEATED: needs evaluation
+CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS: needs evaluation
+CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER: needs evaluation
+CompileTimeErrorCode.IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT: has fix(es)
+CompileTimeErrorCode.IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS: has fix(es)
+CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY: needs evaluation
+CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY: needs evaluation
+CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES: needs evaluation
+CompileTimeErrorCode.INCONSISTENT_INHERITANCE: needs evaluation
+CompileTimeErrorCode.INCONSISTENT_INHERITANCE_GETTER_AND_METHOD: needs evaluation
+CompileTimeErrorCode.INCONSISTENT_LANGUAGE_VERSION_OVERRIDE: needs evaluation
+CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD: needs evaluation
+CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD: needs evaluation
+CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD: has fix(es)
+CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER: has fix(es)
+CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION: needs evaluation
+CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY: needs evaluation
+CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC: needs evaluation
+CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS: needs evaluation
+CompileTimeErrorCode.INSTANTIATE_ENUM: needs evaluation
+CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE: has fix(es)
+CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE: needs evaluation
+CompileTimeErrorCode.INVALID_ANNOTATION: has fix(es)
+CompileTimeErrorCode.INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.INVALID_ASSIGNMENT: has fix(es)
+CompileTimeErrorCode.INVALID_CAST_FUNCTION: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_FUNCTION_EXPR: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_LIST: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_MAP: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_LITERAL_SET: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_METHOD: needs evaluation
+CompileTimeErrorCode.INVALID_CAST_NEW_EXPR: needs evaluation
+CompileTimeErrorCode.INVALID_CONSTANT: needs evaluation
+CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT: needs evaluation
+CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS: needs evaluation
+CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE: needs evaluation
+CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE: needs evaluation
+CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER: needs evaluation
+CompileTimeErrorCode.INVALID_OVERRIDE: has fix(es)
+CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS: needs evaluation
+CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION: needs evaluation
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST: needs evaluation
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP: needs evaluation
+CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET: needs evaluation
+CompileTimeErrorCode.INVALID_URI: needs evaluation
+CompileTimeErrorCode.INVALID_USE_OF_COVARIANT: needs evaluation
+CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE: needs evaluation
+CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL: needs evaluation
+CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION: needs evaluation
+CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION: has fix(es)
+CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE: needs evaluation
+CompileTimeErrorCode.LABEL_UNDEFINED: needs evaluation
+CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED: needs evaluation
+CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE: needs evaluation
+CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS: needs evaluation
+CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS: needs evaluation
+CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION: needs evaluation
+CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP: needs evaluation
+CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL: needs evaluation
+CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL: needs evaluation
+CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL: needs evaluation
+CompileTimeErrorCode.MISSING_DART_LIBRARY: needs evaluation
+CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER: has fix(es)
+CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION: has fix(es)
+CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT: has fix(es)
+CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE: needs evaluation
+CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER: needs evaluation
+CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE: has fix(es)
+CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.MIXIN_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT: needs evaluation
+CompileTimeErrorCode.MIXIN_INSTANTIATE: needs evaluation
+CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS: needs evaluation
+CompileTimeErrorCode.MIXIN_OF_NON_CLASS: has fix(es)
+CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS: needs evaluation
+CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE: needs evaluation
+CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS: needs evaluation
+CompileTimeErrorCode.MIXINS_SUPER_CLASS: needs evaluation
+CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS: needs evaluation
+CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS: needs evaluation
+CompileTimeErrorCode.NEW_WITH_NON_TYPE: has fix(es)
+CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR: has fix(es)
+CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: has fix(es)
+CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS: needs evaluation
+CompileTimeErrorCode.NO_COMBINED_SUPER_SIGNATURE: needs evaluation
+CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT: has fix(es)
+CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT: has fix(es)
+CompileTimeErrorCode.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS: needs evaluation
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS: has fix(es)
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR: has fix(es)
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE: has fix(es)
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE: has fix(es)
+CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO: has fix(es)
+CompileTimeErrorCode.NON_BOOL_CONDITION: has fix(es)
+CompileTimeErrorCode.NON_BOOL_EXPRESSION: needs evaluation
+CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION: needs evaluation
+CompileTimeErrorCode.NON_BOOL_OPERAND: needs evaluation
+CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_KEY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT: needs evaluation
+CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.NON_SYNC_FACTORY: needs evaluation
+CompileTimeErrorCode.NON_TYPE_AS_TYPE_ARGUMENT: has fix(es)
+CompileTimeErrorCode.NON_TYPE_IN_CATCH_CLAUSE: has fix(es)
+CompileTimeErrorCode.NON_VOID_RETURN_FOR_OPERATOR: needs evaluation
+CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER: needs evaluation
+CompileTimeErrorCode.NOT_A_TYPE: has fix(es)
+CompileTimeErrorCode.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE: needs evaluation
+CompileTimeErrorCode.NOT_BINARY_OPERATOR: needs evaluation
+CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS: has fix(es)
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD: has fix(es)
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_VARIABLE: needs evaluation
+CompileTimeErrorCode.NOT_INSTANTIATED_BOUND: needs evaluation
+CompileTimeErrorCode.NOT_ITERABLE_SPREAD: needs evaluation
+CompileTimeErrorCode.NOT_MAP_SPREAD: needs evaluation
+CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD: needs evaluation
+CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE: has fix(es)
+CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE: has fix(es)
+CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE: has fix(es)
+CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE: has fix(es)
+CompileTimeErrorCode.OBJECT_CANNOT_EXTEND_ANOTHER_CLASS: fix infeasible
+CompileTimeErrorCode.ON_REPEATED: needs evaluation
+CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR: needs evaluation
+CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY: needs evaluation
+CompileTimeErrorCode.PART_OF_NON_PART: needs evaluation
+CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY: needs evaluation
+CompileTimeErrorCode.POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT: needs evaluation
+CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER: needs evaluation
+CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT: needs evaluation
+CompileTimeErrorCode.PREFIX_SHADOWED_BY_LOCAL_DECLARATION: needs evaluation
+CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION: needs evaluation
+CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER: needs evaluation
+CompileTimeErrorCode.PRIVATE_SETTER: needs evaluation
+CompileTimeErrorCode.READ_POTENTIALLY_UNASSIGNED_FINAL: needs evaluation
+CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT: needs evaluation
+CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT: needs evaluation
+CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT: needs evaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE: needs evaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS: needs evaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS: needs evaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_ON: needs evaluation
+CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH: needs evaluation
+CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_INVALID_FUNCTION_TYPE: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_INVALID_RETURN_TYPE: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_NON_CLASS: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER: needs evaluation
+CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION: needs evaluation
+CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH: needs evaluation
+CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.RETURN_IN_GENERATOR: needs evaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE: needs evaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION: has fix(es)
+CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_METHOD: has fix(es)
+CompileTimeErrorCode.RETURN_WITHOUT_VALUE: needs evaluation
+CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.SHARED_DEFERRED_PREFIX: needs evaluation
+CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY: needs evaluation
+CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER: needs evaluation
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED: needs evaluation
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED: needs evaluation
+CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL: needs evaluation
+CompileTimeErrorCode.SUPER_IN_EXTENSION: needs evaluation
+CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT: needs evaluation
+CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR: needs evaluation
+CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT: needs evaluation
+CompileTimeErrorCode.SUPER_INVOCATION_NOT_LAST: needs evaluation
+CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY: has fix(es)
+CompileTimeErrorCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE: needs evaluation
+CompileTimeErrorCode.TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS: needs evaluation
+CompileTimeErrorCode.THROW_OF_INVALID_TYPE: needs evaluation
+CompileTimeErrorCode.TOP_LEVEL_CYCLE: needs evaluation
+CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF: needs evaluation
+CompileTimeErrorCode.TYPE_ANNOTATION_DEFERRED_CLASS: needs evaluation
+CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS: needs evaluation
+CompileTimeErrorCode.TYPE_PARAMETER_REFERENCED_BY_STATIC: needs evaluation
+CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND: needs evaluation
+CompileTimeErrorCode.TYPE_TEST_WITH_NON_TYPE: needs evaluation
+CompileTimeErrorCode.TYPE_TEST_WITH_UNDEFINED_NAME: has fix(es)
+CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
+CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
+CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE: has fix(es)
+CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE: has fix(es)
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION: has fix(es)
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR: has fix(es)
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD: has fix(es)
+CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH: has fix(es)
+CompileTimeErrorCode.UNDEFINED_ANNOTATION: has fix(es)
+CompileTimeErrorCode.UNDEFINED_CLASS: has fix(es)
+CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN: has fix(es)
+CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER: needs evaluation
+CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT: has fix(es)
+CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT: needs evaluation
+CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER: has fix(es)
+CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD: has fix(es)
+CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR: needs evaluation
+CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER: has fix(es)
+CompileTimeErrorCode.UNDEFINED_FUNCTION: has fix(es)
+CompileTimeErrorCode.UNDEFINED_GETTER: has_fix(es)
+CompileTimeErrorCode.UNDEFINED_GETTER_ON_FUNCTION_TYPE: needs evaluation
+CompileTimeErrorCode.UNDEFINED_IDENTIFIER: has fix(es)
+CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT: has fix(es)
+CompileTimeErrorCode.UNDEFINED_METHOD: has fix(es)
+CompileTimeErrorCode.UNDEFINED_METHOD_ON_FUNCTION_TYPE: needs evaluation
+CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER: has fix(es)
+CompileTimeErrorCode.UNDEFINED_OPERATOR: has fix(es)
+CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME: has fix(es)
+CompileTimeErrorCode.UNDEFINED_SETTER: has fix(es)
+CompileTimeErrorCode.UNDEFINED_SETTER_ON_FUNCTION_TYPE: needs evaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_GETTER: needs evaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_METHOD: needs evaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR: needs evaluation
+CompileTimeErrorCode.UNDEFINED_SUPER_SETTER: needs evaluation
+CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER: has fix(es)
+CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE: has fix(es)
+CompileTimeErrorCode.URI_DOES_NOT_EXIST: has fix(es)
+CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED: needs evaluation
+CompileTimeErrorCode.URI_WITH_INTERPOLATION: needs evaluation
+CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION: needs evaluation
+CompileTimeErrorCode.USE_OF_VOID_RESULT: needs evaluation
+CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH: needs evaluation
+CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS: has fix(es)
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR: has fix(es)
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION: has fix(es)
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION: needs evaluation
+CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD: has fix(es)
+CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE: needs evaluation
+CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION: needs evaluation
+CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR: needs evaluation
+CompileTimeErrorCode.YIELD_IN_NON_GENERATOR: needs evaluation
+CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE: needs evaluation
+CompileTimeErrorCode.YIELD_OF_INVALID_TYPE: has fix(es)
+FfiCode.ABI_SPECIFIC_INTEGER_INVALID: needs evaluation
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_EXTRA: needs evaluation
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_MISSING: needs evaluation
+FfiCode.ABI_SPECIFIC_INTEGER_MAPPING_UNSUPPORTED: needs evaluation
+FfiCode.ANNOTATION_ON_POINTER_FIELD: needs evaluation
+FfiCode.ARGUMENT_MUST_BE_A_CONSTANT: needs evaluation
+FfiCode.CREATION_OF_STRUCT_OR_UNION: needs evaluation
+FfiCode.EMPTY_STRUCT: needs evaluation
+FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
+FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY: needs evaluation
+FfiCode.FFI_NATIVE_MUST_BE_EXTERNAL: needs evaluation
+  FfiCode
+    .FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER: needs evaluation
+FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS: needs evaluation
+FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER: needs evaluation
+FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER: needs evaluation
+FfiCode.FIELD_INITIALIZER_IN_STRUCT: needs evaluation
+FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT: needs evaluation
+FfiCode.GENERIC_STRUCT_SUBCLASS: needs evaluation
+FfiCode.INVALID_EXCEPTION_VALUE: needs evaluation
+FfiCode.INVALID_FIELD_TYPE_IN_STRUCT: needs evaluation
+FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE: needs evaluation
+FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE: needs evaluation
+FfiCode.MISMATCHED_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
+FfiCode.MISSING_ANNOTATION_ON_STRUCT_FIELD: needs evaluation
+FfiCode.MISSING_EXCEPTION_VALUE: needs evaluation
+FfiCode.MISSING_FIELD_TYPE_IN_STRUCT: needs evaluation
+FfiCode.MISSING_SIZE_ANNOTATION_CARRAY: needs evaluation
+FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE: needs evaluation
+FfiCode.MUST_BE_A_SUBTYPE: needs evaluation
+FfiCode.NON_CONSTANT_TYPE_ARGUMENT: needs evaluation
+FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER: needs evaluation
+FfiCode.NON_POSITIVE_ARRAY_DIMENSION: needs evaluation
+FfiCode.NON_SIZED_TYPE_ARGUMENT: needs evaluation
+FfiCode.PACKED_ANNOTATION: needs evaluation
+FfiCode.PACKED_ANNOTATION_ALIGNMENT: needs evaluation
+FfiCode.PACKED_NESTING_NON_PACKED: needs evaluation
+FfiCode.SIZE_ANNOTATION_DIMENSIONS: needs evaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS: needs evaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS: needs evaluation
+FfiCode.SUBTYPE_OF_FFI_CLASS_IN_WITH: needs evaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS: needs evaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS: needs evaluation
+FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH: needs evaluation
+HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE_TO_ERROR_HANDLER: has fix(es)
+HintCode.ASSIGNMENT_OF_DO_NOT_STORE: needs evaluation
+HintCode.BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE: has fix(es)
+HintCode.CAN_BE_NULL_AFTER_NULL_AWARE: has fix(es)
+HintCode.DEAD_CODE: has fix(es)
+HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH: has fix(es)
+HintCode.DEAD_CODE_ON_CATCH_SUBTYPE: has fix(es)
+HintCode.DEPRECATED_EXTENDS_FUNCTION: needs evaluation
+HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION: needs evaluation
+HintCode.DEPRECATED_IMPLEMENTS_FUNCTION: needs evaluation
+HintCode.DEPRECATED_MEMBER_USE: has fix(es)
+HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE: needs evaluation
+HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE: needs evaluation
+HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: has fix(es)
+HintCode.DEPRECATED_MIXIN_FUNCTION: needs evaluation
+HintCode.DEPRECATED_NEW_IN_COMMENT_REFERENCE: has fix(es)
+HintCode.DIVISION_OPTIMIZATION: has fix(es)
+HintCode.DUPLICATE_HIDDEN_NAME: has fix(es)
+HintCode.DUPLICATE_IGNORE: needs evaluation
+HintCode.DUPLICATE_IMPORT: has fix(es)
+HintCode.DUPLICATE_SHOWN_NAME: has fix(es)
+HintCode.EQUAL_ELEMENTS_IN_SET: needs evaluation
+HintCode.EQUAL_KEYS_IN_MAP: needs evaluation
+HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE: needs evaluation
+HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE: needs evaluation
+HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION: needs evaluation
+HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_FUNCTION_INVOCATION: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_GENERIC_INVOCATION: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE: needs evaluation
+HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER: needs evaluation
+HintCode.INVALID_ANNOTATION_TARGET: needs evaluation
+HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT: needs evaluation
+HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY: needs evaluation
+HintCode.INVALID_FACTORY_ANNOTATION: has fix(es)
+HintCode.INVALID_FACTORY_METHOD_DECL: needs evaluation
+HintCode.INVALID_FACTORY_METHOD_IMPL: needs evaluation
+HintCode.INVALID_IMMUTABLE_ANNOTATION: has fix(es)
+HintCode.INVALID_INTERNAL_ANNOTATION: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOCATION: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_LOWER_CASE: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_NUMBER: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_PREFIX: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TRAILING_CHARACTERS: needs evaluation
+HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_TWO_SLASHES: needs evaluation
+HintCode.INVALID_LITERAL_ANNOTATION: has fix(es)
+HintCode.INVALID_NON_VIRTUAL_ANNOTATION: needs evaluation
+HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER: needs evaluation
+HintCode.INVALID_REQUIRED_NAMED_PARAM: has fix(es)
+HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM: has fix(es)
+HintCode.INVALID_REQUIRED_POSITIONAL_PARAM: has fix(es)
+HintCode.INVALID_SEALED_ANNOTATION: has fix(es)
+HintCode.INVALID_USE_OF_INTERNAL_MEMBER: needs evaluation
+HintCode.INVALID_USE_OF_PROTECTED_MEMBER: needs evaluation
+HintCode.INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER: needs evaluation
+HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER: needs evaluation
+HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER: needs evaluation
+HintCode.INVALID_VISIBILITY_ANNOTATION: needs evaluation
+HintCode.INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION: needs evaluation
+HintCode.MISSING_REQUIRED_PARAM: has fix(es)
+HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS: has fix(es)
+HintCode.MISSING_RETURN: needs evaluation
+HintCode.MIXIN_ON_SEALED_CLASS: needs evaluation
+HintCode.MUST_BE_IMMUTABLE: needs evaluation
+HintCode.MUST_CALL_SUPER: needs fix; https://github.com/dart-lang/sdk/issues/33985
+HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR: needs evaluation
+HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW: needs evaluation
+HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE: needs evaluation
+HintCode.NULL_AWARE_BEFORE_OPERATOR: needs evaluation
+HintCode.NULL_AWARE_IN_CONDITION: needs evaluation
+HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR: needs evaluation
+HintCode.NULL_CHECK_ALWAYS_FAILS: needs evaluation
+HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE: has fix(es)
+HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD: has fix(es)
+HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER: has fix(es)
+HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: has fix(es)
+HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER: has fix(es)
+HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT: needs evaluation
+HintCode.RECEIVER_OF_TYPE_NEVER: needs evaluation
+HintCode.RETURN_OF_DO_NOT_STORE: needs evaluation
+HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR: needs evaluation
+HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR: needs evaluation
+HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT: has fix(es)
+HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE: has fix(es)
+HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT: has fix(es)
+HintCode.SDK_VERSION_CONSTRUCTOR_TEAROFFS: needs evaluation
+HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT: has fix(es)
+HintCode.SDK_VERSION_EXTENSION_METHODS: has fix(es)
+HintCode.SDK_VERSION_GT_GT_GT_OPERATOR: has fix(es)
+HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT: has fix(es)
+HintCode.SDK_VERSION_NEVER: needs evaluation
+HintCode.SDK_VERSION_SET_LITERAL: has fix(es)
+HintCode.SDK_VERSION_UI_AS_CODE: has fix(es)
+HintCode.SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT: needs evaluation
+HintCode.STRICT_RAW_TYPE: needs evaluation
+HintCode.SUBTYPE_OF_SEALED_CLASS: needs evaluation
+HintCode.TYPE_CHECK_IS_NOT_NULL: has fix(es)
+HintCode.TYPE_CHECK_IS_NULL: has fix(es)
+HintCode.UNDEFINED_HIDDEN_NAME: has fix(es)
+HintCode.UNDEFINED_REFERENCED_PARAMETER: has fix(es)
+HintCode.UNDEFINED_SHOWN_NAME: needs evaluation
+HintCode.UNIGNORABLE_IGNORE: needs evaluation
+HintCode.UNNECESSARY_CAST: has fix(es)
+HintCode.UNNECESSARY_IGNORE: needs evaluation
+HintCode.UNNECESSARY_IMPORT: has fix(es)
+HintCode.UNNECESSARY_NO_SUCH_METHOD: needs evaluation
+HintCode.UNNECESSARY_NULL_COMPARISON_FALSE: has fix(es)
+HintCode.UNNECESSARY_NULL_COMPARISON_TRUE: has fix(es)
+HintCode.UNNECESSARY_QUESTION_MARK: needs evaluation
+HintCode.UNNECESSARY_TYPE_CHECK_FALSE: needs fix; https://github.com/dart-lang/sdk/issues/47793
+HintCode.UNNECESSARY_TYPE_CHECK_TRUE: needs fix; https://github.com/dart-lang/sdk/issues/47793
+HintCode.TEXT_DIRECTION_CODE_POINT_IN_COMMENT: needs evaluation
+HintCode.TEXT_DIRECTION_CODE_POINT_IN_LITERAL: needs evaluation
+HintCode.UNUSED_CATCH_CLAUSE: has fix(es)
+HintCode.UNUSED_CATCH_STACK: has fix(es)
+HintCode.UNUSED_ELEMENT: has fix(es)
+HintCode.UNUSED_ELEMENT_PARAMETER: needs evaluation
+HintCode.UNUSED_FIELD: has fix(es)
+HintCode.UNUSED_IMPORT: has fix(es)
+HintCode.UNUSED_LABEL: has fix(es)
+HintCode.UNUSED_LOCAL_VARIABLE: has fix(es)
+HintCode.UNUSED_RESULT: needs evaluation
+HintCode.UNUSED_RESULT_WITH_MESSAGE: needs evaluation
+HintCode.UNUSED_SHOWN_NAME: has fix(es)
+LanguageCode.IMPLICIT_DYNAMIC_FIELD: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_FUNCTION: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_INVOKE: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_LIST_LITERAL: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_MAP_LITERAL: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_METHOD: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_PARAMETER: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_RETURN: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_TYPE: needs evaluation
+LanguageCode.IMPLICIT_DYNAMIC_VARIABLE: needs evaluation
+LintNames.always_declare_return_types: has fix(es)
+LintNames.always_put_control_body_on_new_line: needs evaluation
+LintNames.always_put_required_named_parameters_first: needs evaluation
+LintNames.always_require_non_null_named_parameters: has fix(es)
+LintNames.always_specify_types: has fix(es)
+LintNames.always_use_package_imports: needs evaluation
+LintNames.annotate_overrides: has fix(es)
+LintNames.avoid_annotating_with_dynamic: has fix(es)
+LintNames.avoid_as: needs evaluation
+LintNames.avoid_bool_literals_in_conditional_expressions: needs evaluation
+LintNames.avoid_catches_without_on_clauses: needs evaluation
+LintNames.avoid_catching_errors: needs evaluation
+LintNames.avoid_classes_with_only_static_members: needs evaluation
+LintNames.avoid_double_and_int_checks: needs evaluation
+LintNames.avoid_dynamic_calls: needs evaluation
+LintNames.avoid_empty_else: has fix(es)
+LintNames.avoid_equals_and_hash_code_on_mutable_classes: needs evaluation
+LintNames.avoid_escaping_inner_quotes: has fix(es)
+LintNames.avoid_field_initializers_in_const_classes: needs evaluation
+LintNames.avoid_final_parameters: needs evaluation
+LintNames.avoid_function_literals_in_foreach_calls: has fix(es)
+LintNames.avoid_implementing_value_types: needs evaluation
+LintNames.avoid_init_to_null: has fix(es)
+LintNames.avoid_js_rounded_ints: needs evaluation
+LintNames.avoid_multiple_declarations_per_line: needs evaluation
+LintNames.avoid_null_checks_in_equality_operators: has fix(es)
+LintNames.avoid_positional_boolean_parameters: needs evaluation
+LintNames.avoid_print: has fix(es)
+LintNames.avoid_private_typedef_functions: has fix(es)
+LintNames.avoid_redundant_argument_values: has fix(es)
+LintNames.avoid_relative_lib_imports: has fix(es)
+LintNames.avoid_renaming_method_parameters: needs evaluation
+LintNames.avoid_return_types_on_setters: has fix(es)
+LintNames.avoid_returning_null: needs evaluation
+LintNames.avoid_returning_null_for_future: has fix(es)
+LintNames.avoid_returning_null_for_void: has fix(es)
+LintNames.avoid_returning_this: needs evaluation
+LintNames.avoid_setters_without_getters: needs evaluation
+LintNames.avoid_shadowing_type_parameters: needs evaluation
+LintNames.avoid_single_cascade_in_expression_statements: has fix(es)
+LintNames.avoid_slow_async_io: needs evaluation
+LintNames.avoid_type_to_string: needs evaluation
+LintNames.avoid_types_as_parameter_names: has fix(es)
+LintNames.avoid_types_on_closure_parameters: has fix(es)
+LintNames.avoid_unnecessary_containers: has fix(es)
+LintNames.avoid_unused_constructor_parameters: has fix(es)
+LintNames.avoid_void_async: needs evaluation
+LintNames.avoid_web_libraries_in_flutter: needs evaluation
+LintNames.await_only_futures: has fix(es)
+LintNames.camel_case_extensions: needs evaluation
+LintNames.camel_case_types: needs evaluation
+LintNames.cancel_subscriptions: needs evaluation
+LintNames.cascade_invocations: needs evaluation
+LintNames.cast_nullable_to_non_nullable: needs evaluation
+LintNames.close_sinks: needs evaluation
+LintNames.comment_references: needs evaluation
+LintNames.conditional_uri_does_not_exist: needs evaluation
+LintNames.constant_identifier_names: needs evaluation
+LintNames.control_flow_in_finally: needs evaluation
+LintNames.curly_braces_in_flow_control_structures: has fix(es)
+LintNames.depend_on_referenced_packages: needs evaluation
+LintNames.deprecated_consistency: needs evaluation
+LintNames.diagnostic_describe_all_properties: has fix(es)
+LintNames.directives_ordering: has fix(es)
+LintNames.do_not_use_environment: needs evaluation
+LintNames.empty_catches: has fix(es)
+LintNames.empty_constructor_bodies: has fix(es)
+LintNames.empty_statements: has fix(es)
+LintNames.eol_at_end_of_file: has fix(es)
+LintNames.exhaustive_cases: has fix(es)
+LintNames.file_names: needs evaluation
+LintNames.flutter_style_todos: needs evaluation
+LintNames.hash_and_equals: has fix(es)
+LintNames.implementation_imports: needs evaluation
+LintNames.invariant_booleans: needs evaluation
+LintNames.iterable_contains_unrelated_type: needs evaluation
+LintNames.join_return_with_assignment: needs evaluation
+LintNames.leading_newlines_in_multiline_strings: has fix(es)
+LintNames.library_names: needs evaluation
+LintNames.library_prefixes: needs evaluation
+LintNames.library_private_types_in_public_api: needs evaluation
+LintNames.lines_longer_than_80_chars: needs evaluation
+LintNames.list_remove_unrelated_type: needs evaluation
+LintNames.literal_only_boolean_expressions: needs evaluation
+LintNames.missing_whitespace_between_adjacent_strings: needs evaluation
+LintNames.no_adjacent_strings_in_list: needs evaluation
+LintNames.no_default_cases: needs evaluation
+LintNames.no_duplicate_case_values: has fix(es)
+LintNames.no_leading_underscores_for_library_prefixes: needs evaluation
+LintNames.no_leading_underscores_for_local_identifiers: needs evaluation
+LintNames.no_logic_in_create_state: needs evaluation
+LintNames.no_runtimeType_toString: needs evaluation
+LintNames.non_constant_identifier_names: has fix(es)
+LintNames.noop_primitive_operations: needs evaluation
+LintNames.null_check_on_nullable_type_parameter: needs evaluation
+LintNames.null_closures: has fix(es)
+LintNames.omit_local_variable_types: has fix(es)
+LintNames.one_member_abstracts: needs evaluation
+LintNames.only_throw_errors: needs evaluation
+LintNames.overridden_fields: needs evaluation
+LintNames.package_api_docs: needs evaluation
+LintNames.package_prefixed_library_names: needs evaluation
+LintNames.parameter_assignments: needs evaluation
+LintNames.prefer_adjacent_string_concatenation: has fix(es)
+LintNames.prefer_asserts_in_initializer_lists: needs evaluation
+LintNames.prefer_asserts_with_message: needs evaluation
+LintNames.prefer_bool_in_asserts: needs evaluation
+LintNames.prefer_collection_literals: has fix(es)
+LintNames.prefer_conditional_assignment: has fix(es)
+LintNames.prefer_const_constructors: has fix(es)
+LintNames.prefer_const_constructors_in_immutables: has fix(es)
+LintNames.prefer_const_declarations: has fix(es)
+LintNames.prefer_const_literals_to_create_immutables: has fix(es)
+LintNames.prefer_constructors_over_static_methods: needs evaluation
+LintNames.prefer_contains: has fix(es)
+LintNames.prefer_double_quotes: has fix(es)
+LintNames.prefer_equal_for_default_values: has fix(es)
+LintNames.prefer_expression_function_bodies: has fix(es)
+LintNames.prefer_final_fields: has fix(es)
+LintNames.prefer_final_in_for_each: has fix(es)
+LintNames.prefer_final_locals: has fix(es)
+LintNames.prefer_final_parameters: has fix(es)
+LintNames.prefer_for_elements_to_map_fromIterable: has fix(es)
+LintNames.prefer_foreach: needs evaluation
+LintNames.prefer_function_declarations_over_variables: needs evaluation
+LintNames.prefer_generic_function_type_aliases: has fix(es)
+LintNames.prefer_if_elements_to_conditional_expressions: has fix(es)
+LintNames.prefer_if_null_operators: has fix(es)
+LintNames.prefer_initializing_formals: has fix(es)
+LintNames.prefer_inlined_adds: has fix(es)
+LintNames.prefer_int_literals: has fix(es)
+LintNames.prefer_interpolation_to_compose_strings: has fix(es)
+LintNames.prefer_is_empty: has fix(es)
+LintNames.prefer_is_not_empty: has fix(es)
+LintNames.prefer_is_not_operator: has fix(es)
+LintNames.prefer_iterable_whereType: has fix(es)
+LintNames.prefer_mixin: needs evaluation
+LintNames.prefer_null_aware_method_calls: needs evaluation
+LintNames.prefer_null_aware_operators: has fix(es)
+LintNames.prefer_relative_imports: has fix(es)
+LintNames.prefer_single_quotes: has fix(es)
+LintNames.prefer_spread_collections: has fix(es)
+LintNames.prefer_typing_uninitialized_variables: has fix(es)
+LintNames.prefer_void_to_null: has fix(es)
+LintNames.provide_deprecation_message: needs evaluation
+LintNames.pub/package_names: needs evaluation
+LintNames.pub/secure_pubspec_urls: needs evaluation
+LintNames.pub/sort_pub_dependencies: needs evaluation
+LintNames.public_member_api_docs: needs evaluation
+LintNames.recursive_getters: needs evaluation
+LintNames.require_trailing_commas: has fix(es)
+LintNames.sized_box_for_whitespace: has fix(es)
+LintNames.sized_box_shrink_expand: needs evaluation
+LintNames.slash_for_doc_comments: has fix(es)
+LintNames.sort_child_properties_last: has fix(es)
+LintNames.sort_constructors_first: needs fix; https://github.com/dart-lang/sdk/issues/47953
+LintNames.sort_unnamed_constructors_first: needs evaluation
+LintNames.super_goes_last: needs evaluation
+LintNames.test_types_in_equals: needs evaluation
+LintNames.throw_in_finally: needs evaluation
+LintNames.tighten_type_of_initializing_formals: needs evaluation
+LintNames.type_annotate_public_apis: has fix(es)
+LintNames.type_init_formals: has fix(es)
+LintNames.unawaited_futures: has fix(es)
+LintNames.unnecessary_await_in_return: needs evaluation
+LintNames.unnecessary_brace_in_string_interps: has fix(es)
+LintNames.unnecessary_const: has fix(es)
+LintNames.unnecessary_constructor_name: has fix(es)
+LintNames.unnecessary_final: has fix(es)
+LintNames.unnecessary_getters_setters: has fix(es)
+LintNames.unnecessary_lambdas: has fix(es)
+LintNames.unnecessary_late: needs evaluation
+LintNames.unnecessary_new: has fix(es)
+LintNames.unnecessary_null_aware_assignments: needs evaluation
+LintNames.unnecessary_null_checks: needs evaluation
+LintNames.unnecessary_null_in_if_null_operators: has fix(es)
+LintNames.unnecessary_nullable_for_final_variable_declarations: has fix(es)
+LintNames.unnecessary_overrides: has fix(es)
+LintNames.unnecessary_parenthesis: has fix(es)
+LintNames.unnecessary_raw_strings: has fix(es)
+LintNames.unnecessary_statements: needs evaluation
+LintNames.unnecessary_string_escapes: has fix(es)
+LintNames.unnecessary_string_interpolations: has fix(es)
+LintNames.unnecessary_this: has fix(es)
+LintNames.unrelated_type_equality_checks: needs evaluation
+LintNames.unsafe_html: needs evaluation
+LintNames.use_build_context_synchronously: needs evaluation
+LintNames.use_decorated_box: needs evaluation
+LintNames.use_full_hex_values_for_flutter_colors: has fix(es)
+LintNames.use_function_type_syntax_for_parameters: has fix(es)
+LintNames.use_if_null_to_convert_nulls_to_bools: needs evaluation
+LintNames.use_is_even_rather_than_modulo: needs evaluation
+LintNames.use_key_in_widget_constructors: has fix(es)
+LintNames.use_late_for_private_fields_and_variables: needs evaluation
+LintNames.use_named_constants: needs evaluation
+LintNames.use_raw_strings: needs evaluation
+LintNames.use_rethrow_when_possible: has fix(es)
+LintNames.use_setters_to_change_properties: needs evaluation
+LintNames.use_string_buffers: needs evaluation
+LintNames.use_test_throws_matchers: needs evaluation
+LintNames.use_to_and_as_if_applicable: needs evaluation
+LintNames.valid_regexps: needs evaluation
+LintNames.void_checks: needs evaluation
+ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE: needs evaluation
+ManifestWarningCode.NO_TOUCHSCREEN_FEATURE: needs evaluation
+ManifestWarningCode.NON_RESIZABLE_ACTIVITY: needs evaluation
+ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE: needs evaluation
+ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY: needs evaluation
+ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE: needs evaluation
+ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE: needs evaluation
+ParserErrorCode.ABSTRACT_CLASS_MEMBER: has fix(es)
+ParserErrorCode.ABSTRACT_ENUM: needs evaluation
+ParserErrorCode.ABSTRACT_EXTERNAL_FIELD: needs evaluation
+ParserErrorCode.ABSTRACT_LATE_FIELD: needs evaluation
+ParserErrorCode.ABSTRACT_STATIC_FIELD: needs evaluation
+ParserErrorCode.ABSTRACT_STATIC_METHOD: needs evaluation
+ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION: needs evaluation
+ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE: needs evaluation
+ParserErrorCode.ABSTRACT_TYPEDEF: needs evaluation
+ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT: needs evaluation
+ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS: needs evaluation
+ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED: needs evaluation
+ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER: needs evaluation
+ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT: needs evaluation
+ParserErrorCode.BREAK_OUTSIDE_OF_LOOP: needs evaluation
+ParserErrorCode.CATCH_SYNTAX: needs evaluation
+ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS: needs evaluation
+ParserErrorCode.CLASS_IN_CLASS: needs evaluation
+ParserErrorCode.COLON_IN_PLACE_OF_IN: needs evaluation
+ParserErrorCode.CONFLICTING_MODIFIERS: needs evaluation
+ParserErrorCode.CONST_AND_FINAL: needs evaluation
+ParserErrorCode.CONST_CLASS: needs evaluation
+ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY: needs evaluation
+ParserErrorCode.CONST_ENUM: needs evaluation
+ParserErrorCode.CONST_FACTORY: needs evaluation
+ParserErrorCode.CONST_METHOD: needs evaluation
+ParserErrorCode.CONST_TYPEDEF: needs evaluation
+ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE: needs evaluation
+ParserErrorCode.CONSTRUCTOR_WITH_TYPE_ARGUMENTS: needs evaluation
+ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP: needs evaluation
+ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE: needs evaluation
+ParserErrorCode.COVARIANT_AND_STATIC: needs evaluation
+ParserErrorCode.COVARIANT_CONSTRUCTOR: needs evaluation
+ParserErrorCode.COVARIANT_MEMBER: needs evaluation
+ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION: needs evaluation
+ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE: needs evaluation
+ParserErrorCode.DEFERRED_AFTER_PREFIX: needs evaluation
+ParserErrorCode.DIRECTIVE_AFTER_DECLARATION: needs evaluation
+ParserErrorCode.DUPLICATE_DEFERRED: needs evaluation
+ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT: needs evaluation
+ParserErrorCode.DUPLICATE_PREFIX: needs evaluation
+ParserErrorCode.DUPLICATED_MODIFIER: needs evaluation
+ParserErrorCode.EMPTY_ENUM_BODY: needs evaluation
+ParserErrorCode.ENUM_IN_CLASS: needs evaluation
+ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND: needs evaluation
+ParserErrorCode.EXPECTED_BODY: needs evaluation
+ParserErrorCode.EXPECTED_CASE_OR_DEFAULT: needs evaluation
+ParserErrorCode.EXPECTED_CLASS_MEMBER: needs evaluation
+ParserErrorCode.EXPECTED_ELSE_OR_COMMA: needs evaluation
+ParserErrorCode.EXPECTED_EXECUTABLE: needs evaluation
+ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD: needs evaluation
+ParserErrorCode.EXPECTED_INSTEAD: needs evaluation
+ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL: needs evaluation
+ParserErrorCode.EXPECTED_STRING_LITERAL: needs evaluation
+ParserErrorCode.EXPECTED_TOKEN: has fix(es)
+ParserErrorCode.EXPECTED_TYPE_NAME: needs evaluation
+ParserErrorCode.EXPERIMENT_NOT_ENABLED: needs evaluation
+ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE: needs evaluation
+ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER: needs evaluation
+ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR: needs evaluation
+ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD: needs evaluation
+ParserErrorCode.EXTERNAL_CLASS: needs evaluation
+ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_INITIALIZER: needs evaluation
+ParserErrorCode.EXTERNAL_ENUM: needs evaluation
+ParserErrorCode.EXTERNAL_FACTORY_REDIRECTION: needs evaluation
+ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_FIELD: needs evaluation
+ParserErrorCode.EXTERNAL_GETTER_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_LATE_FIELD: needs evaluation
+ParserErrorCode.EXTERNAL_METHOD_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_SETTER_WITH_BODY: needs evaluation
+ParserErrorCode.EXTERNAL_TYPEDEF: needs evaluation
+ParserErrorCode.EXTRANEOUS_MODIFIER: needs evaluation
+ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION: needs evaluation
+ParserErrorCode.FACTORY_WITH_INITIALIZERS: needs evaluation
+ParserErrorCode.FACTORY_WITHOUT_BODY: needs evaluation
+ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS: needs evaluation
+ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR: needs evaluation
+ParserErrorCode.FINAL_AND_COVARIANT: needs evaluation
+ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER: needs evaluation
+ParserErrorCode.FINAL_AND_VAR: needs evaluation
+ParserErrorCode.FINAL_CLASS: needs evaluation
+ParserErrorCode.FINAL_CONSTRUCTOR: needs evaluation
+ParserErrorCode.FINAL_ENUM: needs evaluation
+ParserErrorCode.FINAL_METHOD: needs evaluation
+ParserErrorCode.FINAL_TYPEDEF: needs evaluation
+ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR: needs evaluation
+ParserErrorCode.GETTER_CONSTRUCTOR: needs evaluation
+ParserErrorCode.GETTER_IN_FUNCTION: needs evaluation
+ParserErrorCode.GETTER_WITH_PARAMETERS: has fix(es)
+ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE: needs evaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS: needs evaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_ON: needs evaluation
+ParserErrorCode.IMPLEMENTS_BEFORE_WITH: needs evaluation
+ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE: needs evaluation
+ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH: needs evaluation
+ParserErrorCode.INVALID_AWAIT_IN_FOR: needs evaluation
+ParserErrorCode.INVALID_CODE_POINT: needs evaluation
+ParserErrorCode.INVALID_COMMENT_REFERENCE: needs evaluation
+ParserErrorCode.INVALID_CONSTRUCTOR_NAME: needs evaluation
+ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE: needs evaluation
+ParserErrorCode.INVALID_HEX_ESCAPE: needs evaluation
+ParserErrorCode.INVALID_INITIALIZER: needs evaluation
+ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION: needs evaluation
+ParserErrorCode.INVALID_OPERATOR: needs evaluation
+ParserErrorCode.INVALID_OPERATOR_FOR_SUPER: needs evaluation
+ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER: needs evaluation
+ParserErrorCode.INVALID_STAR_AFTER_ASYNC: needs evaluation
+ParserErrorCode.INVALID_SUPER_IN_INITIALIZER: needs evaluation
+ParserErrorCode.INVALID_SYNC: needs evaluation
+ParserErrorCode.INVALID_THIS_IN_INITIALIZER: needs evaluation
+ParserErrorCode.INVALID_UNICODE_ESCAPE: needs evaluation
+ParserErrorCode.INVALID_USE_OF_COVARIANT_IN_EXTENSION: needs evaluation
+ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST: needs evaluation
+ParserErrorCode.LITERAL_WITH_CLASS_AND_NEW: needs evaluation
+ParserErrorCode.LITERAL_WITH_CLASS: needs evaluation
+ParserErrorCode.LITERAL_WITH_NEW: needs evaluation
+ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER: needs evaluation
+ParserErrorCode.MEMBER_WITH_CLASS_NAME: needs evaluation
+ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR: needs evaluation
+ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER: needs evaluation
+ParserErrorCode.MISSING_CATCH_OR_FINALLY: needs evaluation
+ParserErrorCode.MISSING_CLOSING_PARENTHESIS: needs evaluation
+ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE: has fix(es)
+ParserErrorCode.MISSING_ENUM_BODY: needs evaluation
+ParserErrorCode.MISSING_EXPRESSION_IN_INITIALIZER: needs evaluation
+ParserErrorCode.MISSING_EXPRESSION_IN_THROW: needs evaluation
+ParserErrorCode.MISSING_FUNCTION_BODY: has fix(es)
+ParserErrorCode.MISSING_FUNCTION_KEYWORD: needs evaluation
+ParserErrorCode.MISSING_FUNCTION_PARAMETERS: needs evaluation
+ParserErrorCode.MISSING_GET: needs evaluation
+ParserErrorCode.MISSING_IDENTIFIER: needs evaluation
+ParserErrorCode.MISSING_INITIALIZER: needs evaluation
+ParserErrorCode.MISSING_KEYWORD_OPERATOR: needs evaluation
+ParserErrorCode.MISSING_METHOD_PARAMETERS: needs evaluation
+ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER: needs evaluation
+ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE: needs evaluation
+ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE: needs evaluation
+ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT: needs evaluation
+ParserErrorCode.MISSING_STAR_AFTER_SYNC: needs evaluation
+ParserErrorCode.MISSING_STATEMENT: needs evaluation
+ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
+ParserErrorCode.MISSING_TYPEDEF_PARAMETERS: needs evaluation
+ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH: needs evaluation
+ParserErrorCode.MIXED_PARAMETER_GROUPS: needs evaluation
+ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR: needs evaluation
+ParserErrorCode.MODIFIER_OUT_OF_ORDER: needs evaluation
+ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES: needs evaluation
+ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES: needs evaluation
+ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES: needs evaluation
+ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS: needs evaluation
+ParserErrorCode.MULTIPLE_ON_CLAUSES: needs evaluation
+ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES: needs evaluation
+ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS: needs evaluation
+ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH: needs evaluation
+ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS: needs evaluation
+ParserErrorCode.MULTIPLE_WITH_CLAUSES: needs evaluation
+ParserErrorCode.NAMED_FUNCTION_EXPRESSION: needs evaluation
+ParserErrorCode.NAMED_FUNCTION_TYPE: needs evaluation
+ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP: needs evaluation
+ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE: needs evaluation
+ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION: needs evaluation
+ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE: needs evaluation
+ParserErrorCode.NON_CONSTRUCTOR_FACTORY: needs evaluation
+ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME: needs evaluation
+ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART: needs evaluation
+ParserErrorCode.NON_STRING_LITERAL_AS_URI: needs evaluation
+ParserErrorCode.NON_USER_DEFINABLE_OPERATOR: needs evaluation
+ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS: needs evaluation
+ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER: needs evaluation
+ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT: needs evaluation
+ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP: needs evaluation
+ParserErrorCode.PREFIX_AFTER_COMBINATOR: needs evaluation
+ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY: needs evaluation
+ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR: needs evaluation
+ParserErrorCode.SETTER_CONSTRUCTOR: needs evaluation
+ParserErrorCode.SETTER_IN_FUNCTION: needs evaluation
+ParserErrorCode.STACK_OVERFLOW: needs evaluation
+ParserErrorCode.STATIC_CONSTRUCTOR: needs evaluation
+ParserErrorCode.STATIC_GETTER_WITHOUT_BODY: needs evaluation
+ParserErrorCode.STATIC_OPERATOR: needs evaluation
+ParserErrorCode.STATIC_SETTER_WITHOUT_BODY: needs evaluation
+ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION: needs evaluation
+ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE: needs evaluation
+ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES: needs evaluation
+ParserErrorCode.TOP_LEVEL_OPERATOR: needs evaluation
+ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE: needs evaluation
+ParserErrorCode.TYPE_BEFORE_FACTORY: needs evaluation
+ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR: needs evaluation
+ParserErrorCode.TYPE_PARAMETER_ON_OPERATOR: needs evaluation
+ParserErrorCode.TYPEDEF_IN_CLASS: needs evaluation
+ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
+ParserErrorCode.UNEXPECTED_TOKEN: needs evaluation
+ParserErrorCode.VAR_AND_TYPE: needs evaluation
+ParserErrorCode.VAR_AS_TYPE_NAME: has fix(es)
+ParserErrorCode.VAR_CLASS: needs evaluation
+ParserErrorCode.VAR_ENUM: needs evaluation
+ParserErrorCode.VAR_RETURN_TYPE: needs evaluation
+ParserErrorCode.VAR_TYPEDEF: needs evaluation
+ParserErrorCode.VOID_WITH_TYPE_ARGUMENTS: needs evaluation
+ParserErrorCode.WITH_BEFORE_EXTENDS: needs evaluation
+ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER: needs evaluation
+ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP: needs evaluation
+PubspecWarningCode.ASSET_DOES_NOT_EXIST: needs evaluation
+PubspecWarningCode.ASSET_DIRECTORY_DOES_NOT_EXIST: needs evaluation
+PubspecWarningCode.ASSET_FIELD_NOT_LIST: needs evaluation
+PubspecWarningCode.ASSET_NOT_STRING: needs evaluation
+PubspecWarningCode.DEPENDENCIES_FIELD_NOT_MAP: needs evaluation
+PubspecWarningCode.DEPRECATED_FIELD: needs evaluation
+PubspecWarningCode.FLUTTER_FIELD_NOT_MAP: needs evaluation
+PubspecWarningCode.INVALID_DEPENDENCY: needs evaluation
+PubspecWarningCode.MISSING_NAME: needs evaluation
+PubspecWarningCode.NAME_NOT_STRING: needs evaluation
+PubspecWarningCode.PATH_DOES_NOT_EXIST: needs evaluation
+PubspecWarningCode.PATH_NOT_POSIX: needs evaluation
+PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST: needs evaluation
+PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY: needs evaluation
+ScannerErrorCode.EXPECTED_TOKEN: needs evaluation
+ScannerErrorCode.ILLEGAL_CHARACTER: needs evaluation
+ScannerErrorCode.MISSING_DIGIT: needs evaluation
+ScannerErrorCode.MISSING_HEX_DIGIT: needs evaluation
+ScannerErrorCode.MISSING_IDENTIFIER: needs evaluation
+ScannerErrorCode.MISSING_QUOTE: needs evaluation
+ScannerErrorCode.UNABLE_GET_CONTENT: needs evaluation
+ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING: needs evaluation
+ScannerErrorCode.UNSUPPORTED_OPERATOR: needs evaluation
+ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT: needs evaluation
+ScannerErrorCode.UNTERMINATED_STRING_LITERAL: needs evaluation
+StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION: has fix(es)
+StaticWarningCode.INVALID_NULL_AWARE_OPERATOR: has fix(es)
+StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT: has fix(es)
+StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED: needs evaluation
+StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL: needs evaluation
+StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH: has fix(es)
+StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION: has fix(es)
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 666ea13..b4fb0b2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -143,6 +143,16 @@
     DartFixKindPriority.DEFAULT,
     "Add 'late' modifier",
   );
+  static const ADD_LEADING_NEWLINE_TO_STRING = FixKind(
+    'dart.fix.add.leadingNewlineToString',
+    DartFixKindPriority.DEFAULT,
+    'Add leading new line',
+  );
+  static const ADD_LEADING_NEWLINE_TO_STRING_MULTI = FixKind(
+    'dart.fix.add.leadingNewlineToString.multi',
+    DartFixKindPriority.DEFAULT,
+    'Add leading new line everywhere in file',
+  );
   static const ADD_MISSING_ENUM_CASE_CLAUSES = FixKind(
     'dart.fix.add.missingEnumCaseClauses',
     DartFixKindPriority.DEFAULT,
@@ -635,6 +645,11 @@
     DartFixKindPriority.DEFAULT,
     "Extend the class '{0}'",
   );
+  static const EXTRACT_LOCAL_VARIABLE = FixKind(
+    'dart.fix.extractLocalVariable',
+    DartFixKindPriority.DEFAULT,
+    'Extract local variable',
+  );
   static const IGNORE_ERROR_LINE = FixKind(
     'dart.fix.ignore.line',
     DartFixKindPriority.IGNORE,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index 837025a..acceb63 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -26,13 +26,14 @@
   final List<ElementKind> validKinds;
 
   /// Initialize a newly created matcher representing a reference to an element
-  /// with the given [name] in a library that imports the [importedUris].
+  /// whose name matches the given [components] and element [kinds] in a library
+  /// that imports the [importedUris].
   ElementMatcher(
       {required this.importedUris,
       required this.components,
-      List<ElementKind>? kinds})
+      required List<ElementKind> kinds})
       : assert(components.isNotEmpty),
-        validKinds = kinds ?? const [];
+        validKinds = kinds;
 
   /// Return `true` if this matcher matches the given [element].
   bool matches(ElementDescriptor element) {
@@ -93,79 +94,389 @@
     return false;
   }
 
-  /// Return an element matcher that will match the element that is, or should
-  /// be, associated with the given [node], or `null` if there is no appropriate
-  /// matcher for the node.
-  static ElementMatcher? forNode(AstNode? node) {
+  /// Return a list of element matchers that will match the element that is, or
+  /// should be, associated with the given [node]. The list will be empty if
+  /// there are no appropriate matchers for the [node].
+  static List<ElementMatcher> matchersForNode(AstNode? node) {
     if (node == null) {
-      return null;
+      return const <ElementMatcher>[];
     }
     var importedUris = _importElementsForNode(node);
     if (importedUris == null) {
-      return null;
+      return const <ElementMatcher>[];
     }
-    var components = _componentsForNode(node);
-    if (components == null) {
-      return null;
-    }
-    return ElementMatcher(
-        importedUris: importedUris,
-        components: components,
-        kinds: _kindsForNode(node));
+    var builder = _MatcherBuilder(importedUris);
+    builder.buildMatchersForNode(node);
+    return builder.matchers.toList();
   }
 
-  /// Return the components of the path of the element associated with the given
-  /// [node]. The components are ordered from the most local to the most global.
-  /// For example, for a constructor this would be the name of the constructor
-  /// followed by the name of the class in which the constructor is declared
-  /// (with an empty string for the unnamed constructor).
-  static List<String>? _componentsForNode(AstNode? node) {
-    if (node is SimpleIdentifier) {
-      var parent = node.parent;
-      if (parent is Label && parent.parent is NamedExpression) {
-        // The parent of the named expression is an argument list. Because we
-        // don't represent parameters as elements, the element we need to match
-        // against is the invocation containing those arguments.
-        return _componentsFromParent(parent.parent!.parent!);
-      } else if (parent is NamedType && parent.parent is ConstructorName) {
-        return ['', node.name];
-      } else if (parent is MethodDeclaration && node == parent.name) {
-        return [node.name];
-      } else if ((parent is MethodInvocation &&
-              node == parent.methodName &&
-              !_isPrefix(parent.target)) ||
-          (parent is PrefixedIdentifier &&
-              node == parent.identifier &&
-              !_isPrefix(parent.prefix)) ||
-          (parent is PropertyAccess &&
-              node == parent.propertyName &&
-              !_isPrefix(parent.target))) {
-        return _componentsFromParent(node);
+  /// Return the URIs of the imports in the library containing the [node], or
+  /// `null` if the imports can't be determined.
+  static List<Uri>? _importElementsForNode(AstNode node) {
+    var root = node.root;
+    if (root is! CompilationUnit) {
+      return null;
+    }
+    var importedUris = <Uri>[];
+    var library = root.declaredElement?.library;
+    if (library == null) {
+      return null;
+    }
+    for (var importElement in library.imports) {
+      // TODO(brianwilkerson) Filter based on combinators to help avoid making
+      //  invalid suggestions.
+      var uri = importElement.importedLibrary?.source.uri;
+      if (uri != null) {
+        // The [uri] is `null` if the literal string is not a valid URI.
+        importedUris.add(uri);
       }
-      return _componentsFromIdentifier(node);
-    } else if (node is PrefixedIdentifier) {
-      var parent = node.parent;
-      if (parent is NamedType && parent.parent is ConstructorName) {
-        return ['', node.identifier.name];
-      }
-      return [node.identifier.name];
+    }
+    return importedUris;
+  }
+}
+
+/// A helper class used to build a list of element matchers.
+class _MatcherBuilder {
+  final List<ElementMatcher> matchers = [];
+
+  final List<Uri> importedUris;
+
+  _MatcherBuilder(this.importedUris);
+
+  void buildMatchersForNode(AstNode? node) {
+    if (node is ArgumentList) {
+      _buildFromArgumentList(node);
+    } else if (node is BinaryExpression) {
+      _buildFromBinaryExpression(node);
     } else if (node is ConstructorName) {
-      var constructorName = node.name;
-      if (constructorName != null) {
-        return [constructorName.name];
+      _buildFromConstructorName(node);
+    } else if (node is Literal) {
+      var parent = node.parent;
+      if (parent is ArgumentList) {
+        _buildFromArgumentList(parent);
       }
     } else if (node is NamedType) {
-      return [node.name.name];
+      _buildFromNamedType(node);
+    } else if (node is PrefixedIdentifier) {
+      _buildFromPrefixedIdentifier(node);
+    } else if (node is SimpleIdentifier) {
+      _buildFromSimpleIdentifier(node);
     } else if (node is TypeArgumentList) {
-      return _componentsFromParent(node);
-    } else if (node is ArgumentList) {
-      return _componentsFromParent(node);
+      _buildFromTypeArgumentList(node);
     }
-    var parent = node?.parent;
-    if (parent is ArgumentList) {
-      return _componentsFromParent(parent);
+  }
+
+  void _addMatcher(
+      {required List<String> components, required List<ElementKind> kinds}) {
+    matchers.add(ElementMatcher(
+        importedUris: importedUris, components: components, kinds: kinds));
+  }
+
+  /// Build a matcher for the element being invoked.
+  void _buildFromArgumentList(ArgumentList node) {
+    var parent = node.parent;
+    if (parent is Annotation) {
+      _addMatcher(
+        components: [parent.constructorName?.name ?? '', parent.name.name],
+        kinds: [ElementKind.constructorKind],
+      );
+      // } else if (parent is ExtensionOverride) {
+      //   // TODO(brianwilkerson) Determine whether this branch can be reached.
+      //   _buildFromExtensionOverride(parent);
+    } else if (parent is FunctionExpressionInvocation) {
+      _buildFromFunctionExpressionInvocation(parent);
+    } else if (parent is InstanceCreationExpression) {
+      _buildFromInstanceCreationExpression(parent);
+    } else if (parent is MethodInvocation) {
+      _buildFromMethodInvocation(parent);
+    } else if (parent is RedirectingConstructorInvocation) {
+      var grandparent = parent.parent;
+      if (grandparent is ConstructorDeclaration) {
+        _addMatcher(
+          components: [
+            parent.constructorName?.name ?? '',
+            grandparent.returnType.name
+          ],
+          kinds: [ElementKind.constructorKind],
+        );
+      }
+    } else if (parent is SuperConstructorInvocation) {
+      var superclassName = parent.staticElement?.enclosingElement.name;
+      if (superclassName != null) {
+        _addMatcher(
+          components: [parent.constructorName?.name ?? '', superclassName],
+          kinds: [ElementKind.constructorKind],
+        );
+      }
     }
-    return null;
+  }
+
+  /// Build a matcher for the operator being invoked.
+  void _buildFromBinaryExpression(BinaryExpression node) {
+    // TODO(brianwilkerson) Implement this method in order to support changes to
+    //  operators.
+  }
+
+  /// Build a matcher for the constructor being referenced.
+  void _buildFromConstructorName(ConstructorName node) {
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    // TODO(brianwilkerson) Use 'new' for the name of the unnamed constructor.
+    var constructorName = node.name?.name ?? ''; // ?? 'new';
+    var className = node.type2.name.simpleName;
+    _addMatcher(
+      components: [constructorName, className],
+      kinds: const [ElementKind.constructorKind],
+    );
+    _addMatcher(
+      components: [className],
+      kinds: const [ElementKind.classKind],
+    );
+  }
+
+  /// Build a matcher for the extension.
+  void _buildFromExtensionOverride(ExtensionOverride node) {
+    _addMatcher(
+      components: [node.extensionName.name],
+      kinds: [ElementKind.extensionKind],
+    );
+  }
+
+  /// Build a matcher for the function being invoked.
+  void _buildFromFunctionExpressionInvocation(
+      FunctionExpressionInvocation node) {
+    // TODO(brianwilkerson) This case was missed in the original implementation
+    //  and there are no tests for it at this point, but it ought to be supported.
+  }
+
+  /// Build a matcher for the constructor being invoked.
+  void _buildFromInstanceCreationExpression(InstanceCreationExpression node) {
+    _buildFromConstructorName(node.constructorName);
+  }
+
+  /// Build a matcher for the method being declared.
+  void _buildFromMethodDeclaration(MethodDeclaration node) {
+    _addMatcher(
+      components: [node.name.name],
+      kinds: [ElementKind.methodKind],
+    );
+  }
+
+  /// Build a matcher for the method being invoked.
+  void _buildFromMethodInvocation(MethodInvocation node) {
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    // var element = node.methodName.staticElement;
+    // if (element != null) {
+    //   return _buildFromElement(element);
+    // }
+    var methodName = node.methodName;
+    var targetName = _nameOfTarget(node.realTarget);
+    if (targetName != null) {
+      // If there is a target, and we know the type of the target, then we know
+      // that a method is being invoked.
+      _addMatcher(
+        components: [methodName.name, targetName],
+        kinds: [
+          ElementKind.constructorKind,
+          ElementKind.methodKind,
+        ],
+      );
+    } else if (node.realTarget != null) {
+      // If there is a target, but we don't know the type of the target, then
+      // the target type might be undefined and this might have been either a
+      // method invocation, an invocation of a function returned by a getter, or
+      // a constructor invocation prior to the type having been deleted.
+      _addMatcher(
+        components: _componentsFromIdentifier(methodName),
+        kinds: [
+          ElementKind.constructorKind,
+          ElementKind.getterKind,
+          ElementKind.methodKind,
+        ],
+      );
+    } else {
+      // If there is no target, then this might have been either a method
+      // invocation, a function invocation (of either a function or a function
+      // returned from a getter), a constructor invocation, or an extension
+      // override. If it's a constructor, then the change might have been to the
+      // class rather than an individual constructor.
+      _addMatcher(
+        components: _componentsFromIdentifier(methodName),
+        kinds: [
+          ElementKind.classKind,
+          ElementKind.constructorKind,
+          ElementKind.extensionKind,
+          ElementKind.functionKind,
+          ElementKind.getterKind,
+          ElementKind.methodKind,
+        ],
+      );
+    }
+  }
+
+  /// Build a matcher for the type.
+  void _buildFromNamedType(NamedType node) {
+    var parent = node.parent;
+    if (parent is ConstructorName) {
+      return _buildFromConstructorName(parent);
+    }
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    _addMatcher(
+      components: [node.name.simpleName],
+      kinds: const [
+        ElementKind.classKind,
+        ElementKind.enumKind,
+        ElementKind.mixinKind,
+        ElementKind.typedefKind
+      ],
+    );
+    // TODO(brianwilkerson) Determine whether we can ever get here as a result
+    //  of having a removed unnamed constructor.
+    // _addMatcher(
+    //   components: ['', node.name.name],
+    //   kinds: const [ElementKind.constructorKind],
+    // );
+  }
+
+  /// Build a matcher for the element represented by the prefixed identifier.
+  void _buildFromPrefixedIdentifier(PrefixedIdentifier node) {
+    var parent = node.parent;
+    if (parent is NamedType) {
+      return _buildFromNamedType(parent);
+    }
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    var prefix = node.prefix;
+    if (prefix.staticElement is PrefixElement) {
+      var parent = node.parent;
+      if ((parent is NamedType && parent.parent is! ConstructorName) ||
+          (parent is PropertyAccess && parent.target == node)) {
+        _addMatcher(components: [
+          node.identifier.name
+        ], kinds: const [
+          ElementKind.classKind,
+          ElementKind.enumKind,
+          ElementKind.extensionKind,
+          ElementKind.mixinKind,
+          ElementKind.typedefKind
+        ]);
+      }
+      _addMatcher(components: [
+        node.identifier.name
+      ], kinds: const [
+        // If the old class has been removed then this might have been a
+        // constructor invocation.
+        ElementKind.constructorKind,
+        ElementKind.functionKind, // tear-off
+        ElementKind.getterKind,
+        ElementKind.setterKind,
+        ElementKind.variableKind
+      ]);
+    }
+    // It looks like we're accessing a member, so try to figure out the
+    // name of the type defining the member.
+    var targetType = node.prefix.staticType;
+    if (targetType is InterfaceType) {
+      _addMatcher(
+        components: [node.identifier.name, targetType.element.name],
+        kinds: const [
+          ElementKind.constantKind,
+          ElementKind.fieldKind,
+          ElementKind.functionKind, // tear-off
+          ElementKind.getterKind,
+          ElementKind.methodKind, // tear-off
+          ElementKind.setterKind
+        ],
+      );
+    }
+    // It looks like we're accessing a member, but we don't know what kind of
+    // member, so we include all of the member kinds.
+    var container = node.prefix.staticElement;
+    if (container is ClassElement) {
+      _addMatcher(
+        components: [node.identifier.name, container.name],
+        kinds: const [
+          ElementKind.constantKind,
+          ElementKind.fieldKind,
+          ElementKind.functionKind, // tear-off
+          ElementKind.getterKind,
+          ElementKind.methodKind, // tear-off
+          ElementKind.setterKind
+        ],
+      );
+    }
+  }
+
+  /// Build a matcher for the property being accessed.
+  void _buildFromPropertyAccess(PropertyAccess node) {
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    var propertyName = node.propertyName;
+    var targetName = _nameOfTarget(node.realTarget);
+    List<String> components;
+    if (targetName != null) {
+      components = [propertyName.name, targetName];
+    } else {
+      components = _componentsFromIdentifier(propertyName);
+    }
+    _addMatcher(
+      components: components,
+      kinds: const [
+        ElementKind.constantKind,
+        ElementKind.fieldKind,
+        ElementKind.functionKind, // tear-off, prefixed
+        ElementKind.getterKind,
+        ElementKind.methodKind, // tear-off, prefixed
+        ElementKind.setterKind
+      ],
+    );
+  }
+
+  /// Build a matcher for the element referenced by the identifier.
+  void _buildFromSimpleIdentifier(SimpleIdentifier node) {
+    // TODO(brianwilkerson) Use the static element, if there is one, in order to
+    //  get a more exact matcher.
+    var parent = node.parent;
+    if (parent is Label && parent.parent is NamedExpression) {
+      // The parent of the named expression is an argument list. Because we
+      // don't represent parameters as elements, the element we need to match
+      // against is the invocation containing those arguments.
+      _buildFromArgumentList(parent.parent!.parent as ArgumentList);
+    } else if (parent is NamedType) {
+      _buildFromNamedType(parent);
+    } else if (parent is MethodDeclaration && node == parent.name) {
+      _buildFromMethodDeclaration(parent);
+    } else if (parent is MethodInvocation &&
+        node == parent.methodName &&
+        !_isPrefix(parent.target)) {
+      _buildFromMethodInvocation(parent);
+    } else if (parent is PrefixedIdentifier && node == parent.identifier) {
+      _buildFromPrefixedIdentifier(parent);
+    } else if (parent is PropertyAccess &&
+        node == parent.propertyName &&
+        !_isPrefix(parent.target)) {
+      _buildFromPropertyAccess(parent);
+    } else {
+      // TODO(brianwilkerson) See whether the list of kinds can be specified.
+      _addMatcher(components: [node.name], kinds: []);
+    }
+  }
+
+  /// Build a matcher for the element with which the type arguments are
+  /// associated.
+  void _buildFromTypeArgumentList(TypeArgumentList node) {
+    var parent = node.parent;
+    if (parent is ExtensionOverride) {
+      _buildFromExtensionOverride(parent);
+    } else if (parent is FunctionExpressionInvocation) {
+      _buildFromFunctionExpressionInvocation(parent);
+    } else if (parent is InstanceCreationExpression) {
+      _buildFromInstanceCreationExpression(parent);
+    } else if (parent is MethodInvocation) {
+      _buildFromMethodInvocation(parent);
+    }
   }
 
   /// Return the components associated with the [identifier] when there is no
@@ -192,185 +503,11 @@
     return [identifier.name];
   }
 
-  /// Return the components for the element associated with the given [node] by
-  /// looking at the parent of the [node].
-  static List<String>? _componentsFromParent(AstNode node) {
-    var parent = node.parent;
-    if (parent is ArgumentList) {
-      parent = parent.parent;
-    }
-    if (parent is Annotation) {
-      return [parent.constructorName?.name ?? '', parent.name.name];
-    } else if (parent is ExtensionOverride) {
-      return [parent.extensionName.name];
-    } else if (parent is InstanceCreationExpression) {
-      var constructorName = parent.constructorName;
-      return [
-        constructorName.name?.name ?? '',
-        constructorName.type2.name.name
-      ];
-    } else if (parent is MethodInvocation) {
-      var methodName = parent.methodName;
-      var targetName = _nameOfTarget(parent.realTarget);
-      if (targetName != null) {
-        return [methodName.name, targetName];
-      }
-      return _componentsFromIdentifier(methodName);
-    } else if (parent is PrefixedIdentifier) {
-      var identifier = parent.identifier;
-      var targetName = _nameOfTarget(parent.prefix);
-      if (targetName != null) {
-        return [identifier.name, targetName];
-      }
-      return _componentsFromIdentifier(identifier);
-    } else if (parent is PropertyAccess) {
-      var propertyName = parent.propertyName;
-      var targetName = _nameOfTarget(parent.realTarget);
-      if (targetName != null) {
-        return [propertyName.name, targetName];
-      }
-      return _componentsFromIdentifier(propertyName);
-    } else if (parent is RedirectingConstructorInvocation) {
-      var ancestor = parent.parent;
-      if (ancestor is ConstructorDeclaration) {
-        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
-      }
-    } else if (parent is SuperConstructorInvocation) {
-      var ancestor = parent.parent;
-      if (ancestor is ConstructorDeclaration) {
-        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
-      }
-    }
-    return null;
-  }
-
-  /// Return the URIs of the imports in the library containing the [node], or
-  /// `null` if the imports can't be determined.
-  static List<Uri>? _importElementsForNode(AstNode node) {
-    var root = node.root;
-    if (root is! CompilationUnit) {
-      return null;
-    }
-    var importedUris = <Uri>[];
-    var library = root.declaredElement?.library;
-    if (library == null) {
-      return null;
-    }
-    for (var importElement in library.imports) {
-      // TODO(brianwilkerson) Filter based on combinators to help avoid making
-      //  invalid suggestions.
-      var uri = importElement.importedLibrary?.source.uri;
-      if (uri != null) {
-        // The [uri] is `null` if the literal string is not a valid URI.
-        importedUris.add(uri);
-      }
-    }
-    return importedUris;
-  }
-
   /// Return `true` if the [node] is a prefix
   static bool _isPrefix(AstNode? node) {
     return node is SimpleIdentifier && node.staticElement is PrefixElement;
   }
 
-  /// Return the kinds of elements that could reasonably be referenced at the
-  /// location of the [node]. If [child] is not `null` then the [node] is a
-  /// parent of the [child].
-  static List<ElementKind>? _kindsForNode(AstNode? node, {AstNode? child}) {
-    if (node is ConstructorName) {
-      return const [ElementKind.constructorKind];
-    } else if (node is ExtensionOverride) {
-      return const [ElementKind.extensionKind];
-    } else if (node is InstanceCreationExpression) {
-      return const [ElementKind.constructorKind];
-    } else if (node is Label) {
-      var argumentList = node.parent?.parent;
-      return _kindsForNode(argumentList?.parent, child: argumentList);
-    } else if (node is MethodInvocation) {
-      assert(child != null);
-      if (node.target == child) {
-        return const [
-          ElementKind.classKind,
-          ElementKind.enumKind,
-          ElementKind.mixinKind
-        ];
-      }
-      var realTarget = node.realTarget;
-      if (realTarget != null && !_isPrefix(realTarget)) {
-        return const [ElementKind.constructorKind, ElementKind.methodKind];
-      }
-      return const [
-        ElementKind.classKind,
-        ElementKind.extensionKind,
-        ElementKind.functionKind,
-        ElementKind.methodKind
-      ];
-    } else if (node is NamedType) {
-      var parent = node.parent;
-      if (parent is ConstructorName && parent.name == null) {
-        return const [ElementKind.classKind, ElementKind.constructorKind];
-      }
-      return const [
-        ElementKind.classKind,
-        ElementKind.enumKind,
-        ElementKind.mixinKind,
-        ElementKind.typedefKind
-      ];
-    } else if (node is PrefixedIdentifier) {
-      var prefix = node.prefix;
-      if (prefix == child) {
-        return const [
-          ElementKind.classKind,
-          ElementKind.enumKind,
-          ElementKind.extensionKind,
-          ElementKind.mixinKind,
-          ElementKind.typedefKind
-        ];
-      } else if (prefix.staticElement is PrefixElement) {
-        var parent = node.parent;
-        if ((parent is NamedType && parent.parent is! ConstructorName) ||
-            (parent is PropertyAccess && parent.target == node)) {
-          return const [
-            ElementKind.classKind,
-            ElementKind.enumKind,
-            ElementKind.extensionKind,
-            ElementKind.mixinKind,
-            ElementKind.typedefKind
-          ];
-        }
-        return const [
-          // If the old class has been removed then this might have been a
-          // constructor invocation.
-          ElementKind.constructorKind,
-          ElementKind.functionKind, // tear-off
-          ElementKind.getterKind,
-          ElementKind.setterKind,
-          ElementKind.variableKind
-        ];
-      }
-      return const [
-        ElementKind.constantKind,
-        ElementKind.fieldKind,
-        ElementKind.functionKind, // tear-off
-        ElementKind.getterKind,
-        ElementKind.methodKind, // tear-off
-        ElementKind.setterKind
-      ];
-    } else if (node is PropertyAccess) {
-      return const [
-        ElementKind.constantKind,
-        ElementKind.fieldKind,
-        ElementKind.functionKind, // tear-off, prefixed
-        ElementKind.getterKind,
-        ElementKind.methodKind, // tear-off, prefixed
-        ElementKind.setterKind
-      ];
-    } else if (node is SimpleIdentifier) {
-      return _kindsForNode(node.parent, child: node);
-    }
-    return null;
-  }
-
   /// Return the name of the class associated with the given [target].
   static String? _nameOfTarget(Expression? target) {
     if (target is SimpleIdentifier) {
@@ -395,3 +532,14 @@
     return null;
   }
 }
+
+extension on Identifier {
+  String get simpleName {
+    var identifier = this;
+    if (identifier is PrefixedIdentifier) {
+      // The prefix isn't part of the name of the class.
+      return identifier.identifier.name;
+    }
+    return name;
+  }
+}
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 0186ba9..bae5fc7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -15,6 +15,7 @@
 import 'package:analysis_server/src/services/correction/dart/add_field_formal_parameters.dart';
 import 'package:analysis_server/src/services/correction/dart/add_key_to_constructors.dart';
 import 'package:analysis_server/src/services/correction/dart/add_late.dart';
+import 'package:analysis_server/src/services/correction/dart/add_leading_newline_to_string.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_enum_case_clauses.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_enum_like_case_clauses.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_parameter.dart';
@@ -80,6 +81,7 @@
 import 'package:analysis_server/src/services/correction/dart/create_setter.dart';
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/dart/extend_class_for_mixin.dart';
+import 'package:analysis_server/src/services/correction/dart/extract_local_variable.dart';
 import 'package:analysis_server/src/services/correction/dart/flutter_remove_widget.dart';
 import 'package:analysis_server/src/services/correction/dart/ignore_diagnostic.dart';
 import 'package:analysis_server/src/services/correction/dart/import_library.dart';
@@ -435,6 +437,9 @@
     LintNames.hash_and_equals: [
       CreateMethod.equalsOrHashCode,
     ],
+    LintNames.leading_newlines_in_multiline_strings: [
+      AddLeadingNewlineToString.newInstance,
+    ],
     LintNames.no_duplicate_case_values: [
       RemoveDuplicateCase.newInstance,
     ],
@@ -504,18 +509,12 @@
     LintNames.prefer_if_elements_to_conditional_expressions: [
       ConvertConditionalExpressionToIfElement.newInstance,
     ],
-    LintNames.prefer_initializing_formals: [
-      ConvertToInitializingFormal.newInstance,
-    ],
-    LintNames.prefer_is_empty: [
-      ReplaceWithIsEmpty.newInstance,
-    ],
-    LintNames.prefer_is_not_empty: [
-      UseIsNotEmpty.newInstance,
-    ],
     LintNames.prefer_if_null_operators: [
       ConvertToIfNull.newInstance,
     ],
+    LintNames.prefer_initializing_formals: [
+      ConvertToInitializingFormal.newInstance,
+    ],
     LintNames.prefer_inlined_adds: [
       ConvertAddAllToSpread.newInstance,
       InlineInvocation.newInstance,
@@ -526,6 +525,12 @@
     LintNames.prefer_interpolation_to_compose_strings: [
       ReplaceWithInterpolation.newInstance,
     ],
+    LintNames.prefer_is_empty: [
+      ReplaceWithIsEmpty.newInstance,
+    ],
+    LintNames.prefer_is_not_empty: [
+      UseIsNotEmpty.newInstance,
+    ],
     LintNames.prefer_is_not_operator: [
       ConvertIntoIsNot.newInstance,
     ],
@@ -550,6 +555,9 @@
     LintNames.prefer_void_to_null: [
       ReplaceNullWithVoid.newInstance,
     ],
+    LintNames.require_trailing_commas: [
+      AddTrailingComma.newInstance,
+    ],
     LintNames.sized_box_for_whitespace: [
       ReplaceContainerWithSizedBox.newInstance,
     ],
@@ -559,9 +567,6 @@
     LintNames.sort_child_properties_last: [
       SortChildPropertyLast.newInstance,
     ],
-    LintNames.require_trailing_commas: [
-      AddTrailingComma.newInstance,
-    ],
     LintNames.type_annotate_public_apis: [
       AddTypeAnnotation.newInstanceBulkFixable,
     ],
@@ -657,6 +662,14 @@
       DataDriven.newInstance,
       ImportLibrary.forType,
     ],
+    CompileTimeErrorCode
+        .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT: [
+      AddSuperConstructorInvocation.newInstance,
+    ],
+    CompileTimeErrorCode
+        .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS: [
+      AddSuperConstructorInvocation.newInstance,
+    ],
     CompileTimeErrorCode.INVALID_ANNOTATION: [
       ImportLibrary.forTopLevelVariable,
       ImportLibrary.forType,
@@ -817,12 +830,12 @@
     CompileTimeErrorCode.CONST_WITH_NON_CONST: [
       RemoveConst.newInstance,
     ],
-    CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR: [
-      ReplaceWithFilled.newInstance,
-    ],
     CompileTimeErrorCode.CONST_WITH_NON_TYPE: [
       ChangeTo.classOrMixin,
     ],
+    CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR: [
+      ReplaceWithFilled.newInstance,
+    ],
     CompileTimeErrorCode.EXTENDS_NON_CLASS: [
       ChangeTo.classOrMixin,
       CreateClass.newInstance,
@@ -889,6 +902,9 @@
       AddRequiredKeyword.newInstance,
       MakeVariableNullable.newInstance,
     ],
+    CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION: [
+      AddRequiredKeyword.newInstance,
+    ],
     CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT: [
       AddMissingRequiredArgument.newInstance,
     ],
@@ -979,6 +995,7 @@
     ],
     CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE: [
       AddNullCheck.newInstance,
+      ExtractLocalVariable.newInstance,
       ReplaceWithNullAware.single,
     ],
     CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE: [
@@ -986,6 +1003,7 @@
     ],
     CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE: [
       AddNullCheck.newInstance,
+      ExtractLocalVariable.newInstance,
       ReplaceWithNullAware.single,
     ],
     CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION: [
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 52aee05..90e9fbe 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -40,9 +40,9 @@
       'avoid_types_on_closure_parameters';
   static const String avoid_unused_constructor_parameters =
       'avoid_unused_constructor_parameters';
-  static const String await_only_futures = 'await_only_futures';
   static const String avoid_unnecessary_containers =
       'avoid_unnecessary_containers';
+  static const String await_only_futures = 'await_only_futures';
   static const String curly_braces_in_flow_control_structures =
       'curly_braces_in_flow_control_structures';
   static const String diagnostic_describe_all_properties =
@@ -54,6 +54,8 @@
   static const String eol_at_end_of_file = 'eol_at_end_of_file';
   static const String exhaustive_cases = 'exhaustive_cases';
   static const String hash_and_equals = 'hash_and_equals';
+  static const String leading_newlines_in_multiline_strings =
+      'leading_newlines_in_multiline_strings';
   static const String no_duplicate_case_values = 'no_duplicate_case_values';
   static const String non_constant_identifier_names =
       'non_constant_identifier_names';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
index 6fe772e..3bb1fae 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
@@ -82,9 +82,18 @@
       processor.addDeclarationEdit(element);
       var references = await searchEngine.searchReferences(element);
 
-      // Exclude "implicit" references to optional positional parameters.
-      if (element is ParameterElement && element.isOptionalPositional) {
-        references.removeWhere((match) => match.sourceRange.length == 0);
+      // Remove references that don't have to have the same name.
+      if (element is ParameterElement) {
+        // Implicit references to optional positional parameters.
+        if (element.isOptionalPositional) {
+          references.removeWhere((match) => match.sourceRange.length == 0);
+        }
+        // References to positional parameters from super-formal.
+        if (element.isPositional) {
+          references.removeWhere(
+            (match) => match.element is SuperFormalParameterElement,
+          );
+        }
       }
 
       processor.addReferenceEdits(references);
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 432a8b3..c86b091 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -50,6 +50,7 @@
   List<String> get experiments => [
         EnableString.constructor_tearoffs,
         EnableString.named_arguments_anywhere,
+        EnableString.super_parameters,
       ];
 
   String get latestLanguageVersion =>
diff --git a/pkg/analysis_server/test/analysis/get_errors_test.dart b/pkg/analysis_server/test/analysis/get_errors_test.dart
index fe232a6..baca9b0 100644
--- a/pkg/analysis_server/test/analysis/get_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/get_errors_test.dart
@@ -23,12 +23,12 @@
   static const String requestId = 'test-getError';
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     server.handlers = [
       AnalysisDomainHandler(server),
     ];
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysisComplete() async {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index eef7d09..6d19ce9 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -29,7 +29,7 @@
       content: '// generated',
     );
 
-    createProject();
+    await createProject();
 
     addTestFile('''
 class A {}
@@ -62,9 +62,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_class_declaration() async {
@@ -933,6 +933,54 @@
     expect(hover.elementKind, 'parameter');
   }
 
+  Future<void>
+      test_parameter_ofConstructor_optionalPositional_super_defaultValue_explicit() async {
+    addTestFile('''
+class A {
+  A([int a = 1]);
+}
+class B extends A {
+  B([super.a = 2]);
+}
+''');
+    var hover = await prepareHover('a = 2]');
+    // element
+    expect(hover.elementDescription, '[int a = 2]');
+    expect(hover.elementKind, 'parameter');
+  }
+
+  Future<void>
+      test_parameter_ofConstructor_optionalPositional_super_defaultValue_inherited() async {
+    addTestFile('''
+class A {
+  A([int a = 1]);
+}
+class B extends A {
+  B([super.a]);
+}
+''');
+    var hover = await prepareHover('a]');
+    // element
+    expect(hover.elementDescription, '[int a = 1]');
+    expect(hover.elementKind, 'parameter');
+  }
+
+  Future<void>
+      test_parameter_ofConstructor_optionalPositional_super_defaultValue_inherited2() async {
+    addTestFile('''
+class A {
+  A([num a = 1.2]);
+}
+class B extends A{
+  B([int super.a]);
+}
+''');
+    var hover = await prepareHover('a]');
+    // element
+    expect(hover.elementDescription, '[int a]');
+    expect(hover.elementKind, 'parameter');
+  }
+
   Future<void> test_parameter_reference_fieldFormal() async {
     addTestFile('''
 class A {
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index de8f51e..1f81f60 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -23,12 +23,12 @@
   static const String requestId = 'test-getNavigation';
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     server.handlers = [
       AnalysisDomainHandler(server),
     ];
-    createProject();
+    await createProject();
   }
 
   Future<void> test_beforeAnalysisComplete() async {
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index 37c6996..d213962 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -41,9 +41,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_constructor() async {
diff --git a/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart b/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
index 32081a6..6116340 100644
--- a/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
@@ -51,10 +51,8 @@
     }
   }
 
-  void setAnalysisRoot() {
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+  Future<void> setAnalysisRoot() async {
+    await setRoots(included: [projectPath], excluded: []);
   }
 
   @override
@@ -84,7 +82,7 @@
 }
 ''');
 
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -111,7 +109,7 @@
 }
 ''');
 
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -150,7 +148,7 @@
 ''');
 
     addTestFile(testSource);
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -176,7 +174,7 @@
 ''');
 
     addTestFile(testSource);
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -188,7 +186,7 @@
 
   Future<void> test_options_file_added() async {
     addTestFile(testSource);
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -215,7 +213,7 @@
     addOptionsFile('''
 ; #bang
 ''');
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
@@ -233,7 +231,7 @@
 ''');
 
     addTestFile(testSource);
-    setAnalysisRoot();
+    await setAnalysisRoot();
 
     await waitForTasksFinished();
 
diff --git a/pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart b/pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart
index c7bcb7e..93cb4ac 100644
--- a/pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart
@@ -46,9 +46,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysis() async {
diff --git a/pkg/analysis_server/test/analysis/notification_closing_labels_test.dart b/pkg/analysis_server/test/analysis/notification_closing_labels_test.dart
index 972025f..b61849e 100644
--- a/pkg/analysis_server/test/analysis/notification_closing_labels_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_closing_labels_test.dart
@@ -55,9 +55,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   void subscribeForLabels() {
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index c311ec8..e2aa4c7 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -59,9 +59,7 @@
     - invalid_lint_rule_name
 ''').path;
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -81,9 +79,7 @@
 include: package:pedantic/analysis_options.yaml
 ''').path;
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
 
@@ -122,9 +118,7 @@
     chrome-os-manifest-checks: true
 ''');
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -153,9 +147,7 @@
     chrome-os-manifest-checks: true
 ''');
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -185,7 +177,7 @@
 A? a;
     ''');
 
-    createProject();
+    await createProject();
     await waitForTasksFinished();
     await pumpEventQueue(times: 5000);
     expect(filesErrors[testFile], isEmpty);
@@ -206,9 +198,7 @@
 transforms:
 ''').path;
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -226,7 +216,7 @@
     // Files inside dotFolders should not generate error notifications even
     // if they are added to priority (priority affects only priority, not what
     // is analyzed).
-    createProject();
+    await createProject();
     addTestFile('');
     var brokenFile =
         newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
@@ -251,7 +241,7 @@
     // them to be opened (such as hovers) should not result in error notifications
     // because there is no event that would flush them and they'd remain in the
     // editor forever.
-    createProject();
+    await createProject();
     addTestFile('');
     var brokenFile =
         newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
@@ -276,7 +266,7 @@
   exclude:
     - excluded/**
 ''');
-    createProject();
+    await createProject();
     var excludedFile =
         newFile(join(projectPath, 'excluded/broken.dart'), content: 'err').path;
 
@@ -300,7 +290,7 @@
   }
 
   Future<void> test_importError() async {
-    createProject();
+    await createProject();
 
     addTestFile('''
 import 'does_not_exist.dart';
@@ -328,10 +318,7 @@
 
     addTestFile('class a { }');
 
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
-
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
 
     var testDriver = server.getAnalysisDriver(testFile)!;
@@ -353,7 +340,7 @@
   }
 
   Future<void> test_notInAnalysisRoot() async {
-    createProject();
+    await createProject();
     var otherFile = newFile('/other.dart', content: 'UnknownType V;').path;
     addTestFile('''
 import '/other.dart';
@@ -368,7 +355,7 @@
   Future<void> test_overlay_dotFolder() async {
     // Files inside dotFolders should not generate error notifications even
     // if they have overlays added.
-    createProject();
+    await createProject();
     addTestFile('');
     var brokenFile =
         newFile(join(projectPath, '.dart_tool/broken.dart'), content: 'err')
@@ -396,7 +383,7 @@
     // Overlays added for files that don't exist on disk should still generate
     // error notifications. Removing the overlay if the file is not on disk
     // should clear the errors.
-    createProject();
+    await createProject();
     addTestFile('');
     var brokenFile = convertPath(join(projectPath, 'broken.dart'));
 
@@ -432,7 +419,7 @@
     // error notifications. If the file is subsequently saved to disk before the
     // overlay is removed, the errors should not be flushed when the overlay is
     // removed.
-    createProject();
+    await createProject();
     addTestFile('');
     var brokenFile = convertPath(join(projectPath, 'broken.dart'));
 
@@ -468,7 +455,7 @@
   }
 
   Future<void> test_ParserError() async {
-    createProject();
+    await createProject();
     addTestFile('library lib');
     await waitForTasksFinished();
     await pumpEventQueue(times: 5000);
@@ -489,9 +476,7 @@
 version: 1.3.2
 ''').path;
 
-    var setRootsRequest =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(setRootsRequest);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -533,9 +518,7 @@
   a: any
 ''').path;
 
-    var setRootsRequest =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(setRootsRequest);
+    await setRoots(included: [projectPath], excluded: []);
     await waitForTasksFinished();
     await pumpEventQueue();
     //
@@ -565,7 +548,7 @@
   }
 
   Future<void> test_StaticWarning() async {
-    createProject();
+    await createProject();
     addTestFile('''
 enum E {e1, e2}
 
diff --git a/pkg/analysis_server/test/analysis/notification_folding_test.dart b/pkg/analysis_server/test/analysis/notification_folding_test.dart
index 39612a6..bc1ed96 100644
--- a/pkg/analysis_server/test/analysis/notification_folding_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_folding_test.dart
@@ -51,9 +51,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   void subscribeForFolding() {
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index a39c58d..ed4a472 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -681,6 +681,20 @@
     assertHasRegion(HighlightRegionType.ENUM_CONSTANT, 'BBB);');
   }
 
+  Future<void> test_EXTENSION() async {
+    addTestFile('''
+extension E on int {
+  void foo() {}
+}
+void f() {
+  E(0).foo();
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.EXTENSION, 'E on int');
+    assertHasRegion(HighlightRegionType.EXTENSION, 'E(0)');
+  }
+
   Future<void> test_FUNCTION_TYPE_ALIAS() async {
     addTestFile('''
 typedef A();
@@ -1136,6 +1150,50 @@
     assertHasRegion(HighlightRegionType.PARAMETER_REFERENCE, 'bbb: 2');
   }
 
+  Future<void> test_PARAMETER_super_children() async {
+    addTestFile('''
+class A {
+  A(Object aaa);
+}
+class B extends A {
+  B(int super.aaa<T>(double a /*0*/));
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.CLASS, 'int');
+    assertHasRegion(HighlightRegionType.CLASS, 'double');
+    assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T>');
+    assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'a /*0*/');
+  }
+
+  Future<void> test_PARAMETER_super_requiredNamed() async {
+    addTestFile('''
+class A {
+  A({required int aaa});
+}
+class B extends A {
+  B({required super.aaa /*0*/});
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'super.aaa');
+    assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'aaa /*0*/');
+  }
+
+  Future<void> test_PARAMETER_super_requiredPositional() async {
+    addTestFile('''
+class A {
+  A(int aaa);
+}
+class B extends A {
+  B(super.aaa /*0*/);
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'super.aaa');
+    assertHasRegion(HighlightRegionType.PARAMETER_DECLARATION, 'aaa /*0*/');
+  }
+
   Future<void> test_SETTER_DECLARATION() async {
     addTestFile('''
 set aaa(x) {}
@@ -1414,9 +1472,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   void _addLibraryForTestPart() {
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index 7e90f36..c0deb4e 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -102,9 +102,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   void subscribeForImplemented() {
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 035909b..3598517 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -182,9 +182,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysis() async {
@@ -1170,6 +1170,62 @@
     assertHasTarget('A {');
   }
 
+  Future<void> test_superFormalParameter_requiredNamed() async {
+    addTestFile('''
+class A {
+  A({required int a}); // 0
+}
+class B extends A {
+  B({required super.a}); // 1
+}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('a}); // 1', 'a}); // 0');
+  }
+
+  Future<void> test_superFormalParameter_requiredPositional() async {
+    addTestFile('''
+class A {
+  A(int a); // 0
+}
+class B extends A {
+  B(super.a); // 1
+}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('super.a', 'a); // 0');
+    assertHasRegionTarget('a); // 1', 'a); // 0');
+  }
+
+  Future<void>
+      test_superFormalParameter_requiredPositional_functionTyped() async {
+    addTestFile('''
+class A {
+  A(Object a); // 0
+}
+class B extends A {
+  B(int super.a<T>(T b)); // 1
+}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('a<T>', 'a); // 0');
+    assertHasRegion('int ');
+    assertHasRegionTarget('T>', 'T>');
+    assertHasRegionTarget('T b', 'T>');
+    assertHasRegionTarget('b))', 'b))');
+  }
+
+  Future<void> test_superFormalParameter_requiredPositional_unresolved() async {
+    addTestFile('''
+class A {}
+class B extends A {
+  B(super.a); // 1
+}
+''');
+    await prepareNavigation();
+    assertNoRegionAt('a); // 1');
+  }
+
   Future<void> test_targetElement() async {
     addTestFile('''
 class AAA {}
diff --git a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
index 576456a..777e230 100644
--- a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
@@ -88,9 +88,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysis() async {
diff --git a/pkg/analysis_server/test/analysis/notification_outline_test.dart b/pkg/analysis_server/test/analysis/notification_outline_test.dart
index 5488d67..8db0451 100644
--- a/pkg/analysis_server/test/analysis/notification_outline_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_outline_test.dart
@@ -54,9 +54,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysis() async {
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index a3846b4..bc48633 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -121,9 +121,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
   }
 
   Future<void> test_afterAnalysis() async {
diff --git a/pkg/analysis_server/test/analysis/reanalyze_test.dart b/pkg/analysis_server/test/analysis/reanalyze_test.dart
index 358df55..4fc723b 100644
--- a/pkg/analysis_server/test/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/analysis/reanalyze_test.dart
@@ -37,7 +37,7 @@
 
 var b = B();
 ''');
-    createProject();
+    await createProject();
 
     // b.dart does not exist, and `B` is unresolved.
     await waitForTasksFinished();
@@ -50,7 +50,7 @@
     newFile(b, content: 'class B {}');
 
     // Reanalyze.
-    server.reanalyze();
+    await server.reanalyze();
     await waitForTasksFinished();
 
     // No errors.
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index 658c3ff..c39b2c1 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -21,12 +21,12 @@
 @reflectiveTest
 class SetPriorityFilesTest extends AbstractAnalysisTest {
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     server.handlers = [
       AnalysisDomainHandler(server),
     ];
-    createProject();
+    await createProject();
   }
 
   Future<void> test_fileDoesNotExist() async {
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index 3d6a4ec..f85f7d4 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -41,10 +41,10 @@
     }
   }
 
-  void test_illegal_ChangeContentOverlay() {
+  void test_illegal_ChangeContentOverlay() async {
     // It should be illegal to send a ChangeContentOverlay for a file that
     // doesn't have an overlay yet.
-    createProject();
+    await createProject();
     addTestFile('library foo;');
     var id = 'myId';
     try {
@@ -95,10 +95,7 @@
 library baz;
 f(int i) {}
 ''').path;
-    var request =
-        AnalysisSetAnalysisRootsParams([project1path, project2path], [])
-            .toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [project1path, project2path], excluded: []);
     {
       await server.onAnalysisComplete;
       // Files foo.dart and bar.dart should both have errors, since they both
@@ -126,8 +123,7 @@
   Future<void> test_overlay_addPreviouslyImported() async {
     // The list of errors doesn't include errors for '/project/target.dart'.
     var project = newFolder('/project');
-    handleSuccessfulRequest(
-        AnalysisSetAnalysisRootsParams([project.path], []).toRequest('0'));
+    await setRoots(included: [project.path], excluded: []);
 
     server.updateContent('1',
         {'/project/main.dart': AddContentOverlay('import "target.dart";')});
@@ -153,10 +149,7 @@
     var folderPath1 = newFolder('/User/project1').path;
     var folderPath2 = newFolder('/User/project2').path;
 
-    handleSuccessfulRequest(AnalysisSetAnalysisRootsParams(
-      [folderPath1, folderPath2],
-      [],
-    ).toRequest('0'));
+    await setRoots(included: [folderPath1, folderPath2], excluded: []);
 
     // exactly 2 contexts
     expect(server.driverMap, hasLength(2));
@@ -184,7 +177,7 @@
   Future<void> test_sendNoticesAfterNopChange() async {
     // The errors are empty on the last line.
     addTestFile('');
-    createProject();
+    await createProject();
     await server.onAnalysisComplete;
     // add an overlay
     server.updateContent(
@@ -204,7 +197,7 @@
   Future<void> test_sendNoticesAfterNopChange_flushedUnit() async {
     // The list of errors is empty on the last line.
     addTestFile('');
-    createProject();
+    await createProject();
     await server.onAnalysisComplete;
     // add an overlay
     server.updateContent(
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 558a318..3045889 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -114,9 +114,9 @@
   }
 
   /// Creates a project [projectPath].
-  void createProject({Map<String, String>? packageRoots}) {
+  Future<void> createProject({Map<String, String>? packageRoots}) async {
     newFolder(projectPath);
-    setRoots(included: [projectPath], excluded: []);
+    await setRoots(included: [projectPath], excluded: []);
   }
 
   void doAllDeclarationsTrackerWork() {
@@ -175,20 +175,25 @@
     handleSuccessfulRequest(request);
   }
 
-  void setRoots({
+  Future<Response> setRoots({
     required List<String> included,
     required List<String> excluded,
-  }) {
-    var includedConverted = included.map(convertPath).toList();
-    var excludedConverted = excluded.map(convertPath).toList();
+    bool validateSuccessResponse = true,
+  }) async {
     var request = AnalysisSetAnalysisRootsParams(
-        includedConverted, excludedConverted,
-        packageRoots: {}).toRequest('0');
-    handleSuccessfulRequest(request, handler: analysisHandler);
+      included.map(convertPath).toList(),
+      excluded.map(convertPath).toList(),
+      packageRoots: {},
+    ).toRequest('0');
+    var response = await waitResponse(request);
+    if (validateSuccessResponse) {
+      expect(response, isResponseSuccess(request.id));
+    }
+    return response;
   }
 
   @mustCallSuper
-  void setUp() {
+  void setUp() async {
     serverChannel = MockServerChannel();
     projectPath = convertPath('/project');
     testFolder = convertPath('/project/bin');
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 907c39a..3546ca2 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -10,9 +10,12 @@
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
 import 'package:analysis_server/src/utilities/mocks.dart';
 import 'package:analysis_server/src/utilities/progress.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
+import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
@@ -26,6 +29,13 @@
 
 @reflectiveTest
 class AnalysisServerTest with ResourceProviderMixin {
+  @override
+  MemoryResourceProvider resourceProvider = MemoryResourceProvider(
+    // Force the in-memory file watchers to be slowly initialized to emulate
+    // the physical watchers (for test_concurrentContextRebuilds).
+    delayWatcherInitialization: Duration(milliseconds: 1),
+  );
+
   late MockServerChannel channel;
   late AnalysisServer server;
 
@@ -38,7 +48,7 @@
     newFolder('/bar');
     newFile('/foo/foo.dart', content: 'import "../bar/bar.dart";');
     var bar = newFile('/bar/bar.dart', content: 'library bar;');
-    server.setAnalysisRoots('0', ['/foo', '/bar'], []);
+    await server.setAnalysisRoots('0', ['/foo', '/bar'], []);
     var subscriptions = <AnalysisService, Set<String>>{};
     for (var service in AnalysisService.VALUES) {
       subscriptions[service] = <String>{bar.path};
@@ -94,6 +104,73 @@
         InstrumentationService.NULL_SERVICE);
   }
 
+  /// Test that modifying package_config again while a context rebuild is in
+  /// progress does not get lost due to a gap between creating a file watcher
+  /// and it raising events.
+  /// https://github.com/Dart-Code/Dart-Code/issues/3438
+  Future test_concurrentContextRebuilds() async {
+    // Subscribe to STATUS so we'll know when analysis is done.
+    server.serverServices = {ServerService.STATUS};
+    final projectRoot = convertPath('/foo');
+    final projectTestFile = convertPath('/foo/test.dart');
+    final projectPackageConfigFile =
+        convertPath('/foo/.dart_tool/package_config.json');
+
+    // Create a file that references two packages, which will we write to
+    // package_config.json individually.
+    newFolder(projectRoot);
+    newFile(
+      projectTestFile,
+      content: r'''
+      import "package:foo/foo.dart";'
+      import "package:bar/bar.dart";'
+      ''',
+    );
+
+    // Ensure the packages and package_config exist.
+    var fooLibFolder = _addSimplePackage('foo', '');
+    var barLibFolder = _addSimplePackage('bar', '');
+    final config = PackageConfigFileBuilder();
+    writePackageConfig(projectPackageConfigFile, config);
+
+    // Track diagnostics that arrive.
+    final errorsByFile = <String, List<AnalysisError>>{};
+    channel.notificationController.stream
+        .where((notification) => notification.event == 'analysis.errors')
+        .listen((notificaton) {
+      final params = AnalysisErrorsParams.fromNotification(notificaton);
+      errorsByFile[params.file] = params.errors;
+    });
+
+    /// Helper that waits for analysis then returns the relevant errors.
+    Future<List<AnalysisError>> getUriNotExistErrors() async {
+      await server.onAnalysisComplete;
+      expect(server.statusAnalyzing, isFalse);
+      return errorsByFile[projectTestFile]!
+          .where((error) => error.code == 'uri_does_not_exist')
+          .toList();
+    }
+
+    // Set roots and expect 2 uri_does_not_exist errors.
+    await server.setAnalysisRoots('0', [projectRoot], []);
+    expect(await getUriNotExistErrors(), hasLength(2));
+
+    // Write both packages, in two events so that the first one will trigger
+    // a rebuild.
+    config.add(name: 'foo', rootPath: fooLibFolder.parent2.path);
+    writePackageConfig(projectPackageConfigFile, config);
+    await pumpEventQueue(times: 1); // Allow server to begin processing.
+    config.add(name: 'bar', rootPath: barLibFolder.parent2.path);
+    writePackageConfig(projectPackageConfigFile, config);
+
+    // Allow the server to catch up with everything.
+    await pumpEventQueue(times: 5000);
+    await server.onAnalysisComplete;
+
+    // Expect both errors are gone.
+    expect(await getUriNotExistErrors(), hasLength(0));
+  }
+
   Future test_echo() {
     server.handlers = [EchoHandler(server)];
     var request = Request('my22', 'echo');
@@ -109,7 +186,7 @@
     newFile('/test/lib/a.dart', content: r'''
 class A {}
 ''');
-    server.setAnalysisRoots('0', [convertPath('/test')], []);
+    await server.setAnalysisRoots('0', [convertPath('/test')], []);
 
     // Pump the event queue, so that the server has finished any analysis.
     await pumpEventQueue(times: 5000);
@@ -139,7 +216,7 @@
     server.serverServices.add(ServerService.STATUS);
 
     newFolder('/test');
-    server.setAnalysisRoots('0', [convertPath('/test')], []);
+    await server.setAnalysisRoots('0', [convertPath('/test')], []);
 
     // Pump the event queue, so that the server has finished any analysis.
     await pumpEventQueue(times: 5000);
@@ -174,13 +251,13 @@
   exclude:
     - 'samples/**'
 ''');
-    server.setAnalysisRoots('0', [convertPath('/project')], []);
+    await server.setAnalysisRoots('0', [convertPath('/project')], []);
     server.setAnalysisSubscriptions(<AnalysisService, Set<String>>{
       AnalysisService.NAVIGATION: <String>{path}
     });
 
     // We respect subscriptions, even for excluded files.
-    await pumpEventQueue();
+    await pumpEventQueue(times: 5000);
     expect(channel.notificationsReceived.any((notification) {
       return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
     }), isTrue);
@@ -195,13 +272,13 @@
   exclude:
     - 'samples/**'
 ''');
-    server.setAnalysisRoots('0', [convertPath('/project')], []);
+    await server.setAnalysisRoots('0', [convertPath('/project')], []);
     server.setAnalysisSubscriptions(<AnalysisService, Set<String>>{
       AnalysisService.NAVIGATION: <String>{path}
     });
 
     // We respect subscriptions, even for excluded files.
-    await pumpEventQueue();
+    await pumpEventQueue(times: 5000);
     expect(channel.notificationsReceived.any((notification) {
       return notification.event == ANALYSIS_NOTIFICATION_NAVIGATION;
     }), isTrue);
@@ -255,6 +332,20 @@
       expect(response.error, isNotNull);
     });
   }
+
+  void writePackageConfig(String path, PackageConfigFileBuilder config) {
+    newFile(path, content: config.toContent(toUriStr: toUriStr));
+  }
+
+  /// Creates a simple package named [name] with [content] in the file at
+  /// `package:$name/$name.dart`.
+  ///
+  /// Returns a [Folder] that represents the packages `lib` folder.
+  Folder _addSimplePackage(String name, String content) {
+    final packagePath = '/packages/$name';
+    final file = newFile('$packagePath/lib/$name.dart', content: content);
+    return file.parent2;
+  }
 }
 
 class EchoHandler implements RequestHandler {
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index c705575..52c2abf 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -10,13 +10,16 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../services/completion/dart/completion_check.dart';
 import '../services/completion/dart/completion_contributor_util.dart';
 import 'impl/completion_driver.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(BasicCompletionTest);
-    defineReflectiveTests(CompletionWithSuggestionsTest);
+    defineReflectiveTests(BasicCompletionTest1);
+    defineReflectiveTests(BasicCompletionTest2);
+    defineReflectiveTests(CompletionWithSuggestionsTest1);
+    defineReflectiveTests(CompletionWithSuggestionsTest2);
   });
 }
 
@@ -29,6 +32,8 @@
 
   String get projectPath => '/$projectName';
 
+  TestingCompletionProtocol get protocol;
+
   AnalysisServerOptions get serverOptions => AnalysisServerOptions();
 
   bool get supportsAvailableSuggestions;
@@ -108,10 +113,32 @@
       await driver.waitForSetWithUri('dart:async');
     }
 
-    suggestions = await driver.getSuggestions();
+    switch (protocol) {
+      case TestingCompletionProtocol.version1:
+        suggestions = await driver.getSuggestions();
+        break;
+      case TestingCompletionProtocol.version2:
+        suggestions = await driver.getSuggestions2();
+        break;
+    }
     return suggestions;
   }
 
+  /// TODO(scheglov) Use it everywhere instead of [addTestFile].
+  Future<CompletionResponseForTesting> getTestCodeSuggestions(
+    String content,
+  ) async {
+    await addTestFile(content);
+
+    return CompletionResponseForTesting(
+      requestOffset: driver.completionOffset,
+      replacementOffset: driver.replacementOffset,
+      replacementLength: driver.replacementLength,
+      isIncomplete: false, // TODO(scheglov) not correct
+      suggestions: suggestions,
+    );
+  }
+
   /// Display sorted suggestions.
   void printSuggestions() {
     suggestions.sort(completionComparator);
@@ -122,7 +149,7 @@
   }
 
   @mustCallSuper
-  void setUp() {
+  Future<void> setUp() async {
     driver = CompletionDriver(
       supportsAvailableSuggestions: supportsAvailableSuggestions,
       projectPath: projectPath,
@@ -130,9 +157,11 @@
       resourceProvider: resourceProvider,
       serverOptions: serverOptions,
     );
-    driver.createProject(packageRoots: packageRoots);
+    await driver.createProject(packageRoots: packageRoots);
 
-    newPubspecYamlFile(projectPath, '');
+    newPubspecYamlFile(projectPath, '''
+name: project
+''');
     newDotPackagesFile(projectPath, content: '''
 project:${toUri('$projectPath/lib')}
 ''');
@@ -197,7 +226,20 @@
 }
 
 @reflectiveTest
-class BasicCompletionTest extends AbstractCompletionDriverTest {
+class BasicCompletionTest1 extends AbstractCompletionDriverTest
+    with BasicCompletionTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class BasicCompletionTest2 extends AbstractCompletionDriverTest
+    with BasicCompletionTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin BasicCompletionTestCases on AbstractCompletionDriverTest {
   @override
   bool get supportsAvailableSuggestions => false;
 
@@ -231,7 +273,40 @@
 }
 
 @reflectiveTest
-class CompletionWithSuggestionsTest extends AbstractCompletionDriverTest {
+class CompletionWithSuggestionsTest1 extends AbstractCompletionDriverTest
+    with CompletionWithSuggestionsTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+
+  @failingTest
+  @override
+  Future<void> test_project_lib_multipleExports() async {
+    return super.test_project_lib_multipleExports();
+  }
+}
+
+@reflectiveTest
+class CompletionWithSuggestionsTest2 extends AbstractCompletionDriverTest
+    with CompletionWithSuggestionsTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+
+  @FailingTest(reason: 'Not implemented yet')
+  @override
+  Future<void> test_project_lib_fields_static() {
+    // TODO: implement test_project_lib_fields_static
+    return super.test_project_lib_fields_static();
+  }
+
+  @FailingTest(reason: 'Not implemented yet')
+  @override
+  Future<void> test_project_lib_getters_static() {
+    // TODO: implement test_project_lib_getters_static
+    return super.test_project_lib_getters_static();
+  }
+}
+
+mixin CompletionWithSuggestionsTestCases on AbstractCompletionDriverTest {
   @override
   bool get supportsAvailableSuggestions => true;
 
@@ -279,9 +354,9 @@
 }
 ''');
     assertSuggestion(
-        completion: 'E.e',
-        element: ElementKind.ENUM_CONSTANT,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'E.e',
+      element: ElementKind.ENUM_CONSTANT,
+    );
   }
 
   /// See: https://github.com/dart-lang/sdk/issues/40620
@@ -327,9 +402,9 @@
 ''');
 
     assertSuggestion(
-        completion: 'A',
-        element: ElementKind.CLASS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'A',
+      element: ElementKind.CLASS,
+    );
   }
 
   Future<void> test_project_lib() async {
@@ -356,33 +431,33 @@
         element: ElementKind.CONSTRUCTOR,
         kind: CompletionSuggestionKind.INVOCATION);
     assertSuggestion(
-        completion: 'A',
-        element: ElementKind.CLASS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'A',
+      element: ElementKind.CLASS,
+    );
     assertSuggestion(
-        completion: 'E',
-        element: ElementKind.ENUM,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'E',
+      element: ElementKind.ENUM,
+    );
     assertSuggestion(
-        completion: 'Ex',
-        element: ElementKind.EXTENSION,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'Ex',
+      element: ElementKind.EXTENSION,
+    );
     assertSuggestion(
-        completion: 'M',
-        element: ElementKind.MIXIN,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'M',
+      element: ElementKind.MIXIN,
+    );
     assertSuggestion(
-        completion: 'T',
-        element: ElementKind.FUNCTION_TYPE_ALIAS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'T',
+      element: ElementKind.TYPE_ALIAS,
+    );
     assertSuggestion(
-        completion: 'T2',
-        element: ElementKind.TYPE_ALIAS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'T2',
+      element: ElementKind.TYPE_ALIAS,
+    );
     assertSuggestion(
-        completion: 'v',
-        element: ElementKind.TOP_LEVEL_VARIABLE,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'v',
+      element: ElementKind.TOP_LEVEL_VARIABLE,
+    );
   }
 
   Future<void> test_project_lib_fields_class() async {
@@ -415,9 +490,9 @@
 ''');
 
     assertSuggestion(
-        completion: 'A.f',
-        element: ElementKind.FIELD,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'A.f',
+      element: ElementKind.FIELD,
+    );
   }
 
   Future<void> test_project_lib_getters_class() async {
@@ -450,9 +525,9 @@
 ''');
 
     assertSuggestion(
-        completion: 'A.g',
-        element: ElementKind.GETTER,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'A.g',
+      element: ElementKind.GETTER,
+    );
   }
 
   /// See: https://github.com/dart-lang/sdk/issues/40626
@@ -468,12 +543,43 @@
 ''');
 
     assertSuggestion(
-        completion: 'g',
-        element: ElementKind.GETTER,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'g',
+      element: ElementKind.GETTER,
+    );
   }
 
-  @failingTest
+  Future<void> test_project_lib_methods_class() async {
+    await addProjectFile('lib/a.dart', r'''
+class A {
+  void foo() => 0;
+}
+''');
+
+    await addTestFile('''
+void f() {
+  ^
+}
+''');
+
+    assertNoSuggestion(completion: 'A.foo');
+  }
+
+  Future<void> test_project_lib_methods_static() async {
+    await addProjectFile('lib/a.dart', r'''
+class A {
+  static void foo() => 0;
+}
+''');
+
+    await addTestFile('''
+void f() {
+  ^
+}
+''');
+
+    assertNoSuggestion(completion: 'A.foo');
+  }
+
   Future<void> test_project_lib_multipleExports() async {
     await addProjectFile('lib/a.dart', r'''
 class A {}
@@ -541,9 +647,9 @@
 ''');
 
     assertSuggestion(
-        completion: 's',
-        element: ElementKind.SETTER,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 's',
+      element: ElementKind.SETTER,
+    );
   }
 
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38739')
@@ -596,16 +702,17 @@
 ''');
 
     expect(
+      suggestionWith(
+        completion: 'A',
+        element: ElementKind.CONSTRUCTOR,
+      ).relevance,
+      greaterThan(
         suggestionWith(
-                completion: 'A',
-                element: ElementKind.CONSTRUCTOR,
-                kind: CompletionSuggestionKind.INVOCATION)
-            .relevance,
-        greaterThan(suggestionWith(
-                completion: 'A',
-                element: ElementKind.CLASS,
-                kind: CompletionSuggestionKind.INVOCATION)
-            .relevance));
+          completion: 'A',
+          element: ElementKind.CLASS,
+        ).relevance,
+      ),
+    );
   }
 
   /// See: https://github.com/dart-lang/sdk/issues/35529
@@ -620,13 +727,13 @@
 ''');
 
     assertSuggestion(
-        completion: 'M',
-        element: ElementKind.MIXIN,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'M',
+      element: ElementKind.MIXIN,
+    );
     assertSuggestion(
-        completion: 'A',
-        element: ElementKind.CLASS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'A',
+      element: ElementKind.CLASS,
+    );
   }
 
   Future<void> test_sdk_lib_future_isNotDuplicated() async {
@@ -682,18 +789,20 @@
 
     // + Classes.
     assertSuggestion(
-        completion: 'HashMap',
-        file: '/sdk/lib/collection/collection.dart',
-        element: ElementKind.CLASS,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'HashMap',
+      file: '/sdk/lib/collection/collection.dart',
+      element: ElementKind.CLASS,
+    );
 
     // + Top level variables.
     assertSuggestion(
-        completion: 'pi',
-        file: '/sdk/lib/math/math.dart',
-        element: ElementKind.TOP_LEVEL_VARIABLE,
-        kind: CompletionSuggestionKind.INVOCATION);
+      completion: 'pi',
+      file: '/sdk/lib/math/math.dart',
+      element: ElementKind.TOP_LEVEL_VARIABLE,
+    );
 
     // (No typedefs, enums, extensions defined in the Mock SDK.)
   }
 }
+
+enum TestingCompletionProtocol { version1, version2 }
diff --git a/pkg/analysis_server/test/client/impl/abstract_client.dart b/pkg/analysis_server/test/client/impl/abstract_client.dart
index 999451f..d1ad27f 100644
--- a/pkg/analysis_server/test/client/impl/abstract_client.dart
+++ b/pkg/analysis_server/test/client/impl/abstract_client.dart
@@ -120,12 +120,11 @@
 
   /// Create a project at [projectPath].
   @mustCallSuper
-  void createProject({Map<String, String>? packageRoots}) {
+  Future<void> createProject({Map<String, String>? packageRoots}) async {
     newFolder(projectPath);
-    var request = AnalysisSetAnalysisRootsParams([projectPath], [],
-            packageRoots: packageRoots)
-        .toRequest('0');
-    handleSuccessfulRequest(request, handler: analysisHandler);
+
+    await setRoots(
+        included: [projectPath], excluded: [], packageRoots: packageRoots);
   }
 
   void expect(actual, matcher, {String reason});
@@ -144,6 +143,19 @@
 
   void processNotification(Notification notification);
 
+  Future<Response> setRoots({
+    required List<String> included,
+    required List<String> excluded,
+    Map<String, String>? packageRoots,
+  }) async {
+    var request = AnalysisSetAnalysisRootsParams(included, excluded,
+            packageRoots: packageRoots)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(response, isResponseSuccess(request.id));
+    return response;
+  }
+
   /// Returns a [Future] that completes when the server's analysis is complete.
   Future waitForTasksFinished() => server.onAnalysisComplete;
 
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index bbdeee9..4907915 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -108,8 +108,8 @@
   }
 
   @override
-  void createProject({Map<String, String>? packageRoots}) {
-    super.createProject(packageRoots: packageRoots);
+  Future<void> createProject({Map<String, String>? packageRoots}) async {
+    await super.createProject(packageRoots: packageRoots);
     if (supportsAvailableSuggestions) {
       var request = CompletionSetSubscriptionsParams(
           [CompletionService.AVAILABLE_SUGGESTION_SETS]).toRequest('0');
@@ -130,6 +130,22 @@
     return suggestions;
   }
 
+  Future<List<CompletionSuggestion>> getSuggestions2() async {
+    await waitForTasksFinished();
+
+    var request = CompletionGetSuggestions2Params(
+      testFilePath,
+      completionOffset,
+      1 << 16,
+      timeout: 60 * 1000,
+    ).toRequest('0');
+    var response = await waitResponse(request);
+    var result = CompletionGetSuggestions2Result.fromResponse(response);
+    replacementOffset = result.replacementOffset;
+    replacementLength = result.replacementLength;
+    return result.suggestions;
+  }
+
   @override
   File newFile(String path, String content) =>
       resourceProvider.newFile(resourceProvider.convertPath(path), content);
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 04c6b0f..35f61fd 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -79,8 +79,8 @@
         .toList();
   }
 
-  Future runTest(LocationSpec spec, [Map<String, String>? extraFiles]) {
-    super.setUp();
+  Future runTest(LocationSpec spec, [Map<String, String>? extraFiles]) async {
+    await super.setUp();
     return Future(() {
       var content = spec.source;
       newFile(testFile, content: content);
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index fa3b3e4..fe0da92 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -60,7 +60,7 @@
 void f(int? a) {}
 ''');
 
-    setRoots(included: [myPackageRootPath], excluded: []);
+    await setRoots(included: [myPackageRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // Cannot use `int?` without enabling null safety.
@@ -83,7 +83,7 @@
 class AnalysisDomainHandlerTest extends AbstractAnalysisTest {
   Future<void> outOfRangeTest(SourceEdit edit) async {
     var helper = AnalysisTestHelper();
-    helper.createSingleFileProject('library A;');
+    await helper.createSingleFileProject('library A;');
     await helper.onAnalysisComplete;
     helper.sendContentChange(AddContentOverlay('library B;'));
     await helper.onAnalysisComplete;
@@ -99,14 +99,14 @@
     newFile('/project/aaa/a.dart', content: '// a');
     newFile('/project/bbb/b.dart', content: '// b');
     var excludedPath = join(projectPath, 'bbb');
-    var response = testSetAnalysisRoots([projectPath], [excludedPath]);
+    var response = await testSetAnalysisRoots([projectPath], [excludedPath]);
     expect(response, isResponseSuccess('0'));
   }
 
   Future<void> test_setAnalysisRoots_included_newFolder() async {
     newPubspecYamlFile('/project', 'name: project');
     var file = newFile('/project/bin/test.dart', content: 'main() {}').path;
-    var response = testSetAnalysisRoots([projectPath], []);
+    var response = await testSetAnalysisRoots([projectPath], []);
     var serverRef = server;
     expect(response, isResponseSuccess('0'));
     // verify that unit is resolved eventually
@@ -119,7 +119,7 @@
     var projectA = convertPath('/project_a');
     var projectB = convertPath('/project_b');
     var fileB = newFile('/project_b/b.dart', content: '// b').path;
-    var response = testSetAnalysisRoots([projectA, projectB], []);
+    var response = await testSetAnalysisRoots([projectA, projectB], []);
     var serverRef = server;
     expect(response, isResponseSuccess('0'));
     // Non-existence of /project_a should not prevent files in /project_b
@@ -130,25 +130,25 @@
   }
 
   Future<void> test_setAnalysisRoots_included_notAbsolute() async {
-    var response = testSetAnalysisRoots(['foo/bar'], []);
+    var response = await testSetAnalysisRoots(['foo/bar'], []);
     expect(response,
         isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT));
   }
 
   Future<void> test_setAnalysisRoots_included_notNormalized() async {
-    var response = testSetAnalysisRoots(['/foo/../bar'], []);
+    var response = await testSetAnalysisRoots(['/foo/../bar'], []);
     expect(response,
         isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT));
   }
 
   Future<void> test_setAnalysisRoots_notAbsolute() async {
-    var response = testSetAnalysisRoots([], ['foo/bar']);
+    var response = await testSetAnalysisRoots([], ['foo/bar']);
     expect(response,
         isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT));
   }
 
   Future<void> test_setAnalysisRoots_notNormalized() async {
-    var response = testSetAnalysisRoots([], ['/foo/../bar']);
+    var response = await testSetAnalysisRoots([], ['/foo/../bar']);
     expect(response,
         isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT));
   }
@@ -161,7 +161,7 @@
     expect(response, isResponseSuccess('0'));
   }
 
-  void test_setPriorityFiles_valid() {
+  Future<void> test_setPriorityFiles_valid() async {
     var p1 = convertPath('/p1');
     var p2 = convertPath('/p2');
     var aPath = convertPath('/p1/a.dart');
@@ -171,11 +171,7 @@
     newFile(bPath, content: 'library b;');
     newFile(cPath, content: 'library c;');
 
-    var setRootsRequest =
-        AnalysisSetAnalysisRootsParams([p1, p2], []).toRequest('0');
-    var setRootsResponse =
-        handler.handleRequest(setRootsRequest, NotCancelableToken());
-    expect(setRootsResponse, isResponseSuccess('0'));
+    await setRoots(included: [p1, p2], excluded: []);
 
     void setPriorityFiles(List<String> fileList) {
       var request = AnalysisSetPriorityFilesParams(fileList).toRequest('0');
@@ -193,7 +189,7 @@
 
   Future<void> test_updateContent_badType() async {
     var helper = AnalysisTestHelper();
-    helper.createSingleFileProject('// empty');
+    await helper.createSingleFileProject('// empty');
     await helper.onAnalysisComplete;
     var request = Request('0', ANALYSIS_REQUEST_UPDATE_CONTENT, {
       ANALYSIS_REQUEST_UPDATE_CONTENT_FILES: {
@@ -208,7 +204,7 @@
 
   Future<void> test_updateContent_changeOnDisk_duringOverride() async {
     var helper = AnalysisTestHelper();
-    helper.createSingleFileProject('library A;');
+    await helper.createSingleFileProject('library A;');
     await helper.onAnalysisComplete;
     // update code
     helper.sendContentChange(AddContentOverlay('library B;'));
@@ -230,7 +226,7 @@
 
   Future<void> test_updateContent_changeOnDisk_normal() async {
     var helper = AnalysisTestHelper();
-    helper.createSingleFileProject('library A;');
+    await helper.createSingleFileProject('library A;');
     await helper.onAnalysisComplete;
     // There should be no errors
     expect(helper.getTestErrors(), hasLength(0));
@@ -244,7 +240,7 @@
 
   Future<void> test_updateContent_fullContent() async {
     var helper = AnalysisTestHelper();
-    helper.createSingleFileProject('// empty');
+    await helper.createSingleFileProject('// empty');
     await helper.onAnalysisComplete;
     // no errors initially
     var errors = helper.getTestErrors();
@@ -260,7 +256,7 @@
   Future<void> test_updateContent_incremental() async {
     var helper = AnalysisTestHelper();
     var initialContent = 'library A;';
-    helper.createSingleFileProject(initialContent);
+    await helper.createSingleFileProject(initialContent);
     await helper.onAnalysisComplete;
     // no errors initially
     var errors = helper.getTestErrors();
@@ -305,17 +301,17 @@
     expect(response, isResponseSuccess('0'));
   }
 
-  Response testSetAnalysisRoots(List<String> included, List<String> excluded) {
-    var request =
-        AnalysisSetAnalysisRootsParams(included, excluded).toRequest('0');
-    return handler.handleRequest(request, NotCancelableToken())!;
+  Future<Response> testSetAnalysisRoots(
+      List<String> included, List<String> excluded) {
+    return setRoots(
+        included: included, excluded: excluded, validateSuccessResponse: false);
   }
 
   Future<void> xtest_getReachableSources_invalidSource() async {
     // TODO(brianwilkerson) Re-enable this test if we re-enable the
     // analysis.getReachableSources request.
     newFile('/project/a.dart', content: 'import "b.dart";');
-    server.setAnalysisRoots('0', ['/project/'], []);
+    await server.setAnalysisRoots('0', ['/project/'], []);
 
     await server.onAnalysisComplete;
 
@@ -332,7 +328,7 @@
     var fileA = newFile('/project/a.dart', content: 'import "b.dart";').path;
     newFile('/project/b.dart');
 
-    server.setAnalysisRoots('0', ['/project/'], []);
+    await server.setAnalysisRoots('0', ['/project/'], []);
 
     await server.onAnalysisComplete;
 
@@ -365,7 +361,7 @@
 
     _createFilesWithErrors([a_path, b_path]);
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // Both a.dart and b.dart are analyzed.
@@ -398,7 +394,7 @@
 
     newFile(a_path, content: 'error');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // a.dart was analyzed
@@ -433,7 +429,7 @@
     chrome-os-manifest-checks: true
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     newFile(path, content: '<manifest/>');
     await pumpEventQueue();
@@ -449,7 +445,7 @@
     // We have to create the folder, otherwise there is nothing to watch.
     newFolder(testPackageLibPath);
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We don't have a.dart yet.
@@ -472,7 +468,7 @@
 void f(A a) {}
 ''');
 
-    createProject();
+    await createProject();
     await pumpEventQueue();
     await server.onAnalysisComplete;
 
@@ -507,7 +503,7 @@
 void f(A a) {}
 ''');
 
-    createProject();
+    await createProject();
     await pumpEventQueue();
     await server.onAnalysisComplete;
 
@@ -540,7 +536,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We cannot resolve `package:aaa/a.dart`
@@ -572,7 +568,7 @@
       PackageConfigFileBuilder(),
     );
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // No `fix_data.yaml` to analyze yet.
     assertNoErrorsNotification(path);
@@ -602,7 +598,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We cannot resolve `package:aaa/a.dart`
@@ -634,7 +630,7 @@
     // We look for `pubspec.yaml` files only in analysis context roots.
     newAnalysisOptionsYamlFile(testPackageRootPath, content: '');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // a.dart was analyzed
@@ -664,7 +660,7 @@
 
     newFile(a_path, content: 'error');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // a.dart was analyzed
@@ -698,7 +694,7 @@
     - lib/b.dart
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // Only a.dart is analyzed, because b.dart is excluded.
@@ -740,7 +736,7 @@
     chrome-os-manifest-checks: true
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // Forget and check that we did.
     forgetReceivedErrors();
@@ -768,7 +764,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     assertNoErrors(a_path);
@@ -798,7 +794,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await pumpEventQueue();
     await server.onAnalysisComplete;
 
@@ -840,7 +836,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await pumpEventQueue();
     await server.onAnalysisComplete;
 
@@ -876,7 +872,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We cannot resolve `package:aaa/a.dart`
@@ -911,7 +907,7 @@
     // This file has an error.
     newFile(path, content: '0: 1');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // The file was analyzed.
     assertHasErrors(path);
@@ -950,7 +946,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We cannot resolve `package:aaa/a.dart`
@@ -986,7 +982,7 @@
     - lib/b.dart
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // Only a.dart is analyzed, because b.dart is excluded.
@@ -1023,7 +1019,7 @@
     chrome-os-manifest-checks: true
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // An error was reported.
     _assertAnalyzedFiles(hasErrors: [path], notAnalyzed: []);
@@ -1041,7 +1037,7 @@
 
     _createFilesWithErrors([a_path]);
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // a.dart was analyzed
@@ -1075,7 +1071,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await pumpEventQueue();
     await server.onAnalysisComplete;
 
@@ -1110,7 +1106,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We have `A` in 'package:aaa/a.dart', so no errors.
@@ -1143,7 +1139,7 @@
     // This file has an error.
     newFile(path, content: '0: 1');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // The file was analyzed.
     _assertAnalyzedFiles(hasErrors: [path], notAnalyzed: []);
@@ -1175,7 +1171,7 @@
 void f(A a) {}
 ''');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We have `A` in 'package:aaa/a.dart', so no errors.
@@ -1214,7 +1210,7 @@
 ''');
 
     // create project and wait for analysis
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We have `A` in 'package:aaa/a.dart', so no errors.
@@ -1230,7 +1226,7 @@
 
     _createFilesWithErrors([a_path, b_path]);
 
-    setRoots(included: [a_path], excluded: []);
+    await setRoots(included: [a_path], excluded: []);
 
     // Only a.dart is included, so b.dart is not analyzed.
     await server.onAnalysisComplete;
@@ -1247,7 +1243,7 @@
     _createFilesWithErrors([a_path, b_path]);
 
     // Include only single file.
-    setRoots(included: [a_path], excluded: []);
+    await setRoots(included: [a_path], excluded: []);
     await server.onAnalysisComplete;
 
     // So, only a.dart is analyzed, and b.dart is not.
@@ -1257,7 +1253,7 @@
     );
 
     // Include the folder that contains both a.dart and b.dart
-    setRoots(included: [testPackageRootPath], excluded: []);
+    await setRoots(included: [testPackageRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // So, both a.dart and b.dart are analyzed.
@@ -1281,7 +1277,7 @@
       notIncludedFile,
     ]);
 
-    setRoots(included: [includedFile, includedFolder], excluded: []);
+    await setRoots(included: [includedFile, includedFolder], excluded: []);
     await server.onAnalysisComplete;
 
     // We can combine a file, and a folder as included paths.
@@ -1307,7 +1303,7 @@
 
     _createFilesWithErrors([a_path, b_path]);
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // b.dart is excluded using the options file.
     await server.onAnalysisComplete;
@@ -1324,7 +1320,7 @@
 
     _createFilesWithErrors([a_path, excluded_path]);
 
-    setRoots(
+    await setRoots(
       included: [workspaceRootPath],
       excluded: [excluded_path],
     );
@@ -1342,7 +1338,7 @@
 
     _createFilesWithErrors([a_path, excluded_path]);
 
-    setRoots(
+    await setRoots(
       included: [workspaceRootPath],
       excluded: ['$testPackageRootPath/excluded'],
     );
@@ -1368,7 +1364,7 @@
 
     newFile(path, content: '<manifest/>');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     // No touch-screen.
     assertHasErrors(path);
@@ -1386,7 +1382,7 @@
     // So, `lib/fix_data.yaml` will be analyzed.
     newFile(path, content: '0: 1');
 
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
 
     assertHasErrors(path);
   }
@@ -1410,7 +1406,7 @@
 ''');
 
     // create project and wait for analysis
-    setRoots(included: [workspaceRootPath], excluded: []);
+    await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
 
     // We have `A` in 'package:aaa/a.dart', so no errors.
@@ -1512,13 +1508,11 @@
 
   /// Creates a project with a single Dart file `/project/bin/test.dart` with
   /// the given [code].
-  void createSingleFileProject(code) {
+  Future<void> createSingleFileProject(code) async {
     testCode = _getCodeString(code);
     newFolder(projectPath);
     newFile(testFile, content: testCode);
-    var request =
-        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(included: [projectPath], excluded: []);
   }
 
   /// Returns the offset of [search] in [testCode].
@@ -1590,11 +1584,25 @@
     handleSuccessfulRequest(request);
   }
 
+  Future<void> setRoots(
+      {required List<String> included, required List<String> excluded}) async {
+    var request =
+        AnalysisSetAnalysisRootsParams(included, excluded).toRequest('0');
+    var response = await waitResponse(request);
+    expect(response, isResponseSuccess(request.id));
+  }
+
   /// Stops the associated server.
   void stopServer() {
     server.done();
   }
 
+  /// Completes with a successful [Response] for the given [request].
+  /// Otherwise fails.
+  Future<Response> waitResponse(Request request) async {
+    return serverChannel.sendRequest(request);
+  }
+
   static String _getCodeString(code) {
     if (code is List<String>) {
       code = code.join('\n');
@@ -1620,7 +1628,7 @@
 
   Future<void> test_afterAnalysis() async {
     addTestFile('int V = 42;');
-    createProject();
+    await createProject();
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[testFile], isNull);
@@ -1634,7 +1642,7 @@
   Future<void> test_afterAnalysis_noSuchFile() async {
     var file = convertPath('/no-such-file.dart');
     addTestFile('// no matter');
-    createProject();
+    await createProject();
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[testFile], isNull);
@@ -1658,7 +1666,7 @@
   new A();
 }
 ''');
-    createProject();
+    await createProject();
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[pkgFile], isNull);
@@ -1684,8 +1692,7 @@
 ''');
     // add 'pkgA' and 'pkgB' as projects
     newFolder(projectPath);
-    handleSuccessfulRequest(
-        AnalysisSetAnalysisRootsParams([pkgA, pkgB], []).toRequest('0'));
+    await setRoots(included: [pkgA, pkgB], excluded: []);
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[pkgFileA], isNull);
@@ -1704,7 +1711,7 @@
     newDotPackagesFile('/project', content: 'pkgA:/packages/pkgA/lib');
     //
     addTestFile('// no "pkgA" reference');
-    createProject();
+    await createProject();
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[pkgFile], isNull);
@@ -1720,7 +1727,7 @@
   Future<void> test_afterAnalysis_sdkFile() async {
     var file = convertPath('/sdk/lib/core/core.dart');
     addTestFile('// no matter');
-    createProject();
+    await createProject();
     // wait for analysis, no results initially
     await waitForTasksFinished();
     expect(filesHighlights[file], isNull);
@@ -1733,7 +1740,7 @@
 
   Future<void> test_beforeAnalysis() async {
     addTestFile('int V = 42;');
-    createProject();
+    await createProject();
     // subscribe
     addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
     // wait for analysis
@@ -1743,7 +1750,7 @@
 
   Future<void> test_sentToPlugins() async {
     addTestFile('int V = 42;');
-    createProject();
+    await createProject();
     // subscribe
     addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
     // wait for analysis
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index e3a94a0..82c6e44 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -27,6 +27,7 @@
 
 import 'domain_completion_util.dart';
 import 'mocks.dart';
+import 'services/completion/dart/completion_check.dart';
 import 'src/plugin/plugin_manager_test.dart';
 import 'utils/change_check.dart';
 
@@ -239,30 +240,30 @@
     await _configureWithWorkspaceRoot();
 
     // Send three requests, the first two should be aborted.
-    var response0 = _sendTestCompletionRequest('0', 0);
-    var response1 = _sendTestCompletionRequest('1', 0);
-    var response2 = _sendTestCompletionRequest('2', 0);
+    var request0 = _sendTestCompletionRequest('0', 0);
+    var request1 = _sendTestCompletionRequest('1', 0);
+    var request2 = _sendTestCompletionRequest('2', 0);
 
     // Wait for all three.
-    var validator0 = await response0.toResult();
-    var validator1 = await response1.toResult();
-    var validator2 = await response2.toResult();
+    var response0 = await request0.toResponse();
+    var response1 = await request1.toResponse();
+    var response2 = await request2.toResponse();
 
     // The first two should be aborted.
     expect(abortedIdSet, {'0', '1'});
 
-    validator0
+    check(response0)
       ..assertIncomplete()
-      ..suggestions.assertEmpty();
+      ..suggestions.isEmpty;
 
-    validator1
+    check(response1)
       ..assertIncomplete()
-      ..suggestions.assertEmpty();
+      ..suggestions.isEmpty;
 
-    validator2
+    check(response2)
       ..assertComplete()
-      ..suggestions.assertCompletionsContainsAll(
-        ['int', 'double', 'Future', 'Directory'],
+      ..suggestions.containsMatch(
+        (suggestion) => suggestion.completion.isEqualTo('int'),
       );
   }
 
@@ -277,7 +278,7 @@
     await _configureWithWorkspaceRoot();
 
     // Schedule a completion request.
-    var response = _sendTestCompletionRequest('0', 0);
+    var request = _sendTestCompletionRequest('0', 0);
 
     // Simulate typing in the IDE.
     await _handleSuccessfulRequest(
@@ -287,39 +288,74 @@
     );
 
     // The request should be aborted.
-    var validator = await response.toResult();
+    var response = await request.toResponse();
     expect(abortedIdSet, {'0'});
 
-    validator
+    check(response)
       ..assertIncomplete()
-      ..suggestions.assertEmpty();
+      ..suggestions.isEmpty;
+  }
+
+  Future<void> test_isNotImportedFeature_prefixed_classInstanceMethod() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A {
+  void foo01() {}
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+import 'a.dart';
+
+class B extends A {
+  void foo02() {}
+}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f(B b) {
+  b.foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // The fact that `b.dart` is imported, and `a.dart` is not, does not affect
+    // the order of suggestions added with an expression prefix. We are not
+    // going to import anything, so this does not matter.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+    ]);
   }
 
   Future<void> test_notImported_dart() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   Rand^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4)
-      ..assertLibrariesToImport(includes: [
-        'dart:math',
-      ], excludes: [
-        'dart:async',
-        'dart:core',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 4);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['Random']);
-    classes.withCompletion('Random').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('dart:math');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('Random')
+        ..libraryUriToImport.isEqualTo('dart:math'),
+    ]);
   }
 
   Future<void> test_notImported_emptyBudget() async {
@@ -328,21 +364,304 @@
     // Empty budget, so no not yet imported libraries.
     completionDomain.budgetDuration = const Duration(milliseconds: 0);
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   Rand^
 }
 ''');
 
-    responseValidator
-      ..assertComplete()
-      ..assertReplacementBack(4)
-      ..assertLibrariesToImport(includes: [], excludes: [
-        'dart:core',
-        'dart:math',
-      ]);
+    check(response)
+      ..assertIncomplete()
+      ..hasReplacement(left: 4)
+      ..suggestions.withElementClass.isEmpty;
+  }
 
-    responseValidator.suggestions.withElementClass().assertEmpty();
+  Future<void> test_notImported_lowerRelevance_enumConstant() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+enum E1 {
+  foo01
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+enum E2 {
+  foo02
+}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+  foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('E2.foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('E1.foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_extension_getter() async {
+    await _configureWithWorkspaceRoot();
+
+    newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+  int get foo01 => 0;
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+  int get foo02 => 0;
+}
+''');
+
+    var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+ 
+void f() {
+  0.foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_extension_method() async {
+    await _configureWithWorkspaceRoot();
+
+    newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+  void foo01() {}
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+  void foo02() {}
+}
+''');
+
+    var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+ 
+void f() {
+  0.foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_extension_setter() async {
+    await _configureWithWorkspaceRoot();
+
+    newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+  set foo01(int _) {}
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+  set foo02(int _) {}
+}
+''');
+
+    var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+ 
+void f() {
+  0.foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_topLevel_class() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+class A02 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+  A0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 2);
+
+    // `A01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_topLevel_getter() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+int get foo01 => 0;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+int get foo02 => 0;
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+  foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_topLevel_setter() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+set foo01(int _) {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+set foo02(int _) {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+  foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
+  }
+
+  Future<void> test_notImported_lowerRelevance_topLevel_variable() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+var foo01 = 0;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+var foo02 = 0;
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+  foo0^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // `foo01` relevance is decreased because it is not yet imported.
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_dependencies_inLib() async {
@@ -378,28 +697,21 @@
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   A0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:aaa/f.dart',
-      ], excludes: [
-        'dart:core',
-        'package:bbb/f.dart',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:aaa/f.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:aaa/f.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_dependencies_inTest() async {
@@ -436,7 +748,7 @@
     await _configureWithWorkspaceRoot();
 
     var test_path = convertPath('$testPackageTestPath/test.dart');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: test_path,
       content: '''
 void f() {
@@ -445,25 +757,18 @@
 ''',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:aaa/f.dart',
-        'package:bbb/f.dart',
-      ], excludes: [
-        'dart:core',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A03']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:aaa/f.dart');
-    classes.withCompletion('A03').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:bbb/f.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:aaa/f.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A03')
+        ..libraryUriToImport.isEqualTo('package:bbb/f.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this() async {
@@ -477,33 +782,24 @@
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   A0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/a.dart',
-        'package:test/b.dart',
-      ], excludes: [
-        'dart:async',
-        'dart:core',
-        'dart:math',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/a.dart');
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/b.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isEqualTo('package:test/b.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_hasImport() async {
@@ -518,7 +814,7 @@
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 import 'a.dart';
 
 void f() {
@@ -526,30 +822,21 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/b.dart',
-      ], excludes: [
-        'dart:async',
-        'dart:core',
-        'dart:math',
-        'package:test/a.dart',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02', 'A03']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport(isNull);
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport(isNull);
-    classes.withCompletion('A03').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/b.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A03')
+        ..libraryUriToImport.isEqualTo('package:test/b.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_hasImport_hasShow() async {
@@ -564,38 +851,33 @@
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
-import 'a.dart' show A01;
+    var response = await _getTestCodeSuggestions('''
+import 'a.dart' show A02;
 
 void f() {
   A0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/a.dart',
-        'package:test/b.dart',
-      ], excludes: [
-        'dart:async',
-        'dart:core',
-        'dart:math',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02', 'A03']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport(isNull);
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/a.dart');
-    classes.withCompletion('A03').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/b.dart');
+    // Note:
+    // 1. A02 is the first, because it is already imported.
+    // 2. A01 is still suggested, but with lower relevance.
+    // 3. A03 has the same relevance (not tested), but sorted by name.
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isNull,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A03')
+        ..libraryUriToImport.isEqualTo('package:test/b.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_inLib_excludesTest() async {
@@ -607,34 +889,27 @@
 class A01 {}
 ''');
 
-    var b = newFile('$testPackageTestPath/b.dart', content: '''
+    newFile('$testPackageTestPath/b.dart', content: '''
 class A02 {}
 ''');
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   A0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/a.dart',
-      ], excludes: [
-        'dart:core',
-        'package:test/test.dart',
-        toUriStr(b.path),
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_inLib_includesThisSrc() async {
@@ -652,31 +927,24 @@
 
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 void f() {
   A0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/f.dart',
-        'package:test/src/f.dart',
-      ], excludes: [
-        'dart:core',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/f.dart');
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/src/f.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/f.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isEqualTo('package:test/src/f.dart'),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_inTest_includesTest() async {
@@ -696,7 +964,7 @@
     await _configureWithWorkspaceRoot();
 
     var test_path = convertPath('$testPackageTestPath/test.dart');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: test_path,
       content: '''
 void f() {
@@ -705,25 +973,18 @@
 ''',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/a.dart',
-        b_uriStr,
-      ], excludes: [
-        'dart:core',
-        toUriStr(test_path),
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/a.dart');
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport(b_uriStr);
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isEqualTo(b_uriStr),
+    ]);
   }
 
   Future<void> test_notImported_pub_this_inTest_includesThisSrc() async {
@@ -742,7 +1003,7 @@
     await _configureWithWorkspaceRoot();
 
     var test_path = convertPath('$testPackageTestPath/test.dart');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: test_path,
       content: '''
 void f() {
@@ -751,31 +1012,24 @@
 ''',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2)
-      ..assertLibrariesToImport(includes: [
-        'package:test/f.dart',
-        'package:test/src/f.dart',
-      ], excludes: [
-        'dart:core',
-        'package:test/test.dart',
-      ]);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02']);
-    classes.withCompletion('A01').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/f.dart');
-    classes.withCompletion('A02').assertSingle()
-      ..assertClass()
-      ..assertLibraryToImport('package:test/src/f.dart');
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..libraryUriToImport.isEqualTo('package:test/f.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..libraryUriToImport.isEqualTo('package:test/src/f.dart'),
+    ]);
   }
 
   Future<void> test_numResults_class_methods() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 class A {
   void foo01() {}
   void foo02() {}
@@ -787,18 +1041,24 @@
 }
 ''', maxResults: 2);
 
-    responseValidator
+    check(response)
       ..assertIncomplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isMethodInvocation,
+    ]);
   }
 
   Future<void> test_numResults_topLevelVariables() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 var foo01 = 0;
 var foo02 = 0;
 var foo03 = 0;
@@ -808,20 +1068,18 @@
 }
 ''', maxResults: 2);
 
-    responseValidator
+    check(response)
       ..assertIncomplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-    suggestionsValidator
-        .withCompletion('foo01')
-        .assertSingle()
-        .assertTopLevelVariable();
-    suggestionsValidator
-        .withCompletion('foo02')
-        .assertSingle()
-        .assertTopLevelVariable();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isTopLevelVariable,
+    ]);
   }
 
   Future<void> test_numResults_topLevelVariables_imported_withPrefix() async {
@@ -833,7 +1091,7 @@
 var foo03 = 0;
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 import 'a.dart' as prefix;
 
 void f() {
@@ -841,18 +1099,24 @@
 }
 ''', maxResults: 2);
 
-    responseValidator
+    check(response)
       ..assertIncomplete()
-      ..assertEmptyReplacement();
+      ..hasEmptyReplacement();
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isTopLevelVariable,
+    ]);
   }
 
   Future<void> test_prefixed_class_constructors() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 class A {
   A.foo01();
   A.foo02();
@@ -863,20 +1127,24 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestions = responseValidator.suggestions;
-    suggestions.assertCompletions(['foo01', 'foo02']);
-    suggestions.withCompletion('foo01').assertSingle().assertConstructor();
-    suggestions.withCompletion('foo02').assertSingle().assertConstructor();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isConstructorInvocation,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isConstructorInvocation,
+    ]);
   }
 
   Future<void> test_prefixed_class_getters() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 class A {
   int get foo01 => 0;
   int get foo02 => 0;
@@ -887,20 +1155,24 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestions = responseValidator.suggestions;
-    suggestions.assertCompletions(['foo01', 'foo02']);
-    suggestions.withCompletion('foo01').assertSingle().assertGetter();
-    suggestions.withCompletion('foo02').assertSingle().assertGetter();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isGetter,
+    ]);
   }
 
   Future<void> test_prefixed_class_methods_instance() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 class A {
   void foo01() {}
   void foo02() {}
@@ -911,20 +1183,24 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestions = responseValidator.suggestions;
-    suggestions.assertCompletions(['foo01', 'foo02']);
-    suggestions.withCompletion('foo01').assertSingle().assertMethod();
-    suggestions.withCompletion('foo02').assertSingle().assertMethod();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isMethodInvocation,
+    ]);
   }
 
   Future<void> test_prefixed_class_methods_static() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 class A {
   static void foo01() {}
   static void foo02() {}
@@ -935,20 +1211,24 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestions = responseValidator.suggestions;
-    suggestions.assertCompletions(['foo01', 'foo02']);
-    suggestions.withCompletion('foo01').assertSingle().assertMethod();
-    suggestions.withCompletion('foo02').assertSingle().assertMethod();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isMethodInvocation,
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionGetters() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 extension E1 on int {
   int get foo01 => 0;
   int get foo02 => 0;
@@ -964,15 +1244,18 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertGetter();
-    suggestionsValidator.withCompletion('foo02').assertSingle().assertGetter();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isGetter,
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionGetters_notImported() async {
@@ -993,25 +1276,26 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 void f() {
   0.foo0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle()
-      ..assertGetter()
-      ..assertLibraryToImport('package:test/a.dart');
-    suggestionsValidator.withCompletion('foo02').assertSingle()
-      ..assertGetter()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isGetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void>
@@ -1032,28 +1316,28 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 void f() {
   0.foo0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle()
-      ..assertGetter()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionMethods() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 extension E1 on int {
   void foo01() {}
   void foo02() {}
@@ -1069,15 +1353,18 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertMethod();
-    suggestionsValidator.withCompletion('foo02').assertSingle().assertMethod();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isMethodInvocation,
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionMethods_notImported() async {
@@ -1098,31 +1385,32 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 void f() {
   0.foo0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle()
-      ..assertMethod()
-      ..assertLibraryToImport('package:test/a.dart');
-    suggestionsValidator.withCompletion('foo02').assertSingle()
-      ..assertMethod()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isMethodInvocation
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionSetters() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 extension E1 on int {
   set foo01(int _) {}
   set foo02(int _) {}
@@ -1138,15 +1426,18 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertSetter();
-    suggestionsValidator.withCompletion('foo02').assertSingle().assertSetter();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isSetter,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isSetter,
+    ]);
   }
 
   Future<void> test_prefixed_expression_extensionSetters_notImported() async {
@@ -1167,25 +1458,26 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 void f() {
   0.foo0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle()
-      ..assertSetter()
-      ..assertLibraryToImport('package:test/a.dart');
-    suggestionsValidator.withCompletion('foo02').assertSingle()
-      ..assertSetter()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isSetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isSetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void>
@@ -1206,22 +1498,22 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 void f() {
   0.foo0^
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle()
-      ..assertSetter()
-      ..assertLibraryToImport('package:test/a.dart');
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isSetter
+        ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+    ]);
   }
 
   Future<void> test_prefixed_extensionGetters_imported() async {
@@ -1239,7 +1531,7 @@
 }
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 import 'a.dart';
 
 void f() {
@@ -1247,21 +1539,24 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertGetter();
-    suggestionsValidator.withCompletion('foo02').assertSingle().assertGetter();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isGetter,
+    ]);
   }
 
   Future<void> test_prefixed_extensionOverride_extensionGetters() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 extension E1 on int {
   int get foo01 => 0;
 }
@@ -1275,19 +1570,21 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01']);
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertGetter();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isGetter,
+    ]);
   }
 
   Future<void> test_prefixed_extensionOverride_extensionMethods() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 extension E1 on int {
   void foo01() {}
 }
@@ -1301,19 +1598,21 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01']);
-    suggestionsValidator.withCompletion('foo01').assertSingle().assertMethod();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isMethodInvocation,
+    ]);
   }
 
   Future<void> test_unprefixed_filters() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 var foo01 = 0;
 var foo02 = 0;
 var bar01 = 0;
@@ -1324,23 +1623,18 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-
-    suggestionsValidator
-        .withCompletion('foo01')
-        .assertSingle()
-        .assertTopLevelVariable();
-    suggestionsValidator
-        .withCompletion('foo02')
-        .assertSingle()
-        .assertTopLevelVariable();
-    suggestionsValidator.withCompletion('bar01').assertEmpty();
-    suggestionsValidator.withCompletion('bar02').assertEmpty();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isTopLevelVariable,
+    ]);
   }
 
   Future<void> test_unprefixed_imported_class() async {
@@ -1354,7 +1648,7 @@
 class A02 {}
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 import 'a.dart';
 import 'b.dart';
 
@@ -1363,14 +1657,18 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(2);
+      ..hasReplacement(left: 2);
 
-    var classes = responseValidator.suggestions.withElementClass();
-    classes.assertCompletions(['A01', 'A02']);
-    classes.withCompletion('A01').assertSingle().assertClass();
-    classes.withCompletion('A02').assertSingle().assertClass();
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A01')
+        ..isClass,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('A02')
+        ..isClass,
+    ]);
   }
 
   Future<void> test_unprefixed_imported_topLevelVariable() async {
@@ -1384,7 +1682,7 @@
 var foo02 = 0;
 ''');
 
-    var responseValidator = await _getTestCodeSuggestions('''
+    var response = await _getTestCodeSuggestions('''
 import 'a.dart';
 import 'b.dart';
 
@@ -1393,26 +1691,47 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
-    suggestionsValidator.assertCompletions(['foo01', 'foo02']);
-    suggestionsValidator
-        .withCompletion('foo01')
-        .assertSingle()
-        .assertTopLevelVariable();
-    suggestionsValidator
-        .withCompletion('foo02')
-        .assertSingle()
-        .assertTopLevelVariable();
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isTopLevelVariable,
+    ]);
+  }
+
+  Future<void> test_unprefixed_imported_withPrefix_class() async {
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'dart:math' as math;
+
+void f() {
+  Rand^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    // No suggestion without the `math` prefix.
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('math.Random')
+        ..libraryUriToImport.isNull,
+    ]);
   }
 
   Future<void> test_unprefixed_sorts_byScore() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 var fooAB = 0;
 var fooBB = 0;
 
@@ -1421,19 +1740,25 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
     // `fooBB` has better score than `fooAB` - prefix match
-    suggestionsValidator.assertCompletions(['fooBB', 'fooAB']);
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('fooBB')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('fooAB')
+        ..isTopLevelVariable,
+    ]);
   }
 
   Future<void> test_unprefixed_sorts_byType() async {
     await _configureWithWorkspaceRoot();
 
-    var responseValidator = await _getTestCodeSuggestions(r'''
+    var response = await _getTestCodeSuggestions(r'''
 var foo01 = 0.0;
 var foo02 = 0;
 
@@ -1442,34 +1767,44 @@
 }
 ''');
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertReplacementBack(4);
+      ..hasReplacement(left: 4);
 
-    var suggestionsValidator = responseValidator.suggestions;
     // `foo02` has better relevance, its type matches the context type
-    suggestionsValidator.assertCompletions(['foo02', 'foo01']);
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo02')
+        ..isTopLevelVariable,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('foo01')
+        ..isTopLevelVariable,
+    ]);
   }
 
   Future<void> test_yaml_analysisOptions_root() async {
     await _configureWithWorkspaceRoot();
 
     var path = convertPath('$testPackageRootPath/analysis_options.yaml');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: path,
       content: '^',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertEmptyReplacement();
+      ..hasEmptyReplacement();
 
-    responseValidator.suggestions
-        .withKindIdentifier()
-        .assertCompletionsContainsAll([
-      'analyzer: ',
-      'include: ',
-      'linter: ',
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('analyzer: ')
+        ..kind.isIdentifier,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('include: ')
+        ..kind.isIdentifier,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('linter: ')
+        ..kind.isIdentifier,
     ]);
   }
 
@@ -1477,20 +1812,22 @@
     await _configureWithWorkspaceRoot();
 
     var path = convertPath('$testPackageRootPath/fix_data.yaml');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: path,
       content: '^',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertEmptyReplacement();
+      ..hasEmptyReplacement();
 
-    responseValidator.suggestions
-        .withKindIdentifier()
-        .assertCompletionsContainsAll([
-      'version: ',
-      'transforms:',
+    check(response).suggestions.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('version: ')
+        ..kind.isIdentifier,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('transforms:')
+        ..kind.isIdentifier,
     ]);
   }
 
@@ -1498,25 +1835,29 @@
     await _configureWithWorkspaceRoot();
 
     var path = convertPath('$testPackageRootPath/pubspec.yaml');
-    var responseValidator = await _getCodeSuggestions(
+    var response = await _getCodeSuggestions(
       path: path,
       content: '^',
     );
 
-    responseValidator
+    check(response)
       ..assertComplete()
-      ..assertEmptyReplacement();
+      ..hasEmptyReplacement();
 
-    responseValidator.suggestions
-        .withKindIdentifier()
-        .assertCompletionsContainsAll([
-      'name: ',
-      'dependencies: ',
-      'dev_dependencies: ',
+    check(response).suggestions.includesAll([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('name: ')
+        ..kind.isIdentifier,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('dependencies: ')
+        ..kind.isIdentifier,
+      (suggestion) => suggestion
+        ..completion.isEqualTo('dev_dependencies: ')
+        ..kind.isIdentifier,
     ]);
   }
 
-  Future<CompletionGetSuggestions2ResponseValidator> _getCodeSuggestions({
+  Future<CompletionResponseForTesting> _getCodeSuggestions({
     required String path,
     required String content,
     int maxResults = 1 << 10,
@@ -1538,7 +1879,7 @@
     );
   }
 
-  Future<CompletionGetSuggestions2ResponseValidator> _getSuggestions({
+  Future<CompletionResponseForTesting> _getSuggestions({
     required String path,
     required int completionOffset,
     required int maxResults,
@@ -1551,13 +1892,19 @@
 
     var response = await _handleSuccessfulRequest(request);
     var result = CompletionGetSuggestions2Result.fromResponse(response);
-    return CompletionGetSuggestions2ResponseValidator(completionOffset, result);
+    return CompletionResponseForTesting(
+      requestOffset: completionOffset,
+      replacementOffset: result.replacementOffset,
+      replacementLength: result.replacementLength,
+      isIncomplete: result.isIncomplete,
+      suggestions: result.suggestions,
+    );
   }
 
-  Future<CompletionGetSuggestions2ResponseValidator> _getTestCodeSuggestions(
+  Future<CompletionResponseForTesting> _getTestCodeSuggestions(
     String content, {
     int maxResults = 1 << 10,
-  }) async {
+  }) {
     return _getCodeSuggestions(
       path: convertPath(testFilePath),
       content: content,
@@ -1779,42 +2126,42 @@
     addTestFile('class A {bool foo; A() : ^;}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_constructor2() async {
     addTestFile('class A {bool foo; A() : s^;}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_constructor3() async {
     addTestFile('class A {bool foo; A() : a=7,^;}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_constructor4() async {
     addTestFile('class A {bool foo; A() : a=7,s^;}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_constructor5() async {
     addTestFile('class A {bool foo; A() : a=7,s^}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_constructor6() async {
     addTestFile('class A {bool foo; A() : a=7,^ void bar() {}}');
     await getSuggestions();
     assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
   }
 
   Future<void> test_extension() async {
@@ -1872,9 +2219,9 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
           elementKind: ElementKind.CLASS);
       assertNoResult('test');
     });
@@ -2023,7 +2370,7 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
           elementKind: ElementKind.CLASS);
       assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
       assertNoResult('HtmlElement');
@@ -2039,11 +2386,22 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement');
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement');
       assertNoResult('test');
     });
   }
 
+  Future<void> test_inComment_block_beforeDartDoc() async {
+    addTestFile('''
+/* text ^ */
+
+/// some doc comments
+class SomeClass {}
+  ''');
+    await getSuggestions();
+    expect(suggestions, isEmpty);
+  }
+
   Future<void> test_inComment_block_beforeNode() async {
     addTestFile('''
   void f(aaa, bbb) {
@@ -2069,6 +2427,17 @@
     expect(suggestions, isEmpty);
   }
 
+  Future<void> test_inComment_endOfLine_beforeDartDoc() async {
+    addTestFile('''
+// text ^
+
+/// some doc comments
+class SomeClass {}
+  ''');
+    await getSuggestions();
+    expect(suggestions, isEmpty);
+  }
+
   Future<void> test_inComment_endOfLine_beforeNode() async {
     addTestFile('''
   void f(aaa, bbb) {
@@ -2228,7 +2597,7 @@
 class A { var isVisible;}
 void f(A p) { var v1 = p.is^; }''');
     await getSuggestions();
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'isVisible');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'isVisible');
   }
 
   Future<void> test_keyword() {
@@ -2258,7 +2627,7 @@
     expect(replacementLength, equals(0));
 
     // The class is suggested.
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'A',
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
         elementKind: ElementKind.CLASS);
 
     // Both constructors - default and named, are suggested.
@@ -2311,7 +2680,7 @@
     expect(replacementLength, equals(0));
 
     // The class is suggested.
-    assertHasResult(CompletionSuggestionKind.INVOCATION, 'A');
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A');
 
     // Class and all its constructors are shadowed by the local variable.
     assertNoResult('A', elementKind: ElementKind.CLASS);
@@ -2324,12 +2693,12 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'a');
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'a');
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'b');
       assertHasResult(CompletionSuggestionKind.INVOCATION, 'x');
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'DateTime',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'DateTime',
           elementKind: ElementKind.CLASS);
     });
   }
@@ -2369,11 +2738,11 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
           elementKind: ElementKind.CLASS);
       assertNoResult('test');
     });
@@ -2392,11 +2761,11 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
           elementKind: ElementKind.CLASS);
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
           elementKind: ElementKind.CLASS);
       assertNoResult('test');
     });
@@ -2432,7 +2801,7 @@
     return getSuggestions().then((_) {
       expect(replacementOffset, equals(completionOffset));
       expect(replacementLength, equals(0));
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object',
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
           elementKind: ElementKind.CLASS);
       assertNoResult('HtmlElement');
       assertNoResult('test');
@@ -2459,62 +2828,12 @@
       expect(replacementLength, equals(4));
       // Suggestions based upon imported elements are partially filtered
       //assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
-      assertHasResult(CompletionSuggestionKind.INVOCATION, 'test');
+      assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'test');
       assertNoResult('HtmlElement');
     });
   }
 }
 
-class CompletionGetSuggestions2ResponseValidator {
-  final int completionOffset;
-  final CompletionGetSuggestions2Result result;
-
-  CompletionGetSuggestions2ResponseValidator(
-    this.completionOffset,
-    this.result,
-  );
-
-  SuggestionsValidator get suggestions {
-    return SuggestionsValidator(
-      result.suggestions,
-      libraryUrisToImport: result.libraryUrisToImport,
-    );
-  }
-
-  void assertComplete() {
-    expect(result.isIncomplete, isFalse);
-  }
-
-  void assertEmptyReplacement() {
-    assertReplacement(completionOffset, 0);
-  }
-
-  void assertIncomplete() {
-    expect(result.isIncomplete, isTrue);
-  }
-
-  void assertLibrariesToImport({
-    required List<String> includes,
-    List<String>? excludes,
-  }) {
-    expect(result.libraryUrisToImport, containsAll(includes));
-    if (excludes != null) {
-      for (var exclude in excludes) {
-        expect(result.libraryUrisToImport, isNot(contains(exclude)));
-      }
-    }
-  }
-
-  void assertReplacement(int offset, int length) {
-    expect(result.replacementOffset, offset);
-    expect(result.replacementLength, length);
-  }
-
-  void assertReplacementBack(int length) {
-    assertReplacement(completionOffset - length, length);
-  }
-}
-
 class PubPackageAnalysisServerTest with ResourceProviderMixin {
   late final MockServerChannel serverChannel;
   late final AnalysisServer server;
@@ -2635,150 +2954,18 @@
 
   RequestWithFutureResponse(this.offset, this.request, this.futureResponse);
 
-  Future<CompletionGetSuggestions2ResponseValidator> toResult() async {
+  Future<CompletionResponseForTesting> toResponse() async {
     var response = await futureResponse;
     expect(response, isResponseSuccess(request.id));
     var result = CompletionGetSuggestions2Result.fromResponse(response);
-    return CompletionGetSuggestions2ResponseValidator(offset, result);
-  }
-}
-
-class SingleSuggestionValidator {
-  final CompletionSuggestion suggestion;
-  final List<String>? libraryUrisToImport;
-
-  SingleSuggestionValidator(
-    this.suggestion, {
-    this.libraryUrisToImport,
-  });
-
-  void assertClass() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.CLASS);
-  }
-
-  void assertConstructor() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.CONSTRUCTOR);
-  }
-
-  void assertGetter() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.GETTER);
-  }
-
-  void assertLibraryToImport(Object matcher) {
-    final libraryUrisToImport = this.libraryUrisToImport;
-    final index = suggestion.libraryUriToImportIndex;
-    var libraryUri = libraryUrisToImport != null && index != null
-        ? libraryUrisToImport[index]
-        : null;
-    expect(libraryUri, matcher);
-  }
-
-  void assertMethod() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.METHOD);
-  }
-
-  void assertSetter() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.SETTER);
-  }
-
-  void assertTopLevelVariable() {
-    expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
-    expect(suggestion.element?.kind, ElementKind.TOP_LEVEL_VARIABLE);
-  }
-}
-
-class SuggestionsValidator {
-  final List<CompletionSuggestion> suggestions;
-  final List<String>? libraryUrisToImport;
-
-  SuggestionsValidator(
-    this.suggestions, {
-    this.libraryUrisToImport,
-  });
-
-  int get length => suggestions.length;
-
-  /// Assert that this has suggestions with exactly the given completions,
-  /// with the exact order.
-  ///
-  /// Does not check suggestion kinds, elements, etc.
-  void assertCompletions(Iterable<String> completions) {
-    var actual = suggestions.map((e) => e.completion).toList();
-    expect(actual, completions);
-  }
-
-  /// Assert that this has suggestions with all [expected] completions.
-  /// There might be more suggestions, with other completions.
-  ///
-  /// Does not check the order, kinds, elements, etc.
-  void assertCompletionsContainsAll(Iterable<String> expected) {
-    var actual = suggestions.map((e) => e.completion).toSet();
-    expect(actual, containsAll(expected));
-  }
-
-  void assertEmpty() {
-    check(suggestions).isEmpty;
-  }
-
-  void assertLength(Object matcher) {
-    expect(suggestions, hasLength(matcher));
-  }
-
-  SingleSuggestionValidator assertSingle() {
-    assertLength(1);
-    return SingleSuggestionValidator(
-      suggestions.single,
-      libraryUrisToImport: libraryUrisToImport,
+    return CompletionResponseForTesting(
+      requestOffset: offset,
+      replacementOffset: result.replacementOffset,
+      replacementLength: result.replacementLength,
+      isIncomplete: result.isIncomplete,
+      suggestions: result.suggestions,
     );
   }
-
-  SuggestionsValidator withCompletion(String completion) {
-    return SuggestionsValidator(
-      suggestions.where((suggestion) {
-        return suggestion.completion == completion;
-      }).toList(),
-      libraryUrisToImport: libraryUrisToImport,
-    );
-  }
-
-  SuggestionsValidator withElementClass() {
-    return withElementKind(ElementKind.CLASS);
-  }
-
-  SuggestionsValidator withElementConstructor() {
-    return withElementKind(ElementKind.CONSTRUCTOR);
-  }
-
-  SuggestionsValidator withElementGetter() {
-    return withElementKind(ElementKind.GETTER);
-  }
-
-  SuggestionsValidator withElementKind(ElementKind kind) {
-    return SuggestionsValidator(
-      suggestions.where((suggestion) {
-        return suggestion.element?.kind == kind;
-      }).toList(),
-      libraryUrisToImport: libraryUrisToImport,
-    );
-  }
-
-  SuggestionsValidator withKind(CompletionSuggestionKind kind) {
-    return SuggestionsValidator(
-      suggestions.where((suggestion) {
-        return suggestion.kind == kind;
-      }).toList(),
-      libraryUrisToImport: libraryUrisToImport,
-    );
-  }
-
-  SuggestionsValidator withKindIdentifier() {
-    return withKind(CompletionSuggestionKind.IDENTIFIER);
-  }
 }
 
 extension on CheckTarget<CompletionGetSuggestionDetails2Result> {
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 8670a6f..9e64bec 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -125,9 +125,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = CompletionDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index 92ab990..2a354f2 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -29,7 +29,7 @@
     newPubspecYamlFile('/project', 'name: project');
     newFile('/project/bin/test.dart', content: 'main() {}');
 
-    server.setAnalysisRoots('0', [convertPath('/project')], []);
+    await server.setAnalysisRoots('0', [convertPath('/project')], []);
 
     await server.onAnalysisComplete;
 
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index 7095b0c..d3945a8 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -163,9 +163,9 @@
   late String contextId;
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = ExecutionDomainHandler(server);
     _createExecutionContext(testFile);
   }
diff --git a/pkg/analysis_server/test/edit/assists_test.dart b/pkg/analysis_server/test/edit/assists_test.dart
index e2cb0dc..d42144e 100644
--- a/pkg/analysis_server/test/edit/assists_test.dart
+++ b/pkg/analysis_server/test/edit/assists_test.dart
@@ -39,9 +39,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
index 5f58bc1..b746b44 100644
--- a/pkg/analysis_server/test/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
@@ -52,11 +52,11 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     registerLintRules();
     handler = EditDomainHandler(server);
-    createProject();
+    await createProject();
   }
 
   Future<void> test_annotateOverrides_excludedFile() async {
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index ff64169..8ffe486 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -36,7 +36,7 @@
 
     // Set up the original project, as the code fix code won't run at all
     // if there are no contexts.
-    createProject();
+    await createProject();
     await waitForTasksFinished();
 
     var request =
@@ -49,7 +49,7 @@
   }
 
   Future<void> test_fixUndefinedClass() async {
-    createProject();
+    await createProject();
     addTestFile('''
 main() {
   Completer<String> x = null;
@@ -81,7 +81,7 @@
       info: Future.value(result.toResponse('-', 1))
     };
 
-    createProject();
+    await createProject();
     addTestFile('main() {}');
     await waitForTasksFinished();
     var errorFixes = await _getFixesAt('in(');
@@ -89,7 +89,7 @@
   }
 
   Future<void> test_hasFixes() async {
-    createProject();
+    await createProject();
     addTestFile('''
 foo() {
   print(1)
@@ -134,7 +134,7 @@
   }
 
   Future<void> test_overlayOnlyFile() async {
-    createProject();
+    await createProject();
     testCode = '''
 main() {
 print(1)
@@ -167,10 +167,8 @@
     newFile('/bbb/lib/target.generated.dart', content: 'class Foo() {}');
     newFile('/bbb/lib/target.template.dart', content: 'class Foo() {}');
 
-    handleSuccessfulRequest(
-        AnalysisSetAnalysisRootsParams(
-            [convertPath('/aaa'), convertPath('/bbb')], []).toRequest('0'),
-        handler: analysisHandler);
+    await setRoots(
+        included: [convertPath('/aaa'), convertPath('/bbb')], excluded: []);
 
     // Configure the test file.
     testFile = convertPath('/aaa/main.dart');
diff --git a/pkg/analysis_server/test/edit/format_test.dart b/pkg/analysis_server/test/edit/format_test.dart
index e5576f7..d62a67e 100644
--- a/pkg/analysis_server/test/edit/format_test.dart
+++ b/pkg/analysis_server/test/edit/format_test.dart
@@ -20,9 +20,9 @@
 @reflectiveTest
 class FormatTest extends AbstractAnalysisTest {
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index c18850e..fccfa57 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -22,9 +22,9 @@
   late SourceFileEdit fileEdit;
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/edit/postfix_completion_test.dart b/pkg/analysis_server/test/edit/postfix_completion_test.dart
index 86085b1..0de0e1c 100644
--- a/pkg/analysis_server/test/edit/postfix_completion_test.dart
+++ b/pkg/analysis_server/test/edit/postfix_completion_test.dart
@@ -23,9 +23,9 @@
   late SourceChange change;
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index bffa9fc..4ae4511 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -899,9 +899,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
     server.handlers = [handler];
   }
@@ -2289,9 +2289,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
     server.handlers = [handler];
   }
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index f6e6bd6..4c173d9 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -22,9 +22,9 @@
   late SourceFileEdit fileEdit;
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/edit/statement_completion_test.dart b/pkg/analysis_server/test/edit/statement_completion_test.dart
index a692a0f..fbbff85 100644
--- a/pkg/analysis_server/test/edit/statement_completion_test.dart
+++ b/pkg/analysis_server/test/edit/statement_completion_test.dart
@@ -22,9 +22,9 @@
   late SourceChange change;
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     handler = EditDomainHandler(server);
   }
 
diff --git a/pkg/analysis_server/test/integration/analysis/highlights_test.dart b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
index 358e8c8..57c3736 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
@@ -27,6 +27,7 @@
   Future<void> computeHighlights(String pathname, String text) async {
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
     sendAnalysisSetSubscriptions({
       AnalysisService.HIGHLIGHTS: [pathname]
     });
diff --git a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
index ff29243..1a95731 100644
--- a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
+++ b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
@@ -90,10 +90,11 @@
   test.^
 }
 ''');
+    standardAnalysisSetup();
+    await analysisFinished;
     // Create an overlay but do not write the file to "disk"
     //   writeFile(pathname, text);
     // Don't wait for any results except the completion notifications
-    standardAnalysisSetup(subscribeStatus: false);
     sendAnalysisUpdateContent({path: AddContentOverlay(content)});
     sendCompletionGetSuggestions(path, completionOffset);
     var param = await onCompletionResults
@@ -109,7 +110,8 @@
     // Do not write the file to "disk"
     //   writeFile(pathname, text);
     // Don't wait for any results except the completion notifications
-    standardAnalysisSetup(subscribeStatus: false);
+    standardAnalysisSetup();
+    await analysisFinished;
     // Missing file and no overlay
     //sendAnalysisUpdateContent({path: new AddContentOverlay(content)});
     var result = await sendCompletionGetSuggestions(path, 0);
diff --git a/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart b/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
index 84b84ae..0081707 100644
--- a/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
+++ b/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
@@ -17,6 +17,7 @@
 class GetDiagnosticsTest extends AbstractAnalysisServerIntegrationTest {
   Future<void> test_getDiagnostics() async {
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendDiagnosticGetDiagnostics();
 
diff --git a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
index 4c4d82d..5cdb5ea 100644
--- a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
@@ -43,6 +43,7 @@
 }
 ''');
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditBulkFixes([sourceDirectory.path]);
     expect(result.edits, hasLength(1));
diff --git a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
index 6610ea2..1c7c608 100644
--- a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
@@ -51,6 +51,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditGetFixes(pathname, text.indexOf('FutureOr f'));
     expect(result.fixes, isEmpty);
diff --git a/pkg/analysis_server/test/integration/edit/organize_directives_test.dart b/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
index 2bf4c1f..deeeb37 100644
--- a/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
@@ -26,6 +26,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditOrganizeDirectives(pathname);
     var edit = result.edit;
@@ -45,6 +46,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditOrganizeDirectives(pathname);
     var edit = result.edit;
@@ -62,6 +64,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     try {
       await sendEditOrganizeDirectives(pathname);
diff --git a/pkg/analysis_server/test/integration/edit/sort_members_test.dart b/pkg/analysis_server/test/integration/edit/sort_members_test.dart
index a49aca3..25ba753 100644
--- a/pkg/analysis_server/test/integration/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/integration/edit/sort_members_test.dart
@@ -23,6 +23,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditSortMembers(pathname);
     var edit = result.edit;
@@ -38,6 +39,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     var result = await sendEditSortMembers(pathname);
     var edit = result.edit;
@@ -52,6 +54,7 @@
 ''';
     writeFile(pathname, text);
     standardAnalysisSetup();
+    await analysisFinished;
 
     try {
       await sendEditSortMembers(pathname);
diff --git a/pkg/analysis_server/test/integration/execution/delete_context_test.dart b/pkg/analysis_server/test/integration/execution/delete_context_test.dart
index 121ba2e..609902d 100644
--- a/pkg/analysis_server/test/integration/execution/delete_context_test.dart
+++ b/pkg/analysis_server/test/integration/execution/delete_context_test.dart
@@ -19,6 +19,7 @@
     var pathname = sourcePath('lib/main.dart');
     writeFile(pathname, '// dummy');
     standardAnalysisSetup();
+    await analysisFinished;
 
     var contextId = (await sendExecutionCreateContext(sourceDirectory.path)).id;
 
diff --git a/pkg/analysis_server/test/integration/execution/map_uri_test.dart b/pkg/analysis_server/test/integration/execution/map_uri_test.dart
index e98032f..4538798 100644
--- a/pkg/analysis_server/test/integration/execution/map_uri_test.dart
+++ b/pkg/analysis_server/test/integration/execution/map_uri_test.dart
@@ -19,6 +19,7 @@
     var pathname = sourcePath('lib/main.dart');
     writeFile(pathname, '// dummy');
     standardAnalysisSetup();
+    await analysisFinished;
 
     var contextId = (await sendExecutionCreateContext(sourceDirectory.path)).id;
 
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 b8704aa..c12b23d 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1021,19 +1021,7 @@
   ///
   ///   This list contains suggestions from both imported, and not yet imported
   ///   libraries. Items from not yet imported libraries will have
-  ///   libraryUriToImportIndex set, which is an index into the
-  ///   libraryUrisToImport in this response.
-  ///
-  /// libraryUrisToImport: List<String>
-  ///
-  ///   The list of libraries with declarations that are not yet available in
-  ///   the file where completion was requested, most often because the library
-  ///   is not yet imported. The declarations still might be included into the
-  ///   suggestions, and the client should use getSuggestionDetails2 on
-  ///   selection to make the library available in the file.
-  ///
-  ///   Each item is the URI of a library, such as package:foo/bar.dart or
-  ///   file:///home/me/workspace/foo/test/bar_test.dart.
+  ///   isNotImported set to true.
   ///
   /// isIncomplete: bool
   ///
@@ -1041,8 +1029,12 @@
   ///   requested maxResults.
   Future<CompletionGetSuggestions2Result> sendCompletionGetSuggestions2(
       String file, int offset, int maxResults,
-      {int? timeout}) async {
+      {CompletionMode? completionMode,
+      int? invocationCount,
+      int? timeout}) async {
     var params = CompletionGetSuggestions2Params(file, offset, maxResults,
+            completionMode: completionMode,
+            invocationCount: invocationCount,
             timeout: timeout)
         .toJson();
     var result = await server.send('completion.getSuggestions2', params);
@@ -1144,7 +1136,7 @@
   }
 
   /// Clients must make this request when the user has selected a completion
-  /// suggestion with the libraryUriToImportIndex field set. The server will
+  /// suggestion with the isNotImported field set to true. The 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. The text to insert might be different from the original suggestion
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index a7e358db..1e7cde4 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -235,6 +235,15 @@
 /// String
 final Matcher isCompletionId = isString;
 
+/// CompletionMode
+///
+/// enum {
+///   BASIC
+///   SMART
+/// }
+final Matcher isCompletionMode =
+    MatchesEnum('CompletionMode', ['BASIC', 'SMART']);
+
 /// CompletionService
 ///
 /// enum {
@@ -296,7 +305,7 @@
           'hasNamedParameters': isBool,
           'parameterName': isString,
           'parameterType': isString,
-          'libraryUriToImportIndex': isInt
+          'isNotImported': isBool
         }));
 
 /// CompletionSuggestionKind
@@ -375,7 +384,8 @@
       'parameters': isString,
       'returnType': isString,
       'typeParameters': isString,
-      'aliasedType': isString
+      'aliasedType': isString,
+      'libraryUri': isString
     }));
 
 /// ElementDeclaration
@@ -784,6 +794,7 @@
 ///   DYNAMIC_PARAMETER_REFERENCE
 ///   ENUM
 ///   ENUM_CONSTANT
+///   EXTENSION
 ///   FIELD
 ///   FIELD_STATIC
 ///   FUNCTION
@@ -865,6 +876,7 @@
   'DYNAMIC_PARAMETER_REFERENCE',
   'ENUM',
   'ENUM_CONSTANT',
+  'EXTENSION',
   'FIELD',
   'FIELD_STATIC',
   'FUNCTION',
@@ -2138,9 +2150,15 @@
 ///   "maxResults": int
 /// }
 final Matcher isCompletionGetSuggestions2Params = LazyMatcher(() =>
-    MatchesJsonObject('completion.getSuggestions2 params',
-        {'file': isFilePath, 'offset': isInt, 'maxResults': isInt},
-        optionalFields: {'timeout': isInt}));
+    MatchesJsonObject('completion.getSuggestions2 params', {
+      'file': isFilePath,
+      'offset': isInt,
+      'maxResults': isInt
+    }, optionalFields: {
+      'completionMode': isCompletionMode,
+      'invocationCount': isInt,
+      'timeout': isInt
+    }));
 
 /// completion.getSuggestions2 result
 ///
@@ -2148,7 +2166,6 @@
 ///   "replacementOffset": int
 ///   "replacementLength": int
 ///   "suggestions": List<CompletionSuggestion>
-///   "libraryUrisToImport": List<String>
 ///   "isIncomplete": bool
 /// }
 final Matcher isCompletionGetSuggestions2Result =
@@ -2156,7 +2173,6 @@
           'replacementOffset': isInt,
           'replacementLength': isInt,
           'suggestions': isListOf(isCompletionSuggestion),
-          'libraryUrisToImport': isListOf(isString),
           'isIncomplete': isBool
         }));
 
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index cbacc55..01f2b09 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -1268,7 +1268,7 @@
     expect(res.any((c) => c.label == 'UniqueNamedClassForLspThree'), isTrue);
   }
 
-  Future<void> test_suggestionSets() async {
+  Future<void> test_unimportedSymbols() async {
     newFile(
       join(projectFolderPath, 'other_file.dart'),
       content: '''
@@ -1342,7 +1342,7 @@
   }
 
   Future<void>
-      test_suggestionSets_doesNotDuplicate_importedViaMultipleLibraries() async {
+      test_unimportedSymbols_doesNotDuplicate_importedViaMultipleLibraries() async {
     // An item that's already imported through multiple libraries that
     // export it should not result in multiple entries.
     newFile(
@@ -1387,7 +1387,7 @@
   }
 
   Future<void>
-      test_suggestionSets_doesNotDuplicate_importedViaSingleLibrary() async {
+      test_unimportedSymbols_doesNotDuplicate_importedViaSingleLibrary() async {
     // An item that's already imported through a library that exports it
     // should not result in multiple entries.
     newFile(
@@ -1430,7 +1430,7 @@
     expect(completions, hasLength(1));
   }
 
-  Future<void> test_suggestionSets_doesNotFilterSymbolsWithSameName() async {
+  Future<void> test_unimportedSymbols_doesNotFilterSymbolsWithSameName() async {
     // Classes here are not re-exports, so should not be filtered out.
     newFile(
       join(projectFolderPath, 'source_file1.dart'),
@@ -1472,7 +1472,7 @@
     expectAutoImportCompletion(resolvedCompletions, '../source_file3.dart');
   }
 
-  Future<void> test_suggestionSets_enumValues() async {
+  Future<void> test_unimportedSymbols_enumValues() async {
     newFile(
       join(projectFolderPath, 'source_file.dart'),
       content: '''
@@ -1536,7 +1536,7 @@
     '''));
   }
 
-  Future<void> test_suggestionSets_enumValuesAlreadyImported() async {
+  Future<void> test_unimportedSymbols_enumValuesAlreadyImported() async {
     newFile(
       join(projectFolderPath, 'lib', 'source_file.dart'),
       content: '''
@@ -1577,10 +1577,10 @@
     expect(completions, hasLength(1));
     final resolved = await resolveCompletion(completions.first);
     // It should not include auto-import text since it's already imported.
-    expect(resolved.detail, isNull);
+    expect(resolved.detail, isNot(contains('Auto import from')));
   }
 
-  Future<void> test_suggestionSets_filtersOutAlreadyImportedSymbols() async {
+  Future<void> test_unimportedSymbols_filtersOutAlreadyImportedSymbols() async {
     newFile(
       join(projectFolderPath, 'lib', 'source_file.dart'),
       content: '''
@@ -1623,7 +1623,7 @@
     expect(resolved.detail, isNull);
   }
 
-  Future<void> test_suggestionSets_importsPackageUri() async {
+  Future<void> test_unimportedSymbols_importsPackageUri() async {
     newFile(
       join(projectFolderPath, 'lib', 'my_class.dart'),
       content: 'class MyClass {}',
@@ -1654,7 +1654,7 @@
   }
 
   Future<void>
-      test_suggestionSets_includesReexportedSymbolsForEachFile() async {
+      test_unimportedSymbols_includesReexportedSymbolsForEachFile() async {
     newFile(
       join(projectFolderPath, 'source_file.dart'),
       content: '''
@@ -1700,7 +1700,7 @@
     expectAutoImportCompletion(resolvedCompletions, '../reexport2.dart');
   }
 
-  Future<void> test_suggestionSets_insertReplaceRanges() async {
+  Future<void> test_unimportedSymbols_insertReplaceRanges() async {
     newFile(
       join(projectFolderPath, 'other_file.dart'),
       content: '''
@@ -1792,7 +1792,7 @@
     '''));
   }
 
-  Future<void> test_suggestionSets_insertsIntoPartFiles() async {
+  Future<void> test_unimportedSymbols_insertsIntoPartFiles() async {
     // File we'll be adding an import for.
     newFile(
       join(projectFolderPath, 'other_file.dart'),
@@ -1883,7 +1883,7 @@
 part 'main.dart';'''));
   }
 
-  Future<void> test_suggestionSets_members() async {
+  Future<void> test_unimportedSymbols_members() async {
     newFile(
       join(projectFolderPath, 'source_file.dart'),
       content: '''
@@ -1961,7 +1961,7 @@
   /// (as it always used 0 as the modification stamp) which would prevent
   /// completion including items from files that were open (had overlays).
   /// https://github.com/Dart-Code/Dart-Code/issues/2286#issuecomment-658597532
-  Future<void> test_suggestionSets_modifiedFiles() async {
+  Future<void> test_unimportedSymbols_modifiedFiles() async {
     final otherFilePath = join(projectFolderPath, 'lib', 'other_file.dart');
     final otherFileUri = Uri.file(otherFilePath);
 
@@ -1991,7 +1991,7 @@
     expect(matching, hasLength(1));
   }
 
-  Future<void> test_suggestionSets_namedConstructors() async {
+  Future<void> test_unimportedSymbols_namedConstructors() async {
     newFile(
       join(projectFolderPath, 'other_file.dart'),
       content: '''
@@ -2050,7 +2050,8 @@
     '''));
   }
 
-  Future<void> test_suggestionSets_preferRelativeImportsLib_insideLib() async {
+  Future<void>
+      test_unimportedSymbols_preferRelativeImportsLib_insideLib() async {
     _enableLints([LintNames.prefer_relative_imports]);
     final importingFilePath =
         join(projectFolderPath, 'lib', 'nested1', 'main.dart');
@@ -2085,7 +2086,8 @@
     );
   }
 
-  Future<void> test_suggestionSets_preferRelativeImportsLib_outsideLib() async {
+  Future<void>
+      test_unimportedSymbols_preferRelativeImportsLib_outsideLib() async {
     // Files outside of the lib folder should still get absolute imports to
     // files inside lib, even with the lint enabled.
     _enableLints([LintNames.prefer_relative_imports]);
@@ -2122,7 +2124,7 @@
     );
   }
 
-  Future<void> test_suggestionSets_unavailableIfDisabled() async {
+  Future<void> test_unimportedSymbols_unavailableIfDisabled() async {
     newFile(
       join(projectFolderPath, 'other_file.dart'),
       content: 'class InOtherFile {}',
@@ -2137,7 +2139,9 @@
     final initialAnalysis = waitForAnalysisComplete();
     // Support applyEdit, but explicitly disable the suggestions.
     await initialize(
-      initializationOptions: {'suggestFromUnimportedLibraries': false},
+      initializationOptions: {
+        'suggestFromUnimportedLibraries': false,
+      },
       workspaceCapabilities:
           withApplyEditSupport(emptyWorkspaceClientCapabilities),
     );
@@ -2151,7 +2155,7 @@
     expect(completion, isNull);
   }
 
-  Future<void> test_suggestionSets_unavailableWithoutApplyEdit() async {
+  Future<void> test_unimportedSymbols_unavailableWithoutApplyEdit() async {
     // If client doesn't advertise support for workspace/applyEdit, we won't
     // include suggestion sets.
     newFile(
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 3b7fc18..2d009c7 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -30,15 +30,15 @@
     final pluginError = plugin.AnalysisError(
       plugin.AnalysisErrorSeverity.ERROR,
       plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
-      plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0,
-          endLine: 0, endColumn: 6),
+      plugin.Location(pluginAnalyzedFilePath, 0, 6, 1, 1,
+          endLine: 1, endColumn: 7),
       'Test error from plugin',
       'ERR1',
       contextMessages: [
         plugin.DiagnosticMessage(
             'Related error',
-            plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12,
-                endLine: 1, endColumn: 16))
+            plugin.Location(pluginAnalyzedFilePath, 31, 4, 2, 13,
+                endLine: 2, endColumn: 17))
       ],
     );
     final pluginResult =
diff --git a/pkg/analysis_server/test/lsp/file_modification_test.dart b/pkg/analysis_server/test/lsp/file_modification_test.dart
index 17ecd10..10c4323 100644
--- a/pkg/analysis_server/test/lsp/file_modification_test.dart
+++ b/pkg/analysis_server/test/lsp/file_modification_test.dart
@@ -19,7 +19,10 @@
 class FileModificationTest extends AbstractLspAnalysisServerTest {
   Future<void> test_change_badPosition() async {
     final contents = '';
-    await initialize();
+    await initialize(
+      // Error is expected and checked below.
+      failTestOnAnyErrorNotification: false,
+    );
     await openFile(mainFileUri, contents);
 
     // Since this is a notification and not a request, the server cannot
@@ -86,7 +89,10 @@
           end: Position(line: 1, character: 1)),
       text: 'test',
     ));
-    await initialize();
+    await initialize(
+      // Error is expected and checked below.
+      failTestOnAnyErrorNotification: false,
+    );
     final notificationParams = await expectErrorNotification(
       () => changeFile(222, mainFileUri, [simpleEdit]),
     );
@@ -131,7 +137,10 @@
   }
 
   Future<void> test_open_invalidPath() async {
-    await initialize();
+    await initialize(
+      // Error is expected and checked below.
+      failTestOnAnyErrorNotification: false,
+    );
 
     final notificationParams = await expectErrorNotification(
       () => openFile(Uri.http('localhost', 'not-a-file'), ''),
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 19c80c0..bb8423b 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -68,6 +68,7 @@
 ```dart
 String abc
 ```
+Type: `String`
 *package:test/main.dart*
 
 ---
@@ -159,6 +160,32 @@
     expect(markup.value, contains('This is a string.'));
   }
 
+  Future<void> test_promotedTypes() async {
+    final content = '''
+void f(aaa) {
+  if (aaa is String) {
+    print([[aa^a]]);
+  }
+}
+    ''';
+
+    final expectedHoverContent = '''
+```dart
+dynamic aaa
+```
+Type: `String`
+    '''
+        .trim();
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final hover = await getHover(mainFileUri, positionFromMarker(content));
+    expect(hover, isNotNull);
+    expect(hover!.range, equals(rangeFromMarkers(content)));
+    expect(hover.contents, isNotNull);
+    expect(_getStringContents(hover), equals(expectedHoverContent));
+  }
+
   Future<void> test_range_multiLineConstructorCall() async {
     final content = '''
     final a = new [[Str^ing.fromCharCodes]]([
@@ -229,6 +256,7 @@
 ```dart
 String abc
 ```
+Type: `String`
 *package:test/main.dart*
     '''
         .trim();
@@ -327,6 +355,7 @@
 ```dart
 String? abc
 ```
+Type: `String?`
 *package:test/main.dart*
     '''
         .trim();
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 413afeb..5cf681a 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -673,21 +673,41 @@
     expect(server.contextManager.includedPaths, equals([projectFolderPath]));
   }
 
+  Future<void> test_initialize_rootPath_trailingSlash() async {
+    await initialize(rootPath: withTrailingSlash(projectFolderPath));
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+  }
+
   Future<void> test_initialize_rootUri() async {
     await initialize(rootUri: projectFolderUri);
     expect(server.contextManager.includedPaths, equals([projectFolderPath]));
   }
 
+  Future<void> test_initialize_rootUri_trailingSlash() async {
+    await initialize(rootUri: withTrailingSlashUri(projectFolderUri));
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+  }
+
   Future<void> test_initialize_workspaceFolders() async {
     await initialize(workspaceFolders: [projectFolderUri]);
     expect(server.contextManager.includedPaths, equals([projectFolderPath]));
   }
 
+  Future<void> test_initialize_workspaceFolders_trailingSlash() async {
+    await initialize(
+        workspaceFolders: [withTrailingSlashUri(projectFolderUri)]);
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+  }
+
   Future<void> test_nonFileScheme_rootUri() async {
     final rootUri = Uri.parse('vsls://');
     final fileUri = rootUri.replace(path: '/file1.dart');
 
-    await initialize(rootUri: rootUri);
+    await initialize(
+      rootUri: rootUri,
+      // We expect an error notification about the invalid file we try to open.
+      failTestOnAnyErrorNotification: false,
+    );
     expect(server.contextManager.includedPaths, equals([]));
 
     // Also open a non-file file to ensure it doesn't cause the root to be added.
@@ -702,10 +722,14 @@
     final rootUri = Uri.parse('vsls://');
     final fileUri = rootUri.replace(path: '/file1.dart');
 
-    await initialize(workspaceFolders: [
-      rootUri,
-      Uri.file(projectFolderPath),
-    ]);
+    await initialize(
+      workspaceFolders: [
+        rootUri,
+        Uri.file(projectFolderPath),
+      ],
+      // We expect an error notification about the invalid file we try to open.
+      failTestOnAnyErrorNotification: false,
+    );
     expect(server.contextManager.includedPaths, equals([projectFolderPath]));
 
     // Also open a non-file file to ensure it doesn't cause the root to be added.
@@ -876,4 +900,15 @@
     expect(response.error, isNotNull);
     expect(response.error!.code, ErrorCodes.ServerNotInitialized);
   }
+
+  String withTrailingSlash(String path) {
+    expect(path, isNot(endsWith('/')));
+    final pathSeparator = server.resourceProvider.pathContext.separator;
+    return '$path$pathSeparator';
+  }
+
+  Uri withTrailingSlashUri(Uri uri) {
+    expect(uri.path, isNot(endsWith('/')));
+    return uri.replace(path: '${uri.path}/');
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
index 907b8fa..3b99787 100644
--- a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -273,8 +273,10 @@
       _Token('/// field docs', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('String', SemanticTokenTypes.class_),
-      _Token('myField', SemanticTokenTypes.property,
-          [SemanticTokenModifiers.declaration]),
+      _Token('myField', SemanticTokenTypes.property, [
+        SemanticTokenModifiers.declaration,
+        CustomSemanticTokenModifiers.instance
+      ]),
       _Token("'FieldVal'", SemanticTokenTypes.string),
       _Token('/// static field docs', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
@@ -292,7 +294,8 @@
           [CustomSemanticTokenModifiers.constructor]),
       _Token('print', SemanticTokenTypes.function),
       _Token('a', SemanticTokenTypes.variable),
-      _Token('myField', SemanticTokenTypes.property),
+      _Token('myField', SemanticTokenTypes.property,
+          [CustomSemanticTokenModifiers.instance]),
       _Token('MyClass', SemanticTokenTypes.class_),
       _Token('myStaticField', SemanticTokenTypes.property,
           [SemanticTokenModifiers.static]),
@@ -334,14 +337,18 @@
           [SemanticTokenModifiers.documentation]),
       _Token('String', SemanticTokenTypes.class_),
       _Token('get', SemanticTokenTypes.keyword),
-      _Token('myGetter', SemanticTokenTypes.property,
-          [SemanticTokenModifiers.declaration]),
+      _Token('myGetter', SemanticTokenTypes.property, [
+        SemanticTokenModifiers.declaration,
+        CustomSemanticTokenModifiers.instance
+      ]),
       _Token("'GetterVal'", SemanticTokenTypes.string),
       _Token('/// setter docs', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('set', SemanticTokenTypes.keyword),
-      _Token('mySetter', SemanticTokenTypes.property,
-          [SemanticTokenModifiers.declaration]),
+      _Token('mySetter', SemanticTokenTypes.property, [
+        SemanticTokenModifiers.declaration,
+        CustomSemanticTokenModifiers.instance
+      ]),
       _Token('String', SemanticTokenTypes.class_),
       _Token('v', SemanticTokenTypes.parameter,
           [SemanticTokenModifiers.declaration]),
@@ -371,9 +378,11 @@
           [CustomSemanticTokenModifiers.constructor]),
       _Token('print', SemanticTokenTypes.function),
       _Token('a', SemanticTokenTypes.variable),
-      _Token('myGetter', SemanticTokenTypes.property),
+      _Token('myGetter', SemanticTokenTypes.property,
+          [CustomSemanticTokenModifiers.instance]),
       _Token('a', SemanticTokenTypes.variable),
-      _Token('mySetter', SemanticTokenTypes.property),
+      _Token('mySetter', SemanticTokenTypes.property,
+          [CustomSemanticTokenModifiers.instance]),
       _Token("'a'", SemanticTokenTypes.string),
     ];
 
@@ -416,8 +425,10 @@
           [CustomSemanticTokenModifiers.annotation]),
       _Token('void', SemanticTokenTypes.keyword,
           [CustomSemanticTokenModifiers.void_]),
-      _Token('myMethod', SemanticTokenTypes.method,
-          [SemanticTokenModifiers.declaration]),
+      _Token('myMethod', SemanticTokenTypes.method, [
+        SemanticTokenModifiers.declaration,
+        CustomSemanticTokenModifiers.instance
+      ]),
       _Token('/// static method docs', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('static', SemanticTokenTypes.keyword),
@@ -434,7 +445,8 @@
       _Token('MyClass', SemanticTokenTypes.class_,
           [CustomSemanticTokenModifiers.constructor]),
       _Token('a', SemanticTokenTypes.variable),
-      _Token('myMethod', SemanticTokenTypes.method),
+      _Token('myMethod', SemanticTokenTypes.method,
+          [CustomSemanticTokenModifiers.instance]),
       _Token('MyClass', SemanticTokenTypes.class_),
       _Token('myStaticMethod', SemanticTokenTypes.method,
           [SemanticTokenModifiers.static]),
@@ -442,7 +454,8 @@
       _Token('b', SemanticTokenTypes.variable,
           [SemanticTokenModifiers.declaration]),
       _Token('a', SemanticTokenTypes.variable),
-      _Token('myMethod', SemanticTokenTypes.method),
+      _Token('myMethod', SemanticTokenTypes.method,
+          [CustomSemanticTokenModifiers.instance]),
       _Token('final', SemanticTokenTypes.keyword),
       _Token('c', SemanticTokenTypes.variable,
           [SemanticTokenModifiers.declaration]),
@@ -473,14 +486,17 @@
     final expected = [
       _Token('/// before [', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
-      _Token('aaa', SemanticTokenTypes.property),
+      _Token('aaa', SemanticTokenTypes.property,
+          [CustomSemanticTokenModifiers.instance]),
       _Token('] after', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('class', SemanticTokenTypes.keyword),
       _Token('MyClass', SemanticTokenTypes.class_),
       _Token('String', SemanticTokenTypes.class_),
-      _Token('aaa', SemanticTokenTypes.property,
-          [SemanticTokenModifiers.declaration]),
+      _Token('aaa', SemanticTokenTypes.property, [
+        SemanticTokenModifiers.declaration,
+        CustomSemanticTokenModifiers.instance
+      ]),
       _Token('/// before [', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('bbb', SemanticTokenTypes.parameter),
@@ -813,8 +829,10 @@
         _Token('/// test', SemanticTokenTypes.comment,
             [SemanticTokenModifiers.documentation]),
         _Token('bool', SemanticTokenTypes.class_),
-        _Token('test$i', SemanticTokenTypes.property,
-            [SemanticTokenModifiers.declaration]),
+        _Token('test$i', SemanticTokenTypes.property, [
+          SemanticTokenModifiers.declaration,
+          CustomSemanticTokenModifiers.instance
+        ]),
         _Token('false', CustomSemanticTokenTypes.boolean),
       ],
     ];
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 851966e..01da792 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -1055,6 +1055,12 @@
   }
 
   Future<List<CompletionItem>> getCompletion(Uri uri, Position pos,
+      {CompletionContext? context}) async {
+    final response = await getCompletionList(uri, pos, context: context);
+    return response.items;
+  }
+
+  Future<CompletionList> getCompletionList(Uri uri, Position pos,
       {CompletionContext? context}) {
     final request = makeRequest(
       Method.textDocument_completion,
@@ -1064,8 +1070,7 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo(
-        request, _fromJsonList(CompletionItem.fromJson));
+    return expectSuccessfulResponseTo(request, CompletionList.fromJson);
   }
 
   Future<Either2<List<Location>, List<LocationLink>>> getDefinition(
@@ -1361,7 +1366,14 @@
     Map<String, Object?>? initializationOptions,
     bool throwOnFailure = true,
     bool allowEmptyRootUri = false,
+    bool failTestOnAnyErrorNotification = true,
   }) async {
+    if (failTestOnAnyErrorNotification) {
+      errorNotificationsFromServer.listen((NotificationMessage error) {
+        fail('${error.toJson()}');
+      });
+    }
+
     final clientCapabilities = ClientCapabilities(
       workspace: workspaceCapabilities,
       textDocument: textDocumentCapabilities,
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index c5508eb..22608c0 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -18,7 +18,10 @@
 @reflectiveTest
 class ServerTest extends AbstractLspAnalysisServerTest {
   Future<void> test_inconsistentStateError() async {
-    await initialize();
+    await initialize(
+      // Error is expected and checked below.
+      failTestOnAnyErrorNotification: false,
+    );
     await openFile(mainFileUri, '');
     // Attempt to make an illegal modification to the file. This indicates the
     // client and server are out of sync and we expect the server to shut down.
@@ -53,7 +56,10 @@
   }
 
   Future<void> test_unknownNotifications_logError() async {
-    await initialize();
+    await initialize(
+      // Error is expected and checked below.
+      failTestOnAnyErrorNotification: false,
+    );
 
     final notification =
         makeNotification(Method.fromJson(r'some/randomNotification'), null);
diff --git a/pkg/analysis_server/test/search/abstract_search_domain.dart b/pkg/analysis_server/test/search/abstract_search_domain.dart
index cba622f..54b8990 100644
--- a/pkg/analysis_server/test/search/abstract_search_domain.dart
+++ b/pkg/analysis_server/test/search/abstract_search_domain.dart
@@ -80,9 +80,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     server.handlers = [
       SearchDomainHandler(server),
     ];
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index e0fef5d..28f9cba 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/domain_analysis.dart';
 import 'package:analysis_server/src/search/search_domain.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -21,10 +22,11 @@
   static const String requestId = 'test-getTypeHierarchy';
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     server.handlers = [
+      AnalysisDomainHandler(server),
       SearchDomainHandler(server),
     ];
   }
@@ -62,7 +64,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -74,7 +77,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -114,7 +118,8 @@
           'kind': 'CLASS',
           'name': 'AAA',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -126,7 +131,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -137,7 +143,8 @@
           'kind': 'CLASS',
           'name': 'BBB',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -149,7 +156,8 @@
           'kind': 'CLASS',
           'name': 'CCC',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -177,9 +185,8 @@
 ''');
     await waitForTasksFinished();
     // configure roots
-    var request = AnalysisSetAnalysisRootsParams(
-        [projectPath, convertPath('/packages/pkgA')], []).toRequest('0');
-    handleSuccessfulRequest(request);
+    await setRoots(
+        included: [projectPath, convertPath('/packages/pkgA')], excluded: []);
     // test A type hierarchy
     var items = await _getTypeHierarchy('A {}');
     var names = _toClassNames(items);
@@ -203,7 +210,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -215,7 +223,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -226,7 +235,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -238,7 +248,8 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 2,
         'interfaces': [],
@@ -264,7 +275,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -276,7 +288,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 2,
         'interfaces': [],
@@ -288,7 +301,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -299,7 +313,8 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -325,7 +340,8 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -337,7 +353,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 2,
         'interfaces': [],
@@ -349,7 +366,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 3,
         'interfaces': [],
@@ -361,7 +379,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -386,7 +405,8 @@
           'kind': 'CLASS',
           'name': 'T',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [2, 3],
@@ -398,7 +418,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -409,7 +430,8 @@
           'kind': 'CLASS',
           'name': 'MA',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -421,7 +443,8 @@
           'kind': 'CLASS',
           'name': 'MB',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -448,7 +471,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -460,7 +484,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -471,7 +496,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -483,7 +509,8 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -495,7 +522,8 @@
           'kind': 'CLASS',
           'name': 'D',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -507,7 +535,8 @@
           'kind': 'CLASS',
           'name': 'E',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 0,
         'interfaces': [],
@@ -519,7 +548,8 @@
           'kind': 'CLASS',
           'name': 'F',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 4,
         'interfaces': [],
@@ -531,7 +561,8 @@
           'kind': 'CLASS',
           'name': 'G',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 4,
         'interfaces': [],
@@ -557,7 +588,8 @@
           'kind': 'CLASS',
           'name': 'T',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -569,7 +601,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -580,7 +613,8 @@
           'kind': 'CLASS',
           'name': 'MA',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -592,7 +626,8 @@
           'kind': 'CLASS',
           'name': 'MB',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [],
@@ -1132,7 +1167,8 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 1,
         'interfaces': [3],
@@ -1144,7 +1180,8 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 2,
         'interfaces': [],
@@ -1156,7 +1193,8 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'interfaces': [],
         'mixins': [],
@@ -1167,7 +1205,8 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0
+          'flags': 0,
+          'libraryUri': anything
         },
         'superclass': 2,
         'interfaces': [],
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 f320c5f..7bf72fe 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
@@ -6,10 +6,10 @@
 import 'package:analysis_server/src/services/completion/dart/arglist_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
-import 'package:test/test.dart';
+import 'package:analyzer_utilities/check/check.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'completion_check.dart';
 import 'completion_contributor_util.dart';
 
 void main() {
@@ -19,95 +19,6 @@
 }
 
 mixin ArgListContributorMixin on DartCompletionContributorTest {
-  void assertNoOtherSuggestions(Iterable<CompletionSuggestion> expected) {
-    for (var suggestion in suggestions) {
-      if (!expected.contains(suggestion)) {
-        failedCompletion('did not expect completion: '
-            '${suggestion.completion}\n  $suggestion');
-      }
-    }
-  }
-
-  /// Assert that there is a suggestion with the given parameter [name] that has
-  /// the given [completion], [selectionOffset] and [selectionLength].
-  void assertSuggestArgumentAndCompletion(String name,
-      {required String completion,
-      required int selectionOffset,
-      int selectionLength = 0}) {
-    var suggestion = suggestions.firstWhere((s) => s.parameterName == name);
-    expect(suggestion, isNotNull);
-    expect(suggestion.completion, completion);
-    expect(suggestion.selectionOffset, selectionOffset);
-    expect(suggestion.selectionLength, selectionLength);
-  }
-
-  void assertSuggestArgumentList_params(
-      List<String> expectedNames,
-      List<String> expectedTypes,
-      List<String>? actualNames,
-      List<String>? actualTypes) {
-    if (actualNames != null &&
-        actualNames.length == expectedNames.length &&
-        actualTypes != null &&
-        actualTypes.length == expectedTypes.length) {
-      var index = 0;
-      while (index < expectedNames.length) {
-        if (actualNames[index] != expectedNames[index] ||
-            actualTypes[index] != expectedTypes[index]) {
-          break;
-        }
-        ++index;
-      }
-      if (index == expectedNames.length) {
-        return;
-      }
-    }
-    var msg = StringBuffer();
-    msg.writeln('Argument list not the same');
-    msg.writeln('  Expected names: $expectedNames');
-    msg.writeln('           found: $actualNames');
-    msg.writeln('  Expected types: $expectedTypes');
-    msg.writeln('           found: $actualTypes');
-    fail(msg.toString());
-  }
-
-  /// Assert that the specified named argument suggestions with their types are
-  /// the only suggestions.
-  void assertSuggestArgumentsAndTypes(
-      {required Map<String, String> namedArgumentsWithTypes,
-      bool includeColon = true,
-      bool includeComma = false}) {
-    var expected = <CompletionSuggestion>[];
-    namedArgumentsWithTypes.forEach((String name, String type) {
-      var completion = includeColon ? '$name: ' : name;
-      // Selection should be before any trailing commas.
-      var selectionOffset = completion.length;
-      if (includeComma) {
-        completion = '$completion,';
-      }
-      expected.add(assertSuggest(completion,
-          csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-          paramName: name,
-          paramType: type,
-          selectionOffset: selectionOffset));
-    });
-    assertNoOtherSuggestions(expected);
-  }
-
-  /// Assert that the specified suggestions are the only suggestions.
-  void assertSuggestions(List<String> suggestions) {
-    var expected = <CompletionSuggestion>[];
-    for (var suggestion in suggestions) {
-      // Selection offset should be before any trailing commas.
-      var selectionOffset =
-          suggestion.endsWith(',') ? suggestion.length - 1 : suggestion.length;
-      expected.add(assertSuggest('$suggestion',
-          csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-          selectionOffset: selectionOffset));
-    }
-    assertNoOtherSuggestions(expected);
-  }
-
   @override
   DartCompletionContributor createContributor(
     DartCompletionRequest request,
@@ -135,21 +46,22 @@
 }
 ''';
     addTestSource(content);
-    await computeSuggestions();
-    expect(suggestions, hasLength(1));
 
-    var suggestion = suggestions[0];
-    expect(suggestion.docSummary, 'aaa');
-    expect(suggestion.docComplete, 'aaa\n\nbbb\nccc');
-
-    var element = suggestion.element!;
-    expect(element.kind, ElementKind.PARAMETER);
-    expect(element.name, 'fff');
-    expect(element.location!.offset, content.indexOf('fff})'));
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('fff: ')
+        ..docComplete.isEqualTo('aaa\n\nbbb\nccc')
+        ..docSummary.isEqualTo('aaa')
+        ..hasSelection(offset: 5)
+        ..element.isNotNull.which((e) => e
+          ..kind.isParameter
+          ..name.isEqualTo('fff'))
+    ]);
   }
 
   Future<void> test_fieldFormal_noDocumentation() async {
-    var content = '''
+    addTestSource('''
 class A {
   int fff;
   A({this.fff});
@@ -157,19 +69,19 @@
 main() {
   new A(^);
 }
-''';
-    addTestSource(content);
-    await computeSuggestions();
-    expect(suggestions, hasLength(1));
+''');
 
-    var suggestion = suggestions[0];
-    expect(suggestion.docSummary, isNull);
-    expect(suggestion.docComplete, isNull);
-
-    var element = suggestion.element!;
-    expect(element.kind, ElementKind.PARAMETER);
-    expect(element.name, 'fff');
-    expect(element.location!.offset, content.indexOf('fff})'));
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('fff: ')
+        ..docComplete.isNull
+        ..docSummary.isNull
+        ..hasSelection(offset: 5)
+        ..element.isNotNull.which((e) => e
+          ..kind.isParameter
+          ..name.isEqualTo('fff'))
+    ]);
   }
 
   Future<void> test_flutter_InstanceCreationExpression_0() async {
@@ -183,13 +95,13 @@
   );
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: [],',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null,
-        selectionOffset: 11,
-        defaultArgumentListTextRanges: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).containsMatch((suggestion) {
+      suggestion
+        ..completion.isEqualTo('children: [],')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 11);
+    });
   }
 
   Future<void> test_flutter_InstanceCreationExpression_01() async {
@@ -205,12 +117,13 @@
   );
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('backgroundColor: ,',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null, // No default values.
-        selectionOffset: 17);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).containsMatch((suggestion) {
+      suggestion
+        ..completion.isEqualTo('backgroundColor: ,')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 17);
+    });
   }
 
   Future<void> test_flutter_InstanceCreationExpression_1() async {
@@ -225,13 +138,13 @@
   );
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: [],',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null,
-        selectionOffset: 11,
-        defaultArgumentListTextRanges: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).containsMatch((suggestion) {
+      suggestion
+        ..completion.isEqualTo('children: [],')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 11);
+    });
   }
 
   Future<void> test_flutter_InstanceCreationExpression_2() async {
@@ -246,13 +159,13 @@
   );
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: [],',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null,
-        selectionOffset: 11,
-        defaultArgumentListTextRanges: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).containsMatch((suggestion) {
+      suggestion
+        ..completion.isEqualTo('children: [],')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 11);
+    });
   }
 
   Future<void>
@@ -273,13 +186,13 @@
 }
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: [],',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null,
-        selectionOffset: 11,
-        defaultArgumentListTextRanges: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('children: [],')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 11),
+    ]);
   }
 
   Future<void> test_flutter_InstanceCreationExpression_children_Map() async {
@@ -298,12 +211,13 @@
 }
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: ,',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        selectionOffset: 10,
-        defaultArgListString: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('children: ,')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 10),
+    ]);
   }
 
   Future<void> test_flutter_InstanceCreationExpression_slivers() async {
@@ -321,13 +235,13 @@
 }
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('slivers: [],',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null,
-        selectionOffset: 10,
-        defaultArgumentListTextRanges: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('slivers: [],')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 10),
+    ]);
   }
 
   Future<void> test_flutter_MethodExpression_children() async {
@@ -347,23 +261,32 @@
 foo({String children}) {}
 ''');
 
-    await computeSuggestions();
-
-    assertSuggest('children: ',
-        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-        defaultArgListString: null);
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).matchesInAnyOrder([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('children: ')
+        ..defaultArgumentListString.isNull
+        ..defaultArgumentListTextRanges.isNull,
+    ]);
   }
 
   Future<void> test_named_01() async {
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool', 'two': 'int'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ')
+            ..parameterType.isEqualTo('int')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -372,12 +295,19 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(o^)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool', 'two': 'int'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ')
+            ..parameterType.isEqualTo('int')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -386,11 +316,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(o^ two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-            namedArgumentsWithTypes: {'one': 'bool'}, includeComma: true);
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ,', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ,')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -399,11 +332,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(o^, two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-            namedArgumentsWithTypes: {'one': 'bool'}, includeComma: false);
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -412,11 +348,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(o^ , two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-            namedArgumentsWithTypes: {'one': 'bool'}, includeComma: false);
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -425,12 +364,19 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^o,)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool', 'two': 'int'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ')
+            ..parameterType.isEqualTo('int')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -439,11 +385,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^ two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-            namedArgumentsWithTypes: {'one': 'bool'}, includeComma: true);
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ,', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ,')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -452,8 +401,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^two: 2)',
-      check: () {
-        assertSuggestions(['one: ,']);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ,')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(right: 3)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -462,13 +417,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^, two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool'},
-          includeComma: false,
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -477,10 +433,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(^ , two: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool'},
-        );
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -489,10 +449,14 @@
     await _tryParametersArguments(
       parameters: '(int one, {bool two, int three})',
       arguments: '(1, ^, three: 3)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'two': 'bool'},
-        );
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -501,8 +465,14 @@
     await _tryParametersArguments(
       parameters: '(int one, {bool two, int three})',
       arguments: '(1, ^ three: 3)',
-      check: () {
-        assertSuggestions(['two: ,']);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ,')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -511,8 +481,14 @@
     await _tryParametersArguments(
       parameters: '(int one, {bool two, int three})',
       arguments: '(1, ^three: 3)',
-      check: () {
-        assertSuggestions(['two: ,']);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ,')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(right: 5)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -522,8 +498,8 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(two: 2^)',
-      check: () {
-        assertSuggestions([', one: ']);
+      check: (response) {
+        _checkNamedArguments(response).isEmpty;
       },
     );
   }
@@ -533,8 +509,8 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(two: 2 ^)',
-      check: () {
-        assertSuggestions([', one: ']);
+      check: (response) {
+        _checkNamedArguments(response).isEmpty;
       },
     );
   }
@@ -543,12 +519,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(two: 2, ^)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -557,12 +535,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(two: 2, o^)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -571,12 +551,14 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(two: 2, o^,)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool'},
-        );
-        assertSuggestArgumentAndCompletion('one',
-            completion: 'one: ', selectionOffset: 5);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one: ')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 5),
+        ]);
       },
     );
   }
@@ -585,8 +567,19 @@
     await _tryParametersArguments(
       parameters: '(int one, int two, int three, {int four, int five})',
       arguments: '(1, ^, 3)',
-      check: () {
-        assertSuggestions(['four: ', 'five: ']);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('four: ')
+            ..parameterType.isEqualTo('int')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 6),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('five: ')
+            ..parameterType.isEqualTo('int')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 6),
+        ]);
       },
     );
   }
@@ -596,8 +589,8 @@
       languageVersion: '2.15',
       parameters: '(int one, int two, int three, {int four, int five})',
       arguments: '(1, ^, 3)',
-      check: () {
-        assertNoSuggestions();
+      check: (response) {
+        _checkNamedArguments(response).isEmpty;
       },
     );
   }
@@ -606,11 +599,19 @@
     await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(o^: false)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'one': 'bool', 'two': 'int'},
-          includeColon: false,
-        );
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('one')
+            ..parameterType.isEqualTo('bool')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 3),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two')
+            ..parameterType.isEqualTo('int')
+            ..hasReplacement(left: 1)
+            ..hasSelection(offset: 3),
+        ]);
       },
     );
   }
@@ -619,30 +620,68 @@
     await _tryParametersArguments(
       parameters: '(bool one, {int two, double three})',
       arguments: '(false, ^t: 2)',
-      check: () {
-        assertSuggestions(['two: ,', 'three: ,']);
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two: ,')
+            ..parameterType.isEqualTo('int')
+            ..hasReplacement(right: 1)
+            ..hasSelection(offset: 5),
+          (suggestion) => suggestion
+            ..completion.isEqualTo('three: ,')
+            ..parameterType.isEqualTo('double')
+            ..hasReplacement(right: 1)
+            ..hasSelection(offset: 7),
+        ]);
       },
     );
   }
 
   Future<void> test_named_23() async {
     await _tryParametersArguments(
-      parameters: '(bool one, {int two, double three})',
-      arguments: '(false, ^: 2)',
-      check: () {
-        assertSuggestArgumentsAndTypes(
-          namedArgumentsWithTypes: {'two': 'int', 'three': 'double'},
-        );
+      parameters: '(bool one, {int two})',
+      arguments: '(false, foo^ba: 2)',
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            ..completion.isEqualTo('two')
+            ..parameterType.isEqualTo('int')
+            ..hasReplacement(left: 3, right: 2)
+            ..hasSelection(offset: 3),
+        ]);
       },
     );
   }
 
   Future<void> test_named_24() async {
     await _tryParametersArguments(
+      parameters: '(bool one, {int two, double three})',
+      arguments: '(false, ^: 2)',
+      check: (response) {
+        _checkNamedArguments(response).matchesInAnyOrder([
+          (suggestion) => suggestion
+            // TODO(scheglov) This does not seem right.
+            ..completion.isEqualTo('two: ')
+            ..parameterType.isEqualTo('int')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 5),
+          (suggestion) => suggestion
+            // TODO(scheglov) This does not seem right.
+            ..completion.isEqualTo('three: ')
+            ..parameterType.isEqualTo('double')
+            ..hasEmptyReplacement()
+            ..hasSelection(offset: 7),
+        ]);
+      },
+    );
+  }
+
+  Future<void> test_named_25() async {
+    await _tryParametersArguments(
       parameters: '({bool one, int two})',
       arguments: '(one: ^)',
-      check: () {
-        assertNoSuggestions();
+      check: (response) {
+        _checkNamedArguments(response).isEmpty;
       },
     );
   }
@@ -651,12 +690,17 @@
     String? languageVersion,
     required String parameters,
     required String arguments,
-    required void Function() check,
+    required void Function(CompletionResponseForTesting response) check,
   }) async {
     var languageVersionLine = languageVersion != null
         ? '// @dart = $languageVersion'
         : '// no language version override';
 
+    Future<void> computeAndCheck() async {
+      var response = await computeSuggestions2();
+      check(response);
+    }
+
     // Annotation, local class.
     addTestSource2('''
 $languageVersionLine
@@ -666,8 +710,7 @@
 @A$arguments
 void f() {}
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Annotation, imported class.
     newFile('$testPackageLibPath/a.dart', content: '''
@@ -681,8 +724,7 @@
 @A$arguments
 void f() {}
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Annotation, imported class, prefixed.
     newFile('$testPackageLibPath/a.dart', content: '''
@@ -696,8 +738,7 @@
 @p.A$arguments
 void f() {}
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Function expression invocation.
     addTestSource2('''
@@ -706,8 +747,7 @@
 void f$parameters() {}
 var v = (f)$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Instance creation, local class, generative.
     addTestSource2('''
@@ -717,8 +757,7 @@
 }
 var v = A$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Instance creation, imported class, generative.
     newFile('$testPackageLibPath/a.dart', content: '''
@@ -731,8 +770,7 @@
 import 'a.dart';
 var v = A$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Instance creation, imported class, factory.
     newFile('$testPackageLibPath/a.dart', content: '''
@@ -745,8 +783,7 @@
 import 'a.dart';
 var v = A$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Method invocation, local method.
     addTestSource2('''
@@ -756,8 +793,7 @@
 }
 var v = A().foo$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Method invocation, local function.
     addTestSource2('''
@@ -765,8 +801,7 @@
 void f$parameters() {}
 var v = f$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Method invocation, imported function.
     newFile('$testPackageLibPath/a.dart', content: '''
@@ -777,8 +812,7 @@
 import 'a.dart';
 var v = f$arguments;
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Super constructor invocation.
     addTestSource2('''
@@ -790,8 +824,7 @@
   B() : super$arguments;
 }
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // This constructor invocation.
     addTestSource2('''
@@ -801,8 +834,7 @@
   A.named() : this$arguments;
 }
 ''');
-    await computeSuggestions();
-    check();
+    await computeAndCheck();
 
     // Invalid: getter invocation.
     // Parameters not used. Check not used.
@@ -814,4 +846,9 @@
     await computeSuggestions();
     assertNoSuggestions();
   }
+
+  static CheckTarget<Iterable<CompletionSuggestionForTesting>>
+      _checkNamedArguments(CompletionResponseForTesting response) {
+    return check(response).suggestions.namedArguments;
+  }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
index a04f0be..3b1df62 100644
--- a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
@@ -63,8 +63,7 @@
     assertSuggestClass('A', kind: CompletionSuggestionKind.IDENTIFIER);
     assertSuggestClass('B', kind: CompletionSuggestionKind.IDENTIFIER);
     assertSuggestClass('PB', kind: CompletionSuggestionKind.IDENTIFIER);
-    assertSuggestTopLevelVar('T1', null,
-        kind: CompletionSuggestionKind.IDENTIFIER);
+    assertSuggestTopLevelVar('T1', null);
     assertSuggestFunction('F1', 'PB',
         kind: CompletionSuggestionKind.IDENTIFIER);
     assertNotSuggested('C');
@@ -107,8 +106,7 @@
     assertSuggestClass('B', kind: CompletionSuggestionKind.IDENTIFIER);
     assertNotSuggested('_AB');
     assertSuggestClass('PB', kind: CompletionSuggestionKind.IDENTIFIER);
-    assertSuggestTopLevelVar('T1', null,
-        kind: CompletionSuggestionKind.IDENTIFIER);
+    assertSuggestTopLevelVar('T1', null);
     assertSuggestFunction('F1', 'PB',
         kind: CompletionSuggestionKind.IDENTIFIER);
     assertSuggestClass('Clz', kind: CompletionSuggestionKind.IDENTIFIER);
@@ -147,8 +145,7 @@
   Future<void> test_Combinator_show_pi() async {
     addTestSource('import "dart:math" show ^;');
     await computeSuggestions();
-    assertSuggestTopLevelVar('pi', 'double',
-        kind: CompletionSuggestionKind.IDENTIFIER);
+    assertSuggestTopLevelVar('pi', 'double');
   }
 
   Future<void> test_Combinator_show_recursive() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
new file mode 100644
index 0000000..57a911e
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -0,0 +1,411 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:meta/meta.dart';
+
+class CompletionResponseForTesting {
+  final int requestOffset;
+  final int replacementOffset;
+  final int replacementLength;
+  final bool isIncomplete;
+  final List<CompletionSuggestion> suggestions;
+
+  CompletionResponseForTesting({
+    required this.requestOffset,
+    required this.replacementOffset,
+    required this.replacementLength,
+    required this.isIncomplete,
+    required this.suggestions,
+  });
+
+  factory CompletionResponseForTesting.legacy(
+    int requestOffset,
+    CompletionResultsParams parameters,
+  ) {
+    return CompletionResponseForTesting(
+      requestOffset: requestOffset,
+      replacementOffset: parameters.replacementOffset,
+      replacementLength: parameters.replacementLength,
+      isIncomplete: false,
+      suggestions: parameters.results,
+    );
+  }
+}
+
+/// A completion suggestion with the response for context.
+class CompletionSuggestionForTesting {
+  final CompletionResponseForTesting response;
+  final CompletionSuggestion suggestion;
+
+  CompletionSuggestionForTesting({
+    required this.response,
+    required this.suggestion,
+  });
+
+  /// Return the effective replacement length.
+  int get replacementLength =>
+      suggestion.replacementLength ?? response.replacementLength;
+
+  /// Return the effective replacement offset.
+  int get replacementOffset =>
+      suggestion.replacementOffset ?? response.replacementOffset;
+
+  @override
+  String toString() => '(completion: ${suggestion.completion})';
+}
+
+extension CompletionResponseExtension
+    on CheckTarget<CompletionResponseForTesting> {
+  @useResult
+  CheckTarget<bool> get isIncomplete {
+    return nest(
+      value.isIncomplete,
+      (selected) => 'has isIncomplete ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<int> get replacementLength {
+    return nest(
+      value.replacementLength,
+      (selected) => 'has replacementLength ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<int> get replacementOffset {
+    return nest(
+      value.replacementOffset,
+      (selected) => 'has replacementOffset ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<List<CompletionSuggestionForTesting>> get suggestions {
+    var suggestions = value.suggestions.map((e) {
+      return CompletionSuggestionForTesting(
+        response: value,
+        suggestion: e,
+      );
+    }).toList();
+    return nest(
+      suggestions,
+      (selected) => 'suggestions ${valueStr(selected)}',
+    );
+  }
+
+  void assertComplete() {
+    isIncomplete.isFalse;
+  }
+
+  void assertIncomplete() {
+    isIncomplete.isTrue;
+  }
+
+  /// Check that the replacement offset is the completion request offset,
+  /// and the length of the replacement is zero.
+  void hasEmptyReplacement() {
+    hasReplacement(left: 0, right: 0);
+  }
+
+  /// Check that the replacement offset is the completion request offset
+  /// minus [left], and the length of the replacement is `left + right`.
+  void hasReplacement({int left = 0, int right = 0}) {
+    replacementOffset.isEqualTo(value.requestOffset - left);
+    replacementLength.isEqualTo(left + right);
+  }
+}
+
+extension CompletionSuggestionExtension
+    on CheckTarget<CompletionSuggestionForTesting> {
+  @useResult
+  CheckTarget<String> get completion {
+    return nest(
+      value.suggestion.completion,
+      (selected) => 'has completion ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get defaultArgumentListString {
+    return nest(
+      value.suggestion.defaultArgumentListString,
+      (selected) => 'has defaultArgumentListString ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<List<int>?> get defaultArgumentListTextRanges {
+    return nest(
+      value.suggestion.defaultArgumentListTextRanges,
+      (selected) => 'has defaultArgumentListTextRanges ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get docComplete {
+    return nest(
+      value.suggestion.docComplete,
+      (selected) => 'has docComplete ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get docSummary {
+    return nest(
+      value.suggestion.docSummary,
+      (selected) => 'has docSummary ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<Element?> get element {
+    return nest(
+      value.suggestion.element,
+      (selected) => 'has element ${valueStr(selected)}',
+    );
+  }
+
+  void get isClass {
+    kind.isIdentifier;
+    element.isNotNull.kind.isClass;
+  }
+
+  void get isConstructorInvocation {
+    kind.isInvocation;
+    element.isNotNull.kind.isConstructor;
+  }
+
+  void get isField {
+    kind.isIdentifier;
+    element.isNotNull.kind.isField;
+  }
+
+  void get isFunctionReference {
+    kind.isIdentifier;
+    element.isNotNull.kind.isFunction;
+  }
+
+  void get isGetter {
+    kind.isIdentifier;
+    element.isNotNull.kind.isGetter;
+  }
+
+  void get isMethodInvocation {
+    kind.isInvocation;
+    element.isNotNull.kind.isMethod;
+  }
+
+  @useResult
+  CheckTarget<bool?> get isNotImported {
+    return nest(
+      value.suggestion.isNotImported,
+      (selected) => 'has isNotImported ${valueStr(selected)}',
+    );
+  }
+
+  void get isParameter {
+    kind.isIdentifier;
+    element.isNotNull.kind.isParameter;
+  }
+
+  void get isSetter {
+    kind.isIdentifier;
+    element.isNotNull.kind.isSetter;
+  }
+
+  void get isTopLevelVariable {
+    kind.isIdentifier;
+    element.isNotNull.kind.isTopLevelVariable;
+  }
+
+  @useResult
+  CheckTarget<CompletionSuggestionKind> get kind {
+    return nest(
+      value.suggestion.kind,
+      (selected) => 'has kind ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get libraryUriToImport {
+    return nest(
+      value.suggestion.isNotImported == true
+          ? value.suggestion.element?.libraryUri
+          : null,
+      (selected) => 'has libraryUriToImport ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get parameterType {
+    return nest(
+      value.suggestion.parameterType,
+      (selected) => 'has parameterType ${valueStr(selected)}',
+    );
+  }
+
+  /// Return the effective replacement length.
+  @useResult
+  CheckTarget<int> get replacementLength {
+    return nest(
+      value.replacementLength,
+      (selected) => 'has replacementLength ${valueStr(selected)}',
+    );
+  }
+
+  /// Return the effective replacement offset.
+  @useResult
+  CheckTarget<int> get replacementOffset {
+    return nest(
+      value.replacementOffset,
+      (selected) => 'has replacementOffset ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String?> get returnType {
+    return nest(
+      value.suggestion.returnType,
+      (selected) => 'has returnType ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<int> get selectionLength {
+    return nest(
+      value.suggestion.selectionLength,
+      (selected) => 'has selectionLength ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<int> get selectionOffset {
+    return nest(
+      value.suggestion.selectionOffset,
+      (selected) => 'has selectionOffset ${valueStr(selected)}',
+    );
+  }
+
+  /// Check that the effective replacement offset is the completion request
+  /// offset, and the length of the replacement is zero.
+  void hasEmptyReplacement() {
+    hasReplacement(left: 0, right: 0);
+  }
+
+  /// Check that the effective replacement offset is the completion request
+  /// offset minus [left], and the length of the replacement is `left + right`.
+  void hasReplacement({int left = 0, int right = 0}) {
+    replacementOffset.isEqualTo(value.response.requestOffset - left);
+    replacementLength.isEqualTo(left + right);
+  }
+
+  void hasSelection({required int offset, int length = 0}) {
+    selectionOffset.isEqualTo(offset);
+    selectionLength.isEqualTo(length);
+  }
+}
+
+extension CompletionSuggestionKindExtension
+    on CheckTarget<CompletionSuggestionKind> {
+  void get isIdentifier {
+    isEqualTo(CompletionSuggestionKind.IDENTIFIER);
+  }
+
+  void get isInvocation {
+    isEqualTo(CompletionSuggestionKind.INVOCATION);
+  }
+}
+
+extension CompletionSuggestionsExtension
+    on CheckTarget<Iterable<CompletionSuggestionForTesting>> {
+  @useResult
+  CheckTarget<List<String>> get completions {
+    return nest(
+      value.map((e) => e.suggestion.completion).toList(),
+      (selected) => 'completions ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<Iterable<CompletionSuggestionForTesting>> get namedArguments {
+    var result = value
+        .where((suggestion) =>
+            suggestion.suggestion.kind ==
+            CompletionSuggestionKind.NAMED_ARGUMENT)
+        .toList();
+    return nest(
+      result,
+      (selected) => 'named arguments ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<Iterable<CompletionSuggestionForTesting>> get withElementClass {
+    return nest(
+      value.where((e) {
+        return e.suggestion.element?.kind == ElementKind.CLASS;
+      }).toList(),
+      (selected) => 'withElementClass ${valueStr(selected)}',
+    );
+  }
+}
+
+extension ElementExtension on CheckTarget<Element> {
+  @useResult
+  CheckTarget<ElementKind> get kind {
+    return nest(
+      value.kind,
+      (selected) => 'has kind ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
+  CheckTarget<String> get name {
+    return nest(
+      value.name,
+      (selected) => 'has name ${valueStr(selected)}',
+    );
+  }
+}
+
+extension ElementKindExtension on CheckTarget<ElementKind> {
+  void get isClass {
+    isEqualTo(ElementKind.CLASS);
+  }
+
+  void get isConstructor {
+    isEqualTo(ElementKind.CONSTRUCTOR);
+  }
+
+  void get isField {
+    isEqualTo(ElementKind.FIELD);
+  }
+
+  void get isFunction {
+    isEqualTo(ElementKind.FUNCTION);
+  }
+
+  void get isGetter {
+    isEqualTo(ElementKind.GETTER);
+  }
+
+  void get isMethod {
+    isEqualTo(ElementKind.METHOD);
+  }
+
+  void get isParameter {
+    isEqualTo(ElementKind.PARAMETER);
+  }
+
+  void get isSetter {
+    isEqualTo(ElementKind.SETTER);
+  }
+
+  void get isTopLevelVariable {
+    isEqualTo(ElementKind.TOP_LEVEL_VARIABLE);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 0485895..f721cc8 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -17,6 +17,7 @@
 import 'package:test/test.dart';
 
 import '../../../abstract_context.dart';
+import 'completion_check.dart';
 
 SuggestionMatcher suggestionHas(
         {required String completion,
@@ -118,30 +119,34 @@
   }
 
   void assertCoreTypeSuggestions() {
-    assertSuggest('Comparable');
-    assertSuggest('Comparator');
-    assertSuggest('DateTime');
-    assertSuggest('Deprecated');
-    assertSuggest('Duration');
-    assertSuggest('Error');
-    assertSuggest('Exception');
-    assertSuggest('FormatException');
-    assertSuggest('Function');
-    assertSuggest('Future');
-    assertSuggest('Invocation');
-    assertSuggest('Iterable');
-    assertSuggest('Iterator');
-    assertSuggest('List');
-    assertSuggest('Map');
-    assertSuggest('MapEntry');
-    assertSuggest('Null');
-    assertSuggest('Object');
-    assertSuggest('Pattern');
-    assertSuggest('RegExp');
-    assertSuggest('Set');
-    assertSuggest('StackTrace');
-    assertSuggest('Stream');
-    assertSuggest('String');
+    assertSuggestClass('Comparable');
+    assertSuggestTypeAlias(
+      'Comparator',
+      aliasedType: 'int Function(T, T)',
+      returnType: 'int',
+    );
+    assertSuggestClass('DateTime');
+    assertSuggestClass('Deprecated');
+    assertSuggestClass('Duration');
+    assertSuggestClass('Error');
+    assertSuggestClass('Exception');
+    assertSuggestClass('FormatException');
+    assertSuggestClass('Function');
+    assertSuggestClass('Future');
+    assertSuggestClass('Invocation');
+    assertSuggestClass('Iterable');
+    assertSuggestClass('Iterator');
+    assertSuggestClass('List');
+    assertSuggestClass('Map');
+    assertSuggestClass('MapEntry');
+    assertSuggestClass('Null');
+    assertSuggestClass('Object');
+    assertSuggestClass('Pattern');
+    assertSuggestClass('RegExp');
+    assertSuggestClass('Set');
+    assertSuggestClass('StackTrace');
+    assertSuggestClass('Stream');
+    assertSuggestClass('String');
   }
 
   void assertHasNoParameterInfo(CompletionSuggestion suggestion) {
@@ -242,7 +247,7 @@
   }
 
   CompletionSuggestion assertSuggestClass(String name,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
+      {CompletionSuggestionKind kind = CompletionSuggestionKind.IDENTIFIER,
       bool isDeprecated = false,
       String? elemFile,
       String? elemName,
@@ -263,7 +268,7 @@
   }
 
   CompletionSuggestion assertSuggestClassTypeAlias(String name,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
+      {CompletionSuggestionKind kind = CompletionSuggestionKind.IDENTIFIER}) {
     var cs = assertSuggest(name, csKind: kind);
     var element = cs.element!;
     expect(element.kind, equals(ElementKind.CLASS_TYPE_ALIAS));
@@ -293,7 +298,11 @@
 
   CompletionSuggestion assertSuggestEnum(String completion,
       {bool isDeprecated = false}) {
-    var suggestion = assertSuggest(completion, isDeprecated: isDeprecated);
+    var suggestion = assertSuggest(
+      completion,
+      isDeprecated: isDeprecated,
+      csKind: CompletionSuggestionKind.IDENTIFIER,
+    );
     expect(suggestion.isDeprecated, isDeprecated);
     expect(suggestion.element!.kind, ElementKind.ENUM);
     return suggestion;
@@ -301,7 +310,11 @@
 
   CompletionSuggestion assertSuggestEnumConst(String completion,
       {bool isDeprecated = false}) {
-    var suggestion = assertSuggest(completion, isDeprecated: isDeprecated);
+    var suggestion = assertSuggest(
+      completion,
+      csKind: CompletionSuggestionKind.IDENTIFIER,
+      isDeprecated: isDeprecated,
+    );
     expect(suggestion.completion, completion);
     expect(suggestion.isDeprecated, isDeprecated);
     expect(suggestion.element!.kind, ElementKind.ENUM_CONSTANT);
@@ -309,10 +322,11 @@
   }
 
   CompletionSuggestion assertSuggestField(String name, String? type,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      bool isDeprecated = false}) {
+      {bool isDeprecated = false}) {
     var cs = assertSuggest(name,
-        csKind: kind, elemKind: ElementKind.FIELD, isDeprecated: isDeprecated);
+        csKind: CompletionSuggestionKind.IDENTIFIER,
+        elemKind: ElementKind.FIELD,
+        isDeprecated: isDeprecated);
     // The returnType represents the type of a field
     expect(cs.returnType, type ?? 'dynamic');
     var element = cs.element!;
@@ -357,10 +371,13 @@
   }
 
   CompletionSuggestion assertSuggestGetter(String name, String? returnType,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-      bool isDeprecated = false}) {
-    var cs = assertSuggest(name,
-        csKind: kind, elemKind: ElementKind.GETTER, isDeprecated: isDeprecated);
+      {bool isDeprecated = false}) {
+    var cs = assertSuggest(
+      name,
+      csKind: CompletionSuggestionKind.IDENTIFIER,
+      elemKind: ElementKind.GETTER,
+      isDeprecated: isDeprecated,
+    );
     expect(cs.returnType, returnType ?? 'dynamic');
     var element = cs.element!;
     expect(element.kind, equals(ElementKind.GETTER));
@@ -374,7 +391,7 @@
   CompletionSuggestion assertSuggestLocalVariable(
       String name, String? returnType) {
     // Local variables should only be suggested by LocalReferenceContributor
-    var cs = assertSuggest(name, csKind: CompletionSuggestionKind.INVOCATION);
+    var cs = assertSuggest(name, csKind: CompletionSuggestionKind.IDENTIFIER);
     expect(cs.returnType, returnType ?? 'dynamic');
     var element = cs.element!;
     expect(element.kind, equals(ElementKind.LOCAL_VARIABLE));
@@ -412,7 +429,7 @@
   }
 
   CompletionSuggestion assertSuggestMixin(String name,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
+      {CompletionSuggestionKind kind = CompletionSuggestionKind.IDENTIFIER,
       bool isDeprecated = false,
       String? elemFile,
       String? elemName,
@@ -443,7 +460,7 @@
   }
 
   CompletionSuggestion assertSuggestParameter(String name, String? returnType) {
-    var cs = assertSuggest(name, csKind: CompletionSuggestionKind.INVOCATION);
+    var cs = assertSuggest(name, csKind: CompletionSuggestionKind.IDENTIFIER);
     expect(cs.returnType, returnType ?? 'dynamic');
     var element = cs.element!;
     expect(element.kind, equals(ElementKind.PARAMETER));
@@ -453,9 +470,12 @@
     return cs;
   }
 
-  CompletionSuggestion assertSuggestSetter(String name,
-      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
-    var cs = assertSuggest(name, csKind: kind, elemKind: ElementKind.SETTER);
+  CompletionSuggestion assertSuggestSetter(String name) {
+    var cs = assertSuggest(
+      name,
+      csKind: CompletionSuggestionKind.IDENTIFIER,
+      elemKind: ElementKind.SETTER,
+    );
     var element = cs.element!;
     expect(element.kind, equals(ElementKind.SETTER));
     expect(element.name, equals(name));
@@ -470,11 +490,8 @@
   }
 
   CompletionSuggestion assertSuggestTopLevelVar(
-    String name,
-    String? returnType, {
-    CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
-  }) {
-    var cs = assertSuggest(name, csKind: kind);
+      String name, String? returnType) {
+    var cs = assertSuggest(name, csKind: CompletionSuggestionKind.IDENTIFIER);
     if (returnType != null) {
       expect(cs.returnType, returnType);
     } else if (isNullExpectedReturnTypeConsideredDynamic) {
@@ -498,7 +515,7 @@
     String? aliasedType,
     String? returnType,
     bool isDeprecated = false,
-    CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
+    CompletionSuggestionKind kind = CompletionSuggestionKind.IDENTIFIER,
   }) {
     var cs = assertSuggest(name, csKind: kind, isDeprecated: isDeprecated);
     if (returnType != null) {
@@ -559,6 +576,17 @@
     expect(suggestions, isNotNull, reason: 'expected suggestions');
   }
 
+  Future<CompletionResponseForTesting> computeSuggestions2() async {
+    await computeSuggestions();
+    return CompletionResponseForTesting(
+      requestOffset: completionOffset,
+      replacementOffset: replacementOffset,
+      replacementLength: replacementLength,
+      isIncomplete: false,
+      suggestions: suggestions,
+    );
+  }
+
   Never failedCompletion(String message,
       [Iterable<CompletionSuggestion>? completions]) {
     var sb = StringBuffer(message);
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
new file mode 100644
index 0000000..842ac90
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(EnumTest1);
+    defineReflectiveTests(EnumTest2);
+  });
+}
+
+@reflectiveTest
+class EnumTest1 extends AbstractCompletionDriverTest with EnumTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class EnumTest2 extends AbstractCompletionDriverTest with EnumTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin EnumTestCases on AbstractCompletionDriverTest {
+  @override
+  bool get supportsAvailableSuggestions => true;
+
+  Future<void> test_unprefixed_imported() async {
+    await addProjectFile('lib/a.dart', r'''
+enum MyEnum { v }
+''');
+
+    var response = await getTestCodeSuggestions('''
+import 'a.dart';
+
+void f() {
+  ^
+}
+''');
+
+    _checkUnprefixed(response);
+  }
+
+  Future<void> test_unprefixed_local() async {
+    var response = await getTestCodeSuggestions('''
+enum MyEnum { v }
+
+void f() {
+  ^
+}
+''');
+
+    _checkUnprefixed(response);
+  }
+
+  Future<void> test_unprefixed_notImported() async {
+    await addProjectFile('lib/a.dart', r'''
+enum MyEnum { v }
+''');
+
+    var response = await getTestCodeSuggestions('''
+void f() {
+  ^
+}
+''');
+
+    _checkUnprefixed(response);
+  }
+
+  void _checkUnprefixed(CompletionResponseForTesting response) {
+    check(response).suggestions
+      ..includesAll([
+        (suggestion) => suggestion.completion.isEqualTo('MyEnum.v'),
+      ])
+      ..excludesAll([
+        (suggestion) => suggestion
+          ..completion.startsWith('MyEnum')
+          ..isConstructorInvocation,
+      ]);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart b/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart
new file mode 100644
index 0000000..b1de9ef
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/test_all.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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 'enum_test.dart' as enum_;
+
+/// Tests suggestions produced for various kinds of declarations.
+void main() {
+  defineReflectiveSuite(() {
+    enum_.main();
+  });
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index ff209f1..d63a695 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -6,9 +6,10 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:test/test.dart';
+import 'package:analyzer_utilities/check/check.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'completion_check.dart';
 import 'completion_contributor_util.dart';
 
 void main() {
@@ -31,183 +32,120 @@
   Future<void> test_mixin_constructor() async {
     addTestSource('''
 mixin M {
+  var field = 0;
   M(this.^);
 }
 ''');
-    await computeSuggestions();
-    expect(suggestions, isEmpty);
+
+    var response = await computeSuggestions2();
+    check(response).suggestions.isEmpty;
   }
 
-  Future<void> test_ThisExpression_constructor_param() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+  Future<void> test_replacement_left() async {
     addTestSource('''
-        main() { }
-        class I {X get f => new A();get _g => new A();}
-        class A implements I {
-          A(this.^) {}
-          A.z() {}
-          var b; X _c; static sb;
-          X get d => new A();get _e => new A();
-          // no semicolon between completion point and next statement
-          set s1(I x) {} set _s2(I x) {m(null);}
-          m(X x) {} I _n(X x) {}}
-        class X{}''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset);
-    expect(replacementLength, 0);
-    assertSuggestField('b', null);
-    assertSuggestField('_c', 'X');
-    assertNotSuggested('sb');
-    assertNotSuggested('d');
-    assertNotSuggested('_e');
-    assertNotSuggested('f');
-    assertNotSuggested('_g');
-    assertNotSuggested('m');
-    assertNotSuggested('_n');
-    assertNotSuggested('s1');
-    assertNotSuggested('_s2');
-    assertNotSuggested('z');
-    assertNotSuggested('I');
-    assertNotSuggested('A');
-    assertNotSuggested('X');
-    assertNotSuggested('Object');
-    assertNotSuggested('==');
+class A {
+  var field = 0;
+  A(this.f^);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasReplacement(left: 1)
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('field')
+          ..isField
+          ..returnType.isEqualTo('int'),
+      ]);
   }
 
-  Future<void> test_ThisExpression_constructor_param2() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+  Future<void> test_replacement_right() async {
     addTestSource('''
-        main() { }
-        class I {X get f => new A();get _g => new A();}
-        class A implements I {
-          A(this.b^) {}
-          A.z() {}
-          var b; X _c;
-          X get d => new A();get _e => new A();
-          // no semicolon between completion point and next statement
-          set s1(I x) {} set _s2(I x) {m(null);}
-          m(X x) {} I _n(X x) {}}
-        class X{}''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset - 1);
-    expect(replacementLength, 1);
-    assertSuggestField('b', null);
-    assertSuggestField('_c', 'X');
-    assertNotSuggested('d');
-    assertNotSuggested('_e');
-    assertNotSuggested('f');
-    assertNotSuggested('_g');
-    assertNotSuggested('m');
-    assertNotSuggested('_n');
-    assertNotSuggested('s1');
-    assertNotSuggested('_s2');
-    assertNotSuggested('z');
-    assertNotSuggested('I');
-    assertNotSuggested('A');
-    assertNotSuggested('X');
-    assertNotSuggested('Object');
-    assertNotSuggested('==');
+class A {
+  var field = 0;
+  A(this.^f);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasReplacement(right: 1)
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('field')
+          ..isField
+          ..returnType.isEqualTo('int'),
+      ]);
   }
 
-  Future<void> test_ThisExpression_constructor_param3() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+  Future<void> test_suggestions_onlyLocal() async {
     addTestSource('''
-        main() { }
-        class I {X get f => new A();get _g => new A();}
-        class A implements I {
-          A(this.^b) {}
-          A.z() {}
-          var b; X _c;
-          X get d => new A();get _e => new A();
-          // no semicolon between completion point and next statement
-          set s1(I x) {} set _s2(I x) {m(null);}
-          m(X x) {} I _n(X x) {}}
-        class X{}''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset);
-    expect(replacementLength, 1);
-    assertSuggestField('b', null);
-    assertSuggestField('_c', 'X');
-    assertNotSuggested('d');
-    assertNotSuggested('_e');
-    assertNotSuggested('f');
-    assertNotSuggested('_g');
-    assertNotSuggested('m');
-    assertNotSuggested('_n');
-    assertNotSuggested('s1');
-    assertNotSuggested('_s2');
-    assertNotSuggested('z');
-    assertNotSuggested('I');
-    assertNotSuggested('A');
-    assertNotSuggested('X');
-    assertNotSuggested('Object');
-    assertNotSuggested('==');
+class A {
+  var inherited = 0;
+}
+
+class B extends A {
+  var first = 0;
+  var second = 1.2;
+  B(this.^);
+  B.constructor() {}
+  void method() {}
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isField
+          ..returnType.isEqualTo('int'),
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isField
+          ..returnType.isEqualTo('double'),
+      ]);
   }
 
-  Future<void> test_ThisExpression_constructor_param4() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+  Future<void> test_suggestions_onlyNotSpecified_optionalNamed() async {
     addTestSource('''
-        main() { }
-        class I {X get f => new A();get _g => new A();}
-        class A implements I {
-          A(this.b, this.^) {}
-          A.z() {}
-          var b; X _c;
-          X get d => new A();get _e => new A();
-          // no semicolon between completion point and next statement
-          set s1(I x) {} set _s2(I x) {m(null);}
-          m(X x) {} I _n(X x) {}}
-        class X{}''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset);
-    expect(replacementLength, 0);
-    assertNotSuggested('b');
-    assertSuggestField('_c', 'X');
-    assertNotSuggested('d');
-    assertNotSuggested('_e');
-    assertNotSuggested('f');
-    assertNotSuggested('_g');
-    assertNotSuggested('m');
-    assertNotSuggested('_n');
-    assertNotSuggested('s1');
-    assertNotSuggested('_s2');
-    assertNotSuggested('z');
-    assertNotSuggested('I');
-    assertNotSuggested('A');
-    assertNotSuggested('X');
-    assertNotSuggested('Object');
-    assertNotSuggested('==');
+class Point {
+  final int x;
+  final int y;
+  Point({this.x, this.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('y')
+          ..isField
+          ..returnType.isEqualTo('int'),
+      ]);
   }
 
-  Future<void> test_ThisExpression_constructor_param_optional() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
+  Future<void> test_suggestions_onlyNotSpecified_requiredPositional() async {
     addTestSource('''
-        main() { }
-        class Point {
-          int x;
-          int y;
-          Point({this.x, this.^}) {}
-          ''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset);
-    expect(replacementLength, 0);
-    assertSuggestField('y', 'int');
-    assertNotSuggested('x');
-  }
+class Point {
+  final int x;
+  final int y;
+  Point(this.x, this.^);
+}
+''');
 
-  Future<void> test_ThisExpression_constructor_param_positional() async {
-    // SimpleIdentifier  FieldFormalParameter  FormalParameterList
-    addTestSource('''
-        main() { }
-        class Point {
-          int x;
-          int y;
-          Point({this.x, this.^}) {}
-          ''');
-    await computeSuggestions();
-    expect(replacementOffset, completionOffset);
-    expect(replacementLength, 0);
-    assertSuggestField('y', 'int');
-    assertNotSuggested('x');
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('y')
+          ..isField
+          ..returnType.isEqualTo('int'),
+      ]);
   }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 585012d..c2c05ab 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -74,6 +74,17 @@
     var keywords = <Keyword>[
       Keyword.COVARIANT,
       Keyword.DYNAMIC,
+      Keyword.SUPER,
+      Keyword.THIS,
+      Keyword.VOID
+    ];
+    return keywords;
+  }
+
+  List<Keyword> get constructorParameter_language215 {
+    var keywords = <Keyword>[
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
       Keyword.THIS,
       Keyword.VOID
     ];
@@ -1018,6 +1029,17 @@
     assertSuggestKeywords(constructorParameter);
   }
 
+  Future<void> test_constructor_param_noPrefix_language215() async {
+    addTestSource(r'''
+// @dart = 2.15
+class A {
+  A(^);
+}
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(constructorParameter_language215);
+  }
+
   Future<void> test_constructor_param_prefix() async {
     addTestSource('class A { A(t^) {}}');
     await computeSuggestions();
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 804bc3a..c463ed9 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
@@ -773,7 +773,7 @@
     expect(replacementLength, 0);
     assertSuggest('a', elemKind: ElementKind.METHOD);
     assertSuggest('foo', elemKind: ElementKind.METHOD);
-    assertSuggest('B', elemKind: ElementKind.CLASS);
+    assertSuggestClass('B');
     assertNotSuggested('A');
     assertNotSuggested('Object');
     assertSuggestMethod('y', 'A', 'Future<dynamic>');
@@ -1307,12 +1307,12 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggest('e1', elemKind: ElementKind.FIELD);
-    assertSuggest('f1', elemKind: ElementKind.FIELD);
-    assertSuggest('i1', elemKind: ElementKind.FIELD);
-    assertSuggest('m1', elemKind: ElementKind.FIELD);
-    assertSuggest('f3', elemKind: ElementKind.GETTER);
-    assertSuggest('f4', elemKind: ElementKind.SETTER);
+    assertSuggestField('e1', null);
+    assertSuggestField('f1', null);
+    assertSuggestField('i1', 'int');
+    assertSuggestField('m1', null);
+    assertSuggestGetter('f3', null);
+    assertSuggestSetter('f4');
     assertSuggest('e2', elemKind: ElementKind.METHOD);
     assertSuggest('f2', elemKind: ElementKind.METHOD);
     assertSuggest('i2', elemKind: ElementKind.METHOD);
@@ -1386,12 +1386,12 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggest('e1', elemKind: ElementKind.FIELD);
-    assertSuggest('f1', elemKind: ElementKind.FIELD);
-    assertSuggest('i1', elemKind: ElementKind.FIELD);
-    assertSuggest('m1', elemKind: ElementKind.FIELD);
-    assertSuggest('f3', elemKind: ElementKind.GETTER);
-    assertSuggest('f4', elemKind: ElementKind.SETTER);
+    assertSuggestField('e1', null);
+    assertSuggestField('f1', null);
+    assertSuggestField('i1', 'int');
+    assertSuggestField('m1', null);
+    assertSuggestGetter('f3', null);
+    assertSuggestSetter('f4');
     assertSuggest('e2', elemKind: ElementKind.METHOD);
     assertSuggest('f2', elemKind: ElementKind.METHOD);
     assertSuggest('i2', elemKind: ElementKind.METHOD);
@@ -2446,7 +2446,7 @@
 ''');
     await computeSuggestions();
 
-    assertSuggest('E', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('E', 'int');
 
     // Enum and all its constants are shadowed by the local variable.
     assertNotSuggested('E', elemKind: ElementKind.ENUM);
@@ -2706,7 +2706,7 @@
     await computeSuggestions();
 
     assertNotSuggested('E', elemKind: ElementKind.EXTENSION);
-    assertSuggest('E', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('E', 'int');
   }
 
   Future<void> test_ExtensionDeclaration_unnamed() async {
@@ -2758,7 +2758,7 @@
     await computeSuggestions();
 
     assertNotSuggested('foo', elemKind: ElementKind.FIELD);
-    assertSuggest('foo', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('foo', 'int');
   }
 
   Future<void> test_FieldFormalParameter_in_non_constructor() async {
@@ -3335,7 +3335,7 @@
     await computeSuggestions();
 
     assertNotSuggested('bar', elemKind: ElementKind.FUNCTION);
-    assertSuggest('bar', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('bar', 'int');
   }
 
   Future<void> test_functionDeclaration_typeParameterBounds() async {
@@ -3638,7 +3638,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertNotSuggested('Object');
-    assertSuggest('B', elemKind: ElementKind.CLASS);
+    assertSuggestClass('B');
     assertSuggestField('a', 'int');
     assertSuggestMethod('b', 'B', 'int');
     assertSuggestMethod('foo', 'B', 'dynamic');
@@ -4196,7 +4196,7 @@
 ''');
     await computeSuggestions();
 
-    assertSuggest('A');
+    assertSuggestLocalVariable('A', 'int');
 
     // Class and all its constructors are shadowed by the local variable.
     assertNotSuggested('A', elemKind: ElementKind.CLASS);
@@ -4919,7 +4919,7 @@
     await computeSuggestions();
 
     assertNotSuggested('foo', elemKind: ElementKind.METHOD);
-    assertSuggest('foo', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('foo', 'dynamic');
   }
 
   Future<void> test_MethodDeclaration_shadowed2() async {
@@ -4940,7 +4940,7 @@
     await computeSuggestions();
 
     assertNotSuggested('foo', elemKind: ElementKind.METHOD);
-    assertSuggest('foo', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('foo', 'dynamic');
   }
 
   Future<void> test_methodDeclaration_typeParameterBounds() async {
@@ -5099,7 +5099,29 @@
     await computeSuggestions();
 
     assertNotSuggested('foo', elemKind: ElementKind.MIXIN);
-    assertSuggest('foo', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('foo', 'int');
+  }
+
+  Future<void>
+      test_namedArgument_instanceCreation_x_localFunction_void() async {
+    addTestSource('''
+class A {
+  A({required void Function() a});
+}
+
+class B {
+  void bar() {
+    void foo01() {}
+    A(a: foo0^);
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestFunction(
+      'foo01',
+      'void',
+      kind: CompletionSuggestionKind.IDENTIFIER,
+    );
   }
 
   Future<void> test_new_instance() async {
@@ -5248,7 +5270,7 @@
     await computeSuggestions();
 
     assertNotSuggested('bar', elemKind: ElementKind.PARAMETER);
-    assertSuggest('bar', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('bar', 'int');
   }
 
   Future<void> test_PrefixedIdentifier_class_const() async {
@@ -6049,7 +6071,7 @@
     await computeSuggestions();
 
     assertNotSuggested('foo', elemKind: ElementKind.TOP_LEVEL_VARIABLE);
-    assertSuggest('foo', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('foo', 'dynamic');
   }
 
   Future<void> test_TopLevelVariableDeclaration_typed_name() async {
@@ -6192,7 +6214,7 @@
 ''');
     await computeSuggestions();
     assertNotSuggested('T', elemKind: ElementKind.TYPE_PARAMETER);
-    assertSuggest('T', elemKind: ElementKind.LOCAL_VARIABLE);
+    assertSuggestLocalVariable('T', 'int');
   }
 
   Future<void> test_VariableDeclaration_name() async {
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 0e65414..df03716 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
@@ -42,6 +42,56 @@
     _assertNoOverrideContaining('bar');
   }
 
+  Future<void> test_beforeGetter() async {
+    addTestSource('''
+class A {
+  method() {}
+  int? age;
+}
+
+class B extends A {
+  m^
+
+  String value1 = '';
+}
+''');
+    await computeSuggestions();
+    _assertOverride('''
+@override
+  method() {
+    // TODO: implement method
+    return super.method();
+  }''',
+        displayText: 'method() { … }',
+        selectionOffset: 57,
+        selectionLength: 22);
+  }
+
+  Future<void> test_beforeMethod() async {
+    addTestSource('''
+class A {
+  method() {}
+  int? age;
+}
+
+class B extends A {
+  m^
+
+  void b() {}
+}
+''');
+    await computeSuggestions();
+    _assertOverride('''
+@override
+  method() {
+    // TODO: implement method
+    return super.method();
+  }''',
+        displayText: 'method() { … }',
+        selectionOffset: 57,
+        selectionLength: 22);
+  }
+
   Future<void> test_customOperator() async {
     addTestSource('''
 class A {
@@ -386,12 +436,13 @@
 ''');
     await computeSuggestions();
     _assertOverride('''
-method() {
+@override
+  method() {
     // TODO: implement method
     return super.method();
   }''',
         displayText: 'method() { … }',
-        selectionOffset: 45,
+        selectionOffset: 57,
         selectionLength: 22);
   }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_test.dart
index 039c915..0254e45 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_test.dart
@@ -5,16 +5,50 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(BoolAssignmentTest);
+    defineReflectiveTests(BoolAssignmentTest1);
+    defineReflectiveTests(BoolAssignmentTest2);
   });
 }
 
 @reflectiveTest
-class BoolAssignmentTest extends CompletionRelevanceTest {
+class BoolAssignmentTest1 extends CompletionRelevanceTest
+    with BoolAssignmentTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class BoolAssignmentTest2 extends CompletionRelevanceTest
+    with BoolAssignmentTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+
+  @FailingTest(reason: r'''
+The actual relevances are:
+[completion: bool.fromEnvironment][relevance: 591]
+[completion: bool.hasEnvironment][relevance: 591]
+[completion: b][relevance: 587]
+[completion: bool][relevance: 578]
+[completion: true][relevance: 574]
+[completion: false][relevance: 572]
+[completion: identical][relevance: 563]
+  for (var e in result) {
+    print('[completion: ${e.completion}][relevance: ${e.relevance}]');
+  }
+''')
+  @override
+  Future<void> test_boolLiterals_imported() {
+    // TODO: implement test_boolLiterals_imported
+    return super.test_boolLiterals_imported();
+  }
+}
+
+mixin BoolAssignmentTestCases on CompletionRelevanceTest {
   Future<void> test_boolLiterals_imported() async {
     await addTestFile('''
 foo() {
@@ -54,7 +88,7 @@
     var bLocalVar = suggestionWith(
         completion: 'b',
         element: ElementKind.LOCAL_VARIABLE,
-        kind: CompletionSuggestionKind.INVOCATION);
+        kind: CompletionSuggestionKind.IDENTIFIER);
 
     assertOrder([bLocalVar, trueSuggestion, falseSuggestion]);
   }
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
index 81532df..f353b8d 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/completion_relevance.dart
@@ -7,7 +7,7 @@
 
 import '../../../../client/completion_driver_test.dart';
 
-class CompletionRelevanceTest extends AbstractCompletionDriverTest {
+abstract class CompletionRelevanceTest extends AbstractCompletionDriverTest {
   @override
   bool get supportsAvailableSuggestions => true;
 
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_test.dart
index 44d0f92..40826b7 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_test.dart
@@ -5,16 +5,31 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(DeprecatedMemberTest);
+    defineReflectiveTests(DeprecatedMemberTest1);
+    defineReflectiveTests(DeprecatedMemberTest2);
   });
 }
 
 @reflectiveTest
-class DeprecatedMemberTest extends CompletionRelevanceTest {
+class DeprecatedMemberTest1 extends CompletionRelevanceTest
+    with DeprecatedMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class DeprecatedMemberTest2 extends CompletionRelevanceTest
+    with DeprecatedMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin DeprecatedMemberTestCases on CompletionRelevanceTest {
   Future<void> test_deprecated() async {
     await addTestFile('''
 class A {
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
index de08d73..b6ad9fc 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/instance_member_test.dart
@@ -4,16 +4,31 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InstanceMemberTest);
+    defineReflectiveTests(InstanceMemberTest1);
+    defineReflectiveTests(InstanceMemberTest2);
   });
 }
 
 @reflectiveTest
-class InstanceMemberTest extends CompletionRelevanceTest {
+class InstanceMemberTest1 extends CompletionRelevanceTest
+    with InstanceMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class InstanceMemberTest2 extends CompletionRelevanceTest
+    with InstanceMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin InstanceMemberTestCases on CompletionRelevanceTest {
   @override
   bool get supportsAvailableSuggestions => true;
 
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/is_no_such_method_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/is_no_such_method_test.dart
index 388a377..0a02b82 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/is_no_such_method_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/is_no_such_method_test.dart
@@ -5,16 +5,31 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(IsNoSuchMethodTest);
+    defineReflectiveTests(IsNoSuchMethodTest1);
+    defineReflectiveTests(IsNoSuchMethodTest2);
   });
 }
 
 @reflectiveTest
-class IsNoSuchMethodTest extends CompletionRelevanceTest {
+class IsNoSuchMethodTest1 extends CompletionRelevanceTest
+    with IsNoSuchMethodTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class IsNoSuchMethodTest2 extends CompletionRelevanceTest
+    with IsNoSuchMethodTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin IsNoSuchMethodTestCases on CompletionRelevanceTest {
   Future<void> test_notSuper() async {
     await addTestFile('''
 void foo(Object o) {
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/local_variable_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/local_variable_test.dart
index c1481fb..c5a3d1a 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/local_variable_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/local_variable_test.dart
@@ -5,16 +5,31 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(LocalVariableTest);
+    defineReflectiveTests(LocalVariableTest1);
+    defineReflectiveTests(LocalVariableTest2);
   });
 }
 
 @reflectiveTest
-class LocalVariableTest extends CompletionRelevanceTest {
+class LocalVariableTest1 extends CompletionRelevanceTest
+    with LocalVariableTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class LocalVariableTest2 extends CompletionRelevanceTest
+    with LocalVariableTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin LocalVariableTestCases on CompletionRelevanceTest {
   Future<void> test_localVariables() async {
     await addTestFile('''
 int f() {
@@ -29,15 +44,15 @@
       suggestionWith(
           completion: 'c',
           element: ElementKind.LOCAL_VARIABLE,
-          kind: CompletionSuggestionKind.INVOCATION),
+          kind: CompletionSuggestionKind.IDENTIFIER),
       suggestionWith(
           completion: 'b',
           element: ElementKind.LOCAL_VARIABLE,
-          kind: CompletionSuggestionKind.INVOCATION),
+          kind: CompletionSuggestionKind.IDENTIFIER),
       suggestionWith(
           completion: 'a',
           element: ElementKind.LOCAL_VARIABLE,
-          kind: CompletionSuggestionKind.INVOCATION),
+          kind: CompletionSuggestionKind.IDENTIFIER),
     ]);
   }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
index beb0563..018a020 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_test.dart
@@ -4,21 +4,35 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import '../../../../src/utilities/mock_packages.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(NamedArgumentTest);
-    defineReflectiveTests(NamedArgumentWithNullSafetyTest);
+    defineReflectiveTests(NamedArgumentTest1);
+    defineReflectiveTests(NamedArgumentTest2);
   });
 }
 
 @reflectiveTest
-class NamedArgumentTest extends CompletionRelevanceTest {
+class NamedArgumentTest1 extends CompletionRelevanceTest
+    with NamedArgumentTestCases {
   @override
-  void setUp() {
-    super.setUp();
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class NamedArgumentTest2 extends CompletionRelevanceTest
+    with NamedArgumentTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin NamedArgumentTestCases on CompletionRelevanceTest {
+  @override
+  Future<void> setUp() async {
+    await super.setUp();
 
     var metaLibFolder = MockPackages.instance.addMeta(resourceProvider);
 
@@ -28,11 +42,9 @@
 ''');
   }
 
-  Future<void> test_requiredAnnotation() async {
+  Future<void> test_required() async {
     await addTestFile('''
-import 'package:meta/meta.dart';
-
-void f({int a, @required int b}) {}
+void f({int a = 0, required int b}) {}
 
 void g() => f(^);
 ''');
@@ -41,13 +53,12 @@
       suggestionWith(completion: 'a: '),
     ]);
   }
-}
 
-@reflectiveTest
-class NamedArgumentWithNullSafetyTest extends NamedArgumentTest {
-  Future<void> test_required() async {
+  Future<void> test_requiredAnnotation() async {
     await addTestFile('''
-void f({int a = 0, required int b}) {}
+import 'package:meta/meta.dart';
+
+void f({int a, @required int b}) {}
 
 void g() => f(^);
 ''');
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/non_type_member_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/non_type_member_test.dart
index 084c91c..c582a1c 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/non_type_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/non_type_member_test.dart
@@ -5,16 +5,31 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(NonTypeMemberTest);
+    defineReflectiveTests(NonTypeMemberTest1);
+    defineReflectiveTests(NonTypeMemberTest2);
   });
 }
 
 @reflectiveTest
-class NonTypeMemberTest extends CompletionRelevanceTest {
+class NonTypeMemberTest1 extends CompletionRelevanceTest
+    with NonTypeMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class NonTypeMemberTest2 extends CompletionRelevanceTest
+    with NonTypeMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin NonTypeMemberTestCases on CompletionRelevanceTest {
   Future<void> test_contextType_constructorInvocation_before_type() async {
     await addTestFile('''
 class StrWrap {
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/static_member_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/static_member_test.dart
index 314b1e0..a9e1de8 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/static_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/static_member_test.dart
@@ -4,16 +4,31 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../../client/completion_driver_test.dart';
 import 'completion_relevance.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(StaticMemberTest);
+    defineReflectiveTests(StaticMemberTest1);
+    defineReflectiveTests(StaticMemberTest2);
   });
 }
 
 @reflectiveTest
-class StaticMemberTest extends CompletionRelevanceTest {
+class StaticMemberTest1 extends CompletionRelevanceTest
+    with StaticMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class StaticMemberTest2 extends CompletionRelevanceTest
+    with StaticMemberTestCases {
+  @override
+  TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin StaticMemberTestCases on CompletionRelevanceTest {
   Future<void> test_contextType() async {
     await addTestFile(r'''
 class A {}
diff --git a/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
new file mode 100644
index 0000000..88d16b9
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
@@ -0,0 +1,471 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/dart/super_formal_contributor.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'completion_check.dart';
+import 'completion_contributor_util.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperFormalContributorTest);
+  });
+}
+
+@reflectiveTest
+class SuperFormalContributorTest extends DartCompletionContributorTest {
+  @override
+  DartCompletionContributor createContributor(
+    DartCompletionRequest request,
+    SuggestionBuilder builder,
+  ) {
+    return SuperFormalContributor(request, builder);
+  }
+
+  Future<void> test_explicit_optionalNamed_hasArgument_named() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({super.^}) : super(first: 0);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_explicit_optionalNamed_hasArgument_positional() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({super.^}) : super(0);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  /// It is an error, but the user already typed `super.`, so maybe do it.
+  Future<void> test_explicit_requiredPositional_hasArgument_positional() async {
+    addTestSource('''
+class A {
+  A(int first, double second);
+}
+
+class B extends A {
+  B(super.^) : super(0);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_explicitNamed_noOther() async {
+    addTestSource('''
+class A {
+  A.named(int first, double second);
+  A(int third)
+}
+
+class B extends A {
+  B(super.^) : super.named();
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasNamed_notSuper() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({int a, super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasNamed_notSuper2() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({int first, super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasNamed_super() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({super.first, super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasNamed_super2() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B({super.second, super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasPositional_notSuper() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B(int a, {super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_hasPositional_super() async {
+    addTestSource('''
+class A {
+  A({int first, double second});
+}
+
+class B extends A {
+  B(super.first, {super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalNamed_noOther() async {
+    addTestSource('''
+class A {
+  A(bool first, {int second, double third});
+}
+
+class B extends A {
+  B({super.^});
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+        (suggestion) => suggestion
+          ..completion.isEqualTo('third')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalPositional_hasPositional_notSuper() async {
+    addTestSource('''
+class A {
+  A([int first, double second]);
+}
+
+class B extends A {
+  B([int one, super.^]);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalPositional_hasPositional_super() async {
+    addTestSource('''
+class A {
+  A([int first, double second, bool third]);
+}
+
+class B extends A {
+  B([super.one, super.^]);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalPositional_hasPositional_super2() async {
+    addTestSource('''
+class A {
+  A([int first, double second, bool third]);
+}
+
+class B extends A {
+  B([super.second, super.^]);
+}
+''');
+
+    // It does not matter what is the name of the positional parameter.
+    // Here `super.second` consumes `int first`.
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_optionalPositional_noOther() async {
+    addTestSource('''
+class A {
+  A([int first, double second]);
+}
+
+class B extends A {
+  B(super.^);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_implicit_requiredPositional_hasPositional_notSuper() async {
+    addTestSource('''
+class A {
+  A(int first, double second);
+}
+
+class B extends A {
+  B(int one, super.^);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+
+  Future<void> test_implicit_requiredPositional_hasPositional_super() async {
+    addTestSource('''
+class A {
+  A(int first, double second, bool third);
+}
+
+class B extends A {
+  B(super.one, super.^);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_requiredPositional_hasPositional_super2() async {
+    addTestSource('''
+class A {
+  A(int first, double second, bool third);
+}
+
+class B extends A {
+  B(super.second, super.^);
+}
+''');
+
+    // It does not matter what is the name of the positional parameter.
+    // Here `super.second` consumes `int first`.
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('second')
+          ..isParameter
+          ..returnType.isEqualTo('double'),
+      ]);
+  }
+
+  Future<void> test_implicit_requiredPositional_noOther() async {
+    addTestSource('''
+class A {
+  A(int first, double second);
+  A.named(int third);
+}
+
+class B extends A {
+  B(super.^);
+}
+''');
+
+    var response = await computeSuggestions2();
+    check(response)
+      ..hasEmptyReplacement()
+      ..suggestions.matchesInAnyOrder([
+        (suggestion) => suggestion
+          ..completion.isEqualTo('first')
+          ..isParameter
+          ..returnType.isEqualTo('int'),
+      ]);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 4ed7cd0..0ed0678 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -8,6 +8,7 @@
 import 'closure_contributor_test.dart' as closure_contributor;
 import 'combinator_contributor_test.dart' as combinator_test;
 import 'completion_manager_test.dart' as completion_manager;
+import 'declaration/test_all.dart' as declaration;
 import 'extension_member_contributor_test.dart' as extension_member_contributor;
 import 'field_formal_contributor_test.dart' as field_formal_contributor_test;
 import 'imported_reference_contributor_test.dart' as imported_ref_test;
@@ -21,6 +22,7 @@
 import 'override_contributor_test.dart' as override_contributor_test;
 import 'relevance/test_all.dart' as relevance_tests;
 import 'static_member_contributor_test.dart' as static_contributor_test;
+import 'super_formal_contributor_test.dart' as super_formal_contributor;
 import 'type_member_contributor_test.dart' as type_member_contributor_test;
 import 'uri_contributor_test.dart' as uri_contributor_test;
 import 'variable_name_contributor_test.dart' as variable_name_contributor_test;
@@ -31,6 +33,7 @@
     closure_contributor.main();
     combinator_test.main();
     completion_manager.main();
+    declaration.main();
     extension_member_contributor.main();
     field_formal_contributor_test.main();
     imported_ref_test.main();
@@ -44,6 +47,7 @@
     override_contributor_test.main();
     relevance_tests.main();
     static_contributor_test.main();
+    super_formal_contributor.main();
     type_member_contributor_test.main();
     uri_contributor_test.main();
     variable_name_contributor_test.main();
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 5b42916..16a846e 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -565,6 +565,31 @@
 ''');
   }
 
+  Future<void> test_createChange_parameter_named_super() async {
+    await indexTestUnit('''
+class A {
+  A({required int test}); // 0
+}
+class B extends A {
+  B({required super.test});
+}
+''');
+    // configure refactoring
+    createRenameRefactoringAtString('test}); // 0');
+    expect(refactoring.refactoringName, 'Rename Parameter');
+    expect(refactoring.elementKindName, 'parameter');
+    refactoring.newName = 'newName';
+    // validate change
+    return assertSuccessfulRefactoring('''
+class A {
+  A({required int newName}); // 0
+}
+class B extends A {
+  B({required super.newName});
+}
+''');
+  }
+
   Future<void> test_createChange_parameter_named_updateHierarchy() async {
     await indexUnit('$testPackageLibPath/test2.dart', '''
 library test2;
@@ -654,6 +679,33 @@
 ''');
   }
 
+  Future<void> test_createChange_parameter_positional_super() async {
+    await indexTestUnit('''
+class A {
+  A(int test); // 0
+}
+class B extends A {
+  B(super.test);
+}
+''');
+
+    createRenameRefactoringAtString('test); // 0');
+    expect(refactoring.refactoringName, 'Rename Parameter');
+    expect(refactoring.elementKindName, 'parameter');
+    refactoring.newName = 'newName';
+
+    // The name of the super-formal parameter does not have to be the same.
+    // So, we don't rename it.
+    return assertSuccessfulRefactoring('''
+class A {
+  A(int newName); // 0
+}
+class B extends A {
+  B(super.test);
+}
+''');
+  }
+
   Future<void> test_oldName() async {
     await indexTestUnit('''
 void f() {
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 07feae1..43637ae 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -344,6 +344,36 @@
     assertHasOne(a, 'a');
   }
 
+  Future<void>
+      test_searchReferences_parameter_ofConstructor_super_named() async {
+    var code = '''
+class A {
+  A({required int a});
+}
+class B extends A {
+  B({required super.a}); // ref
+}
+''';
+    await resolveTestCode(code);
+
+    var element = findElement.unnamedConstructor('A').parameter('a');
+    var matches = await searchEngine.searchReferences(element);
+    expect(
+      matches,
+      unorderedEquals([
+        predicate((SearchMatch m) {
+          return m.kind == MatchKind.REFERENCE &&
+              identical(
+                m.element,
+                findElement.unnamedConstructor('B').superFormalParameter('a'),
+              ) &&
+              m.sourceRange.offset == code.indexOf('a}); // ref') &&
+              m.sourceRange.length == 1;
+        }),
+      ]),
+    );
+  }
+
   Future<void> test_searchTopLevelDeclarations() async {
     newFile('$testPackageLibPath/a.dart', content: '''
 class A {}
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
index 3b95fd5..477d52b 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
@@ -519,7 +519,7 @@
   "label": "MyAlias",
   "declaringLibraryUri": "package:test/a.dart",
   "element": {
-    "kind": "FUNCTION_TYPE_ALIAS",
+    "kind": "TYPE_ALIAS",
     "name": "MyAlias",
     "location": {
       "file": ${jsonOfPath(path)},
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 6172336..25d24d3 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -72,7 +72,7 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     projectPath = convertPath('/home');
     testFile = convertPath('/home/test/lib/test.dart');
@@ -82,7 +82,7 @@
 test:${toUri('/home/test/lib')}
 ''');
 
-    createProject();
+    await createProject();
     handler = server.handlers.whereType<CompletionDomainHandler>().single;
     _setCompletionSubscriptions([CompletionService.AVAILABLE_SUGGESTION_SETS]);
   }
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 24bd1c3..9c47432 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -78,7 +78,7 @@
     // Force the server to rebuild all contexts, as happens when the file watcher
     // fails on Windows.
     // https://github.com/dart-lang/sdk/issues/44650
-    server.contextManager.refresh();
+    await server.contextManager.refresh();
 
     // Give it time to process the newly scheduled files.
     await pumpEventQueue(times: 5000);
diff --git a/pkg/analysis_server/test/src/domains/flutter/base.dart b/pkg/analysis_server/test/src/domains/flutter/base.dart
index 0ab812c..50d2533 100644
--- a/pkg/analysis_server/test/src/domains/flutter/base.dart
+++ b/pkg/analysis_server/test/src/domains/flutter/base.dart
@@ -38,7 +38,7 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
     projectPath = convertPath('/home');
     testFile = convertPath('/home/test/lib/test.dart');
@@ -50,7 +50,7 @@
 
     _addFlutterPackage();
 
-    createProject();
+    await createProject();
     handler = server.handlers.whereType<FlutterDomainHandler>().single;
   }
 
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
index a7e6a4a..25c479b 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
@@ -65,9 +65,9 @@
   }
 
   @override
-  void setUp() {
+  Future<void> setUp() async {
     super.setUp();
-    createProject();
+    await createProject();
     flutterFolder = MockPackages.instance.addFlutter(resourceProvider);
   }
 
@@ -79,6 +79,9 @@
 analyzer:
   strong-mode: true
 ''');
+    await pumpEventQueue();
+    await server.onAnalysisComplete;
+
     var code = '''
 import 'package:flutter/widgets.dart';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart
index e9c868c..e4c955c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_field_formal_parameters_test.dart
@@ -19,7 +19,7 @@
   @override
   FixKind get kind => DartFixKind.ADD_FIELD_FORMAL_PARAMETERS;
 
-  Future<void> test_flutter() async {
+  Future<void> test_flutter_nullable() async {
     writeTestPackageConfig(
       flutter: true,
     );
@@ -30,22 +30,53 @@
 class MyWidget extends StatelessWidget {
   final int a;
   final int b;
-  final int c;
+  final int? c;
+  final int d;
 
   MyWidget({required Key key, required this.a}) : super(key: key);
 }
 ''');
-    // TODO(brianwilkerson) The result should include `required` for the new
-    //  parameters, but I'm omitting them to match the current behavior.
     await assertHasFix('''
 import 'package:flutter/widgets.dart';
 
 class MyWidget extends StatelessWidget {
   final int a;
   final int b;
-  final int c;
+  final int? c;
+  final int d;
 
-  MyWidget({required Key key, required this.a, this.b, this.c}) : super(key: key);
+  MyWidget({required Key key, required this.a, required this.b, this.c, required this.d}) : super(key: key);
+}
+''');
+  }
+
+  Future<void> test_flutter_potentiallyNullable() async {
+    writeTestPackageConfig(
+      flutter: true,
+    );
+
+    await resolveTestCode('''
+import 'package:flutter/widgets.dart';
+
+class MyWidget<T> extends StatelessWidget {
+  final int a;
+  final int b;
+  final T c;
+  final int d;
+
+  MyWidget({required Key key, required this.a}) : super(key: key);
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/widgets.dart';
+
+class MyWidget<T> extends StatelessWidget {
+  final int a;
+  final int b;
+  final T c;
+  final int d;
+
+  MyWidget({required Key key, required this.a, required this.b, required this.c, required this.d}) : super(key: key);
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_leading_newline_to_string_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_leading_newline_to_string_test.dart
new file mode 100644
index 0000000..81d9313
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_leading_newline_to_string_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddLeadingNewlineToStringBulkTest);
+    defineReflectiveTests(AddLeadingNewlineToStringTest);
+  });
+}
+
+@reflectiveTest
+class AddLeadingNewlineToStringBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.leading_newlines_in_multiline_strings;
+
+  Future<void> test_three_fixes() async {
+    await resolveTestCode('''
+var s1 = \'''{
+  "a": 1,
+  "b": 2
+}\''';
+
+var s2 = \'''{
+  "c": 3,
+  "d": 4
+}\''';
+
+var s3 = \'''{
+  "e": 5,
+  "f": 6
+}\''';
+''');
+    await assertHasFix('''
+var s1 = \'''
+{
+  "a": 1,
+  "b": 2
+}\''';
+
+var s2 = \'''
+{
+  "c": 3,
+  "d": 4
+}\''';
+
+var s3 = \'''
+{
+  "e": 5,
+  "f": 6
+}\''';
+''');
+  }
+}
+
+@reflectiveTest
+class AddLeadingNewlineToStringTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_LEADING_NEWLINE_TO_STRING;
+
+  @override
+  String get lintCode => LintNames.leading_newlines_in_multiline_strings;
+
+  Future<void> test_one_fix() async {
+    await resolveTestCode('''
+var s1 = \'''{
+  "a": 1,
+  "b": 2
+}\''';
+''');
+    await assertHasFix('''
+var s1 = \'''
+{
+  "a": 1,
+  "b": 2
+}\''';
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
index 87b75db..67f4e6c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
@@ -51,7 +51,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
     await assertHasFixWithFilter('''
@@ -72,7 +73,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
   }
@@ -86,7 +88,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
     await assertHasFixWithFilter('''
@@ -107,7 +110,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
   }
@@ -126,7 +130,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
     await assertHasFix('''
@@ -145,7 +150,8 @@
   static const E a = E._(0);
   static const E b = E._(1);
   static const E c = E._(2);
-  const E._(int x);
+  final int x;
+  const E._(this.x);
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart
index 3be8c02..b7e793b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_named_test.dart
@@ -29,11 +29,9 @@
   new A(1, b: 2, named: 3.0);
 }
 ''');
-    // TODO(brianwilkerson) The fix should make added named parameters be
-    //  `required`. I'm leaving it as is to match the current behavior.
     await assertHasFix('''
 class A {
-  A(int a, {int b = 0, double named}) {}
+  A(int a, {int b = 0, required double named}) {}
 }
 
 main() {
@@ -54,7 +52,7 @@
 ''');
     await assertHasFix('''
 class A {
-  A(int a, {double named}) {}
+  A(int a, {required double named}) {}
 }
 
 main() {
@@ -75,7 +73,7 @@
 ''');
     await assertHasFix('''
 class A {
-  A({int named}) {}
+  A({required int named}) {}
 }
 
 main() {
@@ -96,7 +94,7 @@
 ''');
     await assertHasFix('''
 class A {
-  A.aaa({int named}) {}
+  A.aaa({required int named}) {}
 }
 
 main() {
@@ -114,7 +112,7 @@
 }
 ''');
     await assertHasFix('''
-test(int a, {int b: 0, double named}) {}
+test(int a, {int b: 0, required double named}) {}
 
 main() {
   test(1, b: 2, named: 3.0);
@@ -131,7 +129,7 @@
 }
 ''');
     await assertHasFix('''
-test(int a, {double named}) {}
+test(int a, {required double named}) {}
 
 main() {
   test(1, named: 2.0);
@@ -148,7 +146,7 @@
 }
 ''');
     await assertHasFix('''
-test({int named}) {}
+test({required int named}) {}
 
 main() {
   test(named: 42);
@@ -168,7 +166,7 @@
 ''');
     await assertHasFix('''
 class A {
-  test(int a, {int b: 0, double named}) {}
+  test(int a, {int b: 0, required double named}) {}
 
   main() {
     test(1, b: 2, named: 3.0);
@@ -202,7 +200,7 @@
 ''');
     await assertHasFix('''
 class A {
-  test(int a, {double named}) {}
+  test(int a, {required double named}) {}
 
   main() {
     test(1, named: 2.0);
@@ -223,7 +221,7 @@
 ''');
     await assertHasFix('''
 class A {
-  test({int named}) {}
+  test({required int named}) {}
 
   main() {
     test(named: 42);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
index ce129cc..42c321b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
@@ -11,11 +11,25 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AddSuperConstructorInvocationTest);
+    defineReflectiveTests(AddSuperConstructorInvocationTest_language215);
   });
 }
 
 @reflectiveTest
-class AddSuperConstructorInvocationTest extends FixProcessorTest {
+class AddSuperConstructorInvocationTest extends FixProcessorTest
+    with AddSuperConstructorInvocationTestCases {}
+
+@reflectiveTest
+class AddSuperConstructorInvocationTest_language215 extends FixProcessorTest
+    with AddSuperConstructorInvocationTestCases {
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfig(languageVersion: '2.15');
+  }
+}
+
+mixin AddSuperConstructorInvocationTestCases on FixProcessorTest {
   @override
   FixKind get kind => DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION;
 
@@ -71,7 +85,26 @@
     await assertNoFix();
   }
 
-  Future<void> test_requiredAndNamed() async {
+  Future<void> test_typeArgument() async {
+    await resolveTestCode('''
+class A<T> {
+  A(T p);
+}
+class B extends A<int> {
+  B();
+}
+''');
+    await assertHasFix('''
+class A<T> {
+  A(T p);
+}
+class B extends A<int> {
+  B() : super(0);
+}
+''');
+  }
+
+  Future<void> test_unnamed_requiredAndNamed() async {
     await resolveTestCode('''
 class A {
   A(bool p1, int p2, double p3, String p4, {p5});
@@ -90,21 +123,24 @@
 ''');
   }
 
-  Future<void> test_typeArgument() async {
+  @FailingTest(
+    reason: 'Generates positional arguments instead of named',
+  )
+  Future<void> test_unnamed_requiredNamed() async {
     await resolveTestCode('''
-class A<T> {
-  A(T p);
+class A {
+  A({required int p1});
 }
-class B extends A<int> {
+class B extends A {
   B();
 }
 ''');
     await assertHasFix('''
-class A<T> {
-  A(T p);
+class A {
+  A({required int p1});
 }
-class B extends A<int> {
-  B() : super(0);
+class B extends A {
+  B() : super(p1: 0);
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_setting_test.dart b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_setting_test.dart
index c378884..9276b71 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_setting_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_setting_test.dart
@@ -18,13 +18,13 @@
     await assertHasFix('''
 analyzer:
   enable-experiment:
-    - non-nullable
+    - super-parameters
   language:
     enableSuperMixins: true
 ''', '''
 analyzer:
   enable-experiment:
-    - non-nullable
+    - super-parameters
 ''');
   }
 
@@ -33,11 +33,11 @@
 analyzer:
   enable-experiment:
     - not-an-experiment
-    - non-nullable
+    - super-parameters
 ''', '''
 analyzer:
   enable-experiment:
-    - non-nullable
+    - super-parameters
 ''');
   }
 
@@ -45,12 +45,12 @@
     await assertHasFix('''
 analyzer:
   enable-experiment:
-    - non-nullable
+    - super-parameters
     - not-an-experiment
 ''', '''
 analyzer:
   enable-experiment:
-    - non-nullable
+    - super-parameters
 ''');
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart
index dbfcc51..5f54e50 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart
@@ -415,17 +415,21 @@
     await resolveTestCode('''
 class A {
   void f() {
-    myUndefinedMethod(0, bbb: 1.0, ccc: '2');
+    var c = '2';
+    int? d;
+    myUndefinedMethod(0, bbb: 1.0, ccc: c, ddd: d);
   }
 }
 ''');
     await assertHasFix('''
 class A {
   void f() {
-    myUndefinedMethod(0, bbb: 1.0, ccc: '2');
+    var c = '2';
+    int? d;
+    myUndefinedMethod(0, bbb: 1.0, ccc: c, ddd: d);
   }
 
-  void myUndefinedMethod(int i, {double bbb, String ccc}) {}
+  void myUndefinedMethod(int i, {required double bbb, required String ccc, int? ddd}) {}
 }
 ''');
     // linked positions
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index dff9c05..6839e8f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -33,7 +33,7 @@
   void C() {}
 }
 ''');
-    setPackageData(_add(0, components: ['C', 'C']));
+    setPackageData(_add(0, components: ['C']));
     await resolveTestCode('''
 import '$importUri';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
index 16ec4ae..e7a0f03 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
@@ -23,7 +23,9 @@
       List<ElementKind>? expectedKinds,
       List<String>? expectedUris}) {
     var node = findNode.any(search);
-    var matcher = ElementMatcher.forNode(node)!;
+    var matchers = ElementMatcher.matchersForNode(node);
+    expect(matchers, hasLength(1));
+    var matcher = matchers[0];
     if (expectedUris != null) {
       expect(matcher.importedUris,
           unorderedEquals(expectedUris.map((uri) => Uri.parse(uri))));
@@ -52,8 +54,10 @@
   /// The kinds that are expected where an invocation is allowed.
   static List<ElementKind> invocationKinds = [
     ElementKind.classKind,
+    ElementKind.constructorKind,
     ElementKind.extensionKind,
     ElementKind.functionKind,
+    ElementKind.getterKind,
     ElementKind.methodKind,
   ];
 
@@ -107,7 +111,7 @@
   }
 }
 ''');
-    _assertMatcher('g;', expectedComponents: ['g', 'C']);
+    _assertMatcher('g;', expectedComponents: ['g']);
   }
 
   Future<void> test_getter_withoutTarget_unresolved() async {
@@ -147,17 +151,7 @@
   s.length;
 }
 ''');
-    // TODO(brianwilkerson) Several of these kinds don't seem to be appropriate,
-    //  so we might want to narrow down the list.
-    _assertMatcher('s', expectedComponents: [
-      's'
-    ], expectedKinds: [
-      ElementKind.classKind,
-      ElementKind.enumKind,
-      ElementKind.extensionKind,
-      ElementKind.mixinKind,
-      ElementKind.typedefKind,
-    ]);
+    _assertMatcher('s', expectedComponents: ['s'], expectedKinds: []);
   }
 
   Future<void> test_method_withoutTarget_resolved() async {
@@ -215,7 +209,7 @@
   }
 }
 ''');
-    _assertMatcher('s =', expectedComponents: ['s', 'C']);
+    _assertMatcher('s =', expectedComponents: ['s']);
   }
 
   Future<void> test_setter_withoutTarget_unresolved() async {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
index e8d6d1b..ce50e6b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
@@ -706,6 +706,117 @@
 ''');
   }
 
+  @failingTest
+  Future<void> test_material_FlatButton_deprecated() async {
+    setPackageContent('''
+@deprecated
+class FlatButton {
+  factory FlatButton.icon({
+    Key? key,
+    required VoidCallback? onPressed,
+    VoidCallback? onLongPress,
+    ValueChanged<bool>? onHighlightChanged,
+    ButtonTextTheme? textTheme,
+    Color? highlightColor,
+    Brightness? colorBrightness,
+    Clip? clipBehavior,
+    FocusNode? focusNode,
+    bool autofocus = true,
+    required Widget icon,
+    required Widget label,
+  }) => FlatButton();
+  FlatButton();
+}
+class Key {}
+class UniqueKey extends Key {}
+typedef VoidCallback = void Function();
+typedef ValueChanged<T> = void Function(T value);
+class ButtonTextTheme {}
+class Color {}
+class Colors {
+  static Color blue = Color();
+}
+class Brightness {
+  static Brightness dark = Brightness();
+}
+class Clip {
+  static Clip hardEdge = Clip();
+}
+class FocusNode {}
+class Widget {}
+class Icon extends Widget {
+  Icon(String icon);
+}
+class Text extends Widget {
+  Text(String content);
+}
+class Icons {
+  static String ten_k_outlined = '';
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+  # Changes made in https://github.com/flutter/flutter/pull/73352
+  - title: "Migrate to 'TextButton.icon'"
+    date: 2021-01-08
+    element:
+      uris: [ '$importUri' ]
+      constructor: 'icon'
+      inClass: 'FlatButton'
+    changes:
+      - kind: 'removeParameter'
+        name: 'onHighlightChanged'
+      - kind: 'removeParameter'
+        name: 'textTheme'
+      - kind: 'removeParameter'
+        name: 'highlightColor'
+      - kind: 'removeParameter'
+        name: 'colorBrightness'
+      - kind: 'replacedBy'
+        newElement:
+          uris: [ '$importUri' ]
+          constructor: 'icon'
+          inClass: 'TextButton'
+''');
+    await resolveTestCode('''
+import '$importUri';
+
+void f() {
+  FlatButton.icon(
+    key: UniqueKey(),
+    icon: Icon(Icons.ten_k_outlined),
+    label: Text('FlatButton'),
+    onPressed: (){},
+    onLongPress: (){},
+    clipBehavior: Clip.hardEdge,
+    focusNode: FocusNode(),
+    autofocus: true,
+    onHighlightChanged: (_) {},
+    textTheme: ButtonTextTheme(),
+    highlightColor: Colors.blue,
+    colorBrightness: Brightness.dark,
+  );
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  TextButton.icon(
+    key: UniqueKey(),
+    icon: Icon(Icons.ten_k_outlined),
+    label: Text('FlatButton'),
+    onPressed: (){},
+    onLongPress: (){},
+    clipBehavior: Clip.hardEdge,
+    focusNode: FocusNode(),
+    autofocus: true,
+  );
+}
+''');
+  }
+
   Future<void>
       test_material_InputDecoration_defaultConstructor_matchFirstCase_deprecated() async {
     setPackageContent('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index 95055f4..c3d8722 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -784,7 +784,7 @@
       (transform.changesSelector as UnconditionalChangesSelector).changes;
 
   ElementMatcher _matcher(String name) =>
-      ElementMatcher(importedUris: uris, components: [name]);
+      ElementMatcher(importedUris: uris, components: [name], kinds: const []);
 
   List<Transform> _transforms(String name) =>
       result!.transformsFor(_matcher(name), applyingBulkFixes: false);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/extract_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/extract_local_variable_test.dart
new file mode 100644
index 0000000..3fdb4db
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/extract_local_variable_test.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtractLocalVariableTest);
+  });
+}
+
+@reflectiveTest
+class ExtractLocalVariableTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.EXTRACT_LOCAL_VARIABLE;
+
+  Future<void> test_ifCondition_notBangEq() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    if (foo == 0) {
+      foo.isEven;
+    }
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_ifCondition_notBinaryExpression() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    if (!(1 == 0)) {
+      foo.isEven;
+    }
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_ifCondition_notNull() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    if (foo != 0) {
+      foo.isEven;
+    }
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_noEnclosingIf() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    foo.isEven;
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_prefixedIdentifier() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    if (foo != null) {
+      foo.isEven;
+    }
+  }
+}
+''');
+    await assertHasFix('''
+abstract class A {
+  int? get foo;
+
+  void bar() {
+    final foo = this.foo;
+    if (foo != null) {
+      foo.isEven;
+    }
+  }
+}
+''');
+  }
+
+  Future<void> test_prefixedIdentifier_methodInvocation() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+}
+void f(A a) {
+  if (a.foo != null) {
+    a.foo.abs();
+  }
+}
+''');
+    await assertHasFix('''
+abstract class A {
+  int? get foo;
+}
+void f(A a) {
+  final foo = a.foo;
+  if (foo != null) {
+    foo.abs();
+  }
+}
+''');
+  }
+
+  Future<void> test_prefixedIdentifier_propertyAccess() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+}
+void f(A a) {
+  if (a.foo != null) {
+    a.foo.isEven;
+  }
+}
+''');
+    await assertHasFix('''
+abstract class A {
+  int? get foo;
+}
+void f(A a) {
+  final foo = a.foo;
+  if (foo != null) {
+    foo.isEven;
+  }
+}
+''');
+  }
+
+  Future<void> test_propertyAccess_methodInvocation() async {
+    await resolveTestCode('''
+abstract class A {
+  int? get foo;
+}
+abstract class B {
+  A get a;
+}
+void f(B b) {
+  if (b.a.foo != null) {
+    b.a.foo.abs();
+  }
+}
+''');
+    await assertHasFix('''
+abstract class A {
+  int? get foo;
+}
+abstract class B {
+  A get a;
+}
+void f(B b) {
+  final foo = b.a.foo;
+  if (foo != null) {
+    foo.abs();
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
index d7771af..16718c3 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/make_final_test.dart
@@ -304,6 +304,19 @@
 ''');
   }
 
+  Future<void> test_named_optional_withDefault() async {
+    await resolveTestCode('''
+void fn({String test = 'value'}) {
+  print(test);
+}
+''');
+    await assertHasFix('''
+void fn({final String test = 'value'}) {
+  print(test);
+}
+''');
+  }
+
   Future<void> test_named_required() async {
     await resolveTestCode('''
 void fn({required String test}) {
@@ -330,6 +343,19 @@
 ''');
   }
 
+  Future<void> test_positional_optional_withDefault() async {
+    await resolveTestCode('''
+void fn([String? test = 'value']) {
+  print(test);
+}
+''');
+    await assertHasFix('''
+void fn([final String? test = 'value']) {
+  print(test);
+}
+''');
+  }
+
   Future<void> test_simple_hasType() async {
     await resolveTestCode('''
 void fn(String test) {
@@ -356,6 +382,19 @@
 ''');
   }
 
+  Future<void> test_simple_nullable() async {
+    await resolveTestCode('''
+void fn(String? test) {
+  print(test);
+}
+''');
+    await assertHasFix('''
+void fn(final String? test) {
+  print(test);
+}
+''');
+  }
+
   Future<void> test_simple_second() async {
     await resolveTestCode('''
 void fn(final String test, String other) {
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 3174635..001e243 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
@@ -15,6 +15,8 @@
 import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters;
 import 'add_key_to_constructors_test.dart' as add_key_to_constructors;
 import 'add_late_test.dart' as add_late;
+import 'add_leading_newline_to_string_test.dart'
+    as add_leading_newline_to_string;
 import 'add_missing_enum_case_clauses_test.dart'
     as add_missing_enum_case_clauses;
 import 'add_missing_enum_like_case_clauses_test.dart'
@@ -96,6 +98,7 @@
 import 'create_setter_test.dart' as create_setter;
 import 'data_driven/test_all.dart' as data_driven;
 import 'extend_class_for_mixin_test.dart' as extend_class_for_mixin;
+import 'extract_local_variable_test.dart' as extract_local_variable;
 import 'fix_in_file_test.dart' as fix_in_file;
 import 'fix_processor_map_test.dart' as fix_processor_map;
 import 'fix_test.dart' as fix;
@@ -227,6 +230,7 @@
     add_field_formal_parameters.main();
     add_key_to_constructors.main();
     add_late.main();
+    add_leading_newline_to_string.main();
     add_missing_enum_case_clauses.main();
     add_missing_enum_like_case_clauses.main();
     add_missing_parameter_named.main();
@@ -296,6 +300,7 @@
     data_driven.main();
     extend_class_for_mixin.main();
     fix.main();
+    extract_local_variable.main();
     fix_in_file.main();
     fix_processor_map.main();
     ignore_error.main();
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index aba444c..7007b15 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -306,6 +306,9 @@
   /// run.
   final bool availableSuggestions;
 
+  /// A flag indicating whether the new protocol should be used for this run.
+  final bool useNewProtocol;
+
   /// The function to be executed when this metrics collector is enabled.
   final void Function()? enableFunction;
 
@@ -375,9 +378,11 @@
 
   CompletionMetrics(this.name,
       {required this.availableSuggestions,
+      this.useNewProtocol = false,
       this.enableFunction,
       this.disableFunction})
-      : userTag = UserTag(name);
+      : assert(!(availableSuggestions && useNewProtocol)),
+        userTag = UserTag(name);
 
   /// Return an instance extracted from the decoded JSON [map].
   factory CompletionMetrics.fromJson(Map<String, dynamic> map) {
@@ -694,19 +699,23 @@
     // To compare two or more changes to completions, add a `CompletionMetrics`
     // object with enable and disable functions to the list of `targetMetrics`.
     targetMetrics.add(CompletionMetrics('shipping',
-        availableSuggestions: false,
+        availableSuggestions: true,
         enableFunction: null,
         disableFunction: null));
 
     // To compare two or more relevance tables, uncomment the line below and
     // add the `RelevanceTables` to the list. The default relevance tables
     // should not be included in the list.
-//     compareRelevanceTables([], availableSuggestions: false);
+//    compareRelevanceTables([], availableSuggestions: false);
 
     // To compare the relative benefit from each of the features, uncomment the
     // line below.
 //    compareIndividualFeatures(availableSuggestions: false);
 
+    // To compare the new protocol to the old, uncomment the lines below.
+//    targetMetrics.add(CompletionMetrics('new protocol',
+//        availableSuggestions: false, useNewProtocol: true));
+
     final collection = AnalysisContextCollectionImpl(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1201,17 +1210,18 @@
       OperationPerformanceImpl performance,
       DartCompletionRequest dartRequest,
       [DeclarationsTracker? declarationsTracker,
-      protocol.CompletionAvailableSuggestionsParams?
-          availableSuggestionsParams]) async {
+      protocol.CompletionAvailableSuggestionsParams? availableSuggestionsParams,
+      NotImportedSuggestions? notImportedSuggestions]) async {
     List<protocol.CompletionSuggestion> suggestions;
 
     var budget = CompletionBudget(Duration(seconds: 30));
     if (declarationsTracker == null) {
       // available suggestions == false
       suggestions = await DartCompletionManager(
-        budget: budget,
-        listener: listener,
-      ).computeSuggestions(dartRequest, performance);
+              budget: budget,
+              listener: listener,
+              notImportedSuggestions: notImportedSuggestions)
+          .computeSuggestions(dartRequest, performance);
     } else {
       // available suggestions == true
       var includedElementKinds = <protocol.ElementKind>{};
@@ -1382,6 +1392,7 @@
             request,
             metrics.availableSuggestions ? declarationsTracker : null,
             metrics.availableSuggestions ? availableSuggestionsParams : null,
+            metrics.useNewProtocol ? NotImportedSuggestions() : null,
           );
           stopwatch.stop();
 
@@ -1899,10 +1910,11 @@
     0.0,
     0.0,
     0.0,
+    0.0,
     0.0
   ];
 
-  Map<protocol.CompletionSuggestion, List<double>> featureMap = {};
+  Map<protocol.CompletionSuggestion, List<double>> featureMap = Map.identity();
 
   List<double> cachedFeatures = noFeatures;
 
@@ -1923,6 +1935,7 @@
       double hasDeprecated = 0.0,
       double isConstant = 0.0,
       double isNoSuchMethod = 0.0,
+      double isNotImported = 0.0,
       double keyword = 0.0,
       double startsWithDollar = 0.0,
       double superMatches = 0.0,
@@ -1935,6 +1948,7 @@
       hasDeprecated,
       isConstant,
       isNoSuchMethod,
+      isNotImported,
       keyword,
       startsWithDollar,
       superMatches,
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 5383d50..ba060b9 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -131,6 +131,8 @@
 }
 
 String _getTypeCheckFailureMessage(TypeBase type) {
+  type = resolveTypeAlias(type);
+
   if (type is LiteralType) {
     return 'must be the literal ${type.literal}';
   } else if (type is LiteralUnionType) {
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index f1783c2..58a60e2 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -251,17 +251,17 @@
       ],
     ),
     interface(
+      // Used as a base class for all resolution data classes.
       'CompletionItemResolutionInfo',
-      [
-        field('file', type: 'string'),
-        field('offset', type: 'int'),
-      ],
+      [],
     ),
     interface(
-      'DartCompletionItemResolutionInfo',
+      'DartSuggestionSetCompletionItemResolutionInfo',
       [
         // These fields have short-ish names because they're on the payload
         // for all suggestion-set backed completions.
+        field('file', type: 'string'),
+        field('offset', type: 'int'),
         field('libId', type: 'int'),
         field('displayUri', type: 'string'),
         field('rOffset', type: 'int'), // replacementOffset
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 28bf1c5..d897d0b 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -42,7 +42,8 @@
   return parser.parse();
 }
 
-TypeBase typeOfLiteral(TokenType tokenType) {
+TypeBase typeOfLiteral(Token token) {
+  final tokenType = token.type;
   final typeName = tokenType == TokenType.STRING
       ? 'string'
       : tokenType == TokenType.NUMBER
@@ -178,7 +179,7 @@
 }
 
 class LiteralType extends TypeBase {
-  final Type type;
+  final TypeBase type;
   final String literal;
 
   LiteralType(this.type, this.literal);
@@ -278,7 +279,7 @@
     final value = _match([TokenType.EQUAL]) ? _advance() : null;
 
     if (type == null && value != null) {
-      type = typeOfLiteral(value.type);
+      type = typeOfLiteral(value);
     }
 
     _consume(TokenType.SEMI_COLON, 'Expected ;');
@@ -339,7 +340,7 @@
     final value = _match([TokenType.EQUAL]) ? _advance() : null;
 
     if (type == null && value != null) {
-      type = typeOfLiteral(value.type);
+      type = typeOfLiteral(value);
     }
     return Const(leadingComment, name, type!, value!);
   }
@@ -601,17 +602,13 @@
         // Some types are in (parens), so we just parse the contents as a nested type.
         type = _type(containerName, fieldName);
         _consume(TokenType.RIGHT_PAREN, 'Expected )');
-      } else if (_check(TokenType.STRING)) {
+      } else if (_check(TokenType.STRING) || _check(TokenType.NUMBER)) {
         final token = _advance();
-        // In TS and the spec, literal strings can be types:
+        // In TS and the spec, literal values can be types:
         // export const PlainText: 'plaintext' = 'plaintext';
         // trace?: 'off' | 'messages' | 'verbose';
-        type = LiteralType(Type.identifier('string'), token.lexeme);
-      } else if (_check(TokenType.NUMBER)) {
-        final token = _advance();
-        // In TS and the spec, literal numbers can be types:
         // export const Invoked: 1 = 1;
-        type = LiteralType(Type.identifier('number'), token.lexeme);
+        type = LiteralType(typeOfLiteral(token), token.lexeme);
       } else if (_match([TokenType.LEFT_BRACKET])) {
         // Tuples will just be converted to List/Array.
         final tupleElementTypes = <TypeBase>[];
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index c5022ea..3d8e563 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -405,11 +405,10 @@
    * {@code completion.getSuggestionDetails2}
    *
    * Clients must make this request when the user has selected a completion suggestion with the
-   * libraryUriToImportIndex field set. The 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. The text to insert might be different from the original suggestion to include an
-   * import prefix if the library will be imported with a prefix to avoid shadowing conflicts in the
-   * file.
+   * isNotImported field set to true. The 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. The text to insert might be different from the original suggestion to include an import
+   * prefix if the library will be imported with a prefix to avoid shadowing conflicts in the file.
    *
    * @param file The path of the file into which this completion is being inserted.
    * @param offset The offset in the file where the completion will be inserted.
@@ -441,12 +440,16 @@
    * @param offset The offset within the file at which suggestions are to be made.
    * @param maxResults The maximum number of suggestions to return. If the number of suggestions
    *         after filtering is greater than the maxResults, then isIncomplete is set to true.
+   * @param completionMode The mode of code completion being invoked. If no value is provided, BASIC
+   *         will be assumed. BASIC is also the only currently supported.
+   * @param invocationCount The number of times that the user has invoked code completion at the same
+   *         code location, counting from 1. If no value is provided, 1 will be assumed.
    * @param timeout The approximate time in milliseconds that the server should spend. The server
    *         will perform some steps anyway, even if it takes longer than the specified timeout. This
    *         field is intended to be used for benchmarking, and usually should not be provided, so
    *         that the default timeout is used.
    */
-  public void completion_getSuggestions2(String file, int offset, int maxResults, int timeout, GetSuggestions2Consumer consumer);
+  public void completion_getSuggestions2(String file, int offset, int maxResults, String completionMode, int invocationCount, int timeout, GetSuggestions2Consumer consumer);
 
   /**
    * {@code completion.registerLibraryPaths}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionMode.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionMode.java
new file mode 100644
index 0000000..89f11dd
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionMode.java
@@ -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.
+ *
+ * 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 kinds of code completion that users can invoke.
+ *
+ * @coverage dart.server.generated.types
+ */
+public class CompletionMode {
+
+  /**
+   * Basic code completion invocation type, and the default for this enumeration.
+   */
+  public static final String BASIC = "BASIC";
+
+  /**
+   * Smart code completion, currently not implemented.
+   */
+  public static final String SMART = "SMART";
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index bf8d912..f73aa41 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -176,18 +176,16 @@
   private final String parameterType;
 
   /**
-   * The index in the list of libraries that could be imported to make this suggestion accessible in
-   * the file where completion was requested. The server provides this list of libraries together
-   * with suggestions, so that information about the library can be shared for multiple suggestions.
-   * This field is omitted if the library is already imported, so that the suggestion can be inserted
-   * as is, or if getSuggestions was used rather than getSuggestions2.
+   * True if the suggestion is for an element from a not yet imported library. This field is omitted
+   * if the element is declared locally, or is from library is already imported, so that the
+   * suggestion can be inserted as is, or if getSuggestions was used rather than getSuggestions2.
    */
-  private final Integer libraryUriToImportIndex;
+  private final Boolean isNotImported;
 
   /**
    * Constructor for {@link CompletionSuggestion}.
    */
-  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Integer libraryUriToImportIndex) {
+  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Boolean isNotImported) {
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
@@ -211,7 +209,7 @@
     this.hasNamedParameters = hasNamedParameters;
     this.parameterName = parameterName;
     this.parameterType = parameterType;
-    this.libraryUriToImportIndex = libraryUriToImportIndex;
+    this.isNotImported = isNotImported;
   }
 
   @Override
@@ -242,7 +240,7 @@
         ObjectUtilities.equals(other.hasNamedParameters, hasNamedParameters) &&
         ObjectUtilities.equals(other.parameterName, parameterName) &&
         ObjectUtilities.equals(other.parameterType, parameterType) &&
-        ObjectUtilities.equals(other.libraryUriToImportIndex, libraryUriToImportIndex);
+        ObjectUtilities.equals(other.isNotImported, isNotImported);
     }
     return false;
   }
@@ -271,8 +269,8 @@
     Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
     String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
     String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
-    Integer libraryUriToImportIndex = jsonObject.get("libraryUriToImportIndex") == null ? null : jsonObject.get("libraryUriToImportIndex").getAsInt();
-    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, libraryUriToImportIndex);
+    Boolean isNotImported = jsonObject.get("isNotImported") == null ? null : jsonObject.get("isNotImported").getAsBoolean();
+    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, isNotImported);
   }
 
   public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -369,6 +367,15 @@
   }
 
   /**
+   * True if the suggestion is for an element from a not yet imported library. This field is omitted
+   * if the element is declared locally, or is from library is already imported, so that the
+   * suggestion can be inserted as is, or if getSuggestions was used rather than getSuggestions2.
+   */
+  public Boolean getIsNotImported() {
+    return isNotImported;
+  }
+
+  /**
    * True if the element is not known to be valid for the target. This happens if the type of the
    * target is dynamic.
    */
@@ -384,17 +391,6 @@
   }
 
   /**
-   * The index in the list of libraries that could be imported to make this suggestion accessible in
-   * the file where completion was requested. The server provides this list of libraries together
-   * with suggestions, so that information about the library can be shared for multiple suggestions.
-   * This field is omitted if the library is already imported, so that the suggestion can be inserted
-   * as is, or if getSuggestions was used rather than getSuggestions2.
-   */
-  public Integer getLibraryUriToImportIndex() {
-    return libraryUriToImportIndex;
-  }
-
-  /**
    * The name of the optional parameter being suggested. This field is omitted if the suggestion is
    * not the addition of an optional argument within an argument list.
    */
@@ -509,7 +505,7 @@
     builder.append(hasNamedParameters);
     builder.append(parameterName);
     builder.append(parameterType);
-    builder.append(libraryUriToImportIndex);
+    builder.append(isNotImported);
     return builder.toHashCode();
   }
 
@@ -582,8 +578,8 @@
     if (parameterType != null) {
       jsonObject.addProperty("parameterType", parameterType);
     }
-    if (libraryUriToImportIndex != null) {
-      jsonObject.addProperty("libraryUriToImportIndex", libraryUriToImportIndex);
+    if (isNotImported != null) {
+      jsonObject.addProperty("isNotImported", isNotImported);
     }
     return jsonObject;
   }
@@ -638,8 +634,8 @@
     builder.append(parameterName + ", ");
     builder.append("parameterType=");
     builder.append(parameterType + ", ");
-    builder.append("libraryUriToImportIndex=");
-    builder.append(libraryUriToImportIndex);
+    builder.append("isNotImported=");
+    builder.append(isNotImported);
     builder.append("]");
     return builder.toString();
   }
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Element.java b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
index 690f101..0648fc7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Element.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
@@ -101,9 +101,15 @@
   private final String aliasedType;
 
   /**
+   * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
+   * defined.
+   */
+  private final String libraryUri;
+
+  /**
    * Constructor for {@link Element}.
    */
-  public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType) {
+  public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType, String libraryUri) {
     this.kind = kind;
     this.name = name;
     this.location = location;
@@ -112,6 +118,7 @@
     this.returnType = returnType;
     this.typeParameters = typeParameters;
     this.aliasedType = aliasedType;
+    this.libraryUri = libraryUri;
   }
 
   @Override
@@ -126,7 +133,8 @@
         ObjectUtilities.equals(other.parameters, parameters) &&
         ObjectUtilities.equals(other.returnType, returnType) &&
         ObjectUtilities.equals(other.typeParameters, typeParameters) &&
-        ObjectUtilities.equals(other.aliasedType, aliasedType);
+        ObjectUtilities.equals(other.aliasedType, aliasedType) &&
+        ObjectUtilities.equals(other.libraryUri, libraryUri);
     }
     return false;
   }
@@ -140,7 +148,8 @@
     String returnType = jsonObject.get("returnType") == null ? null : jsonObject.get("returnType").getAsString();
     String typeParameters = jsonObject.get("typeParameters") == null ? null : jsonObject.get("typeParameters").getAsString();
     String aliasedType = jsonObject.get("aliasedType") == null ? null : jsonObject.get("aliasedType").getAsString();
-    return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType);
+    String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
+    return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType, libraryUri);
   }
 
   public static List<Element> fromJsonArray(JsonArray jsonArray) {
@@ -185,6 +194,14 @@
   }
 
   /**
+   * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
+   * defined.
+   */
+  public String getLibraryUri() {
+    return libraryUri;
+  }
+
+  /**
    * The location of the name in the declaration of the element.
    */
   public Location getLocation() {
@@ -235,6 +252,7 @@
     builder.append(returnType);
     builder.append(typeParameters);
     builder.append(aliasedType);
+    builder.append(libraryUri);
     return builder.toHashCode();
   }
 
@@ -282,6 +300,9 @@
     if (aliasedType != null) {
       jsonObject.addProperty("aliasedType", aliasedType);
     }
+    if (libraryUri != null) {
+      jsonObject.addProperty("libraryUri", libraryUri);
+    }
     return jsonObject;
   }
 
@@ -304,7 +325,9 @@
     builder.append("typeParameters=");
     builder.append(typeParameters + ", ");
     builder.append("aliasedType=");
-    builder.append(aliasedType);
+    builder.append(aliasedType + ", ");
+    builder.append("libraryUri=");
+    builder.append(libraryUri);
     builder.append("]");
     return builder.toString();
   }
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
index fe567c5..4c4e17f 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
@@ -50,6 +50,8 @@
 
   public static final String ENUM_CONSTANT = "ENUM_CONSTANT";
 
+  public static final String EXTENSION = "EXTENSION";
+
   /**
    * Deprecated - no longer sent.
    */
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index c634b46..51f35a4 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.32.8</version>
+  <version>1.32.9</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1507,6 +1507,22 @@
           then <tt>isIncomplete</tt> is set to <tt>true</tt>.
         </p>
       </field>
+      <field name="completionMode" experimental="true" optional="true">
+        <ref>CompletionMode</ref>
+        <p>
+          The mode of code completion being invoked. If no value is provided,
+          <tt>BASIC</tt> will be assumed. <tt>BASIC</tt> is also the only
+          currently supported.
+        </p>
+      </field>
+      <field name="invocationCount" experimental="true" optional="true">
+        <ref>int</ref>
+        <p>
+          The number of times that the user has invoked code completion at
+          the same code location, counting from 1. If no value is provided,
+          1 will be assumed.
+        </p>
+      </field>
       <field name="timeout" experimental="true" optional="true">
         <ref>int</ref>
         <p>
@@ -1554,25 +1570,7 @@
         <p>
           This list contains suggestions from both imported, and not yet
           imported libraries. Items from not yet imported libraries will
-          have <tt>libraryUriToImportIndex</tt> set, which is an index into
-          the <tt>libraryUrisToImport</tt> in this response.
-        </p>
-      </field>
-      <field name="libraryUrisToImport">
-        <list>
-          <ref>String</ref>
-        </list>
-        <p>
-          The list of libraries with declarations that are not yet available
-          in the file where completion was requested, most often because
-          the library is not yet imported. The declarations still might be
-          included into the <tt>suggestions</tt>, and the client should use
-          <tt>getSuggestionDetails2</tt> on selection to make the library
-          available in the file.
-        </p>
-        <p>
-          Each item is the URI of a library, such as <tt>package:foo/bar.dart</tt>
-          or <tt>file:///home/me/workspace/foo/test/bar_test.dart</tt>.
+          have <tt>isNotImported</tt> set to <tt>true</tt>.
         </p>
       </field>
       <field name="isIncomplete">
@@ -1683,7 +1681,7 @@
   <request method="getSuggestionDetails2" experimental="true">
     <p>
       Clients must make this request when the user has selected a completion
-      suggestion with the <tt>libraryUriToImportIndex</tt> field set.
+      suggestion with the <tt>isNotImported</tt> field set to <tt>true</tt>.
       The 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. The text to insert might be
@@ -4128,6 +4126,26 @@
       </field>
     </object>
   </type>
+  <type name="CompletionMode">
+    <p>
+      An enumeration of the kinds of code completion that users can invoke.
+    </p>
+    <enum>
+      <value>
+        <code>BASIC</code>
+        <p>
+          Basic code completion invocation type, and the default for this
+          enumeration.
+        </p>
+      </value>
+      <value>
+        <code>SMART</code>
+        <p>
+          Smart code completion, currently not implemented.
+        </p>
+      </value>
+    </enum>
+  </type>
   <type name="RuntimeCompletionExpression">
     <p>
       An expression for which we want to know its runtime type.
diff --git a/pkg/analysis_server_client/lib/server.dart b/pkg/analysis_server_client/lib/server.dart
index 3d9dbb4..169d25b 100644
--- a/pkg/analysis_server_client/lib/server.dart
+++ b/pkg/analysis_server_client/lib/server.dart
@@ -99,11 +99,12 @@
     bool suppressAnalytics = true,
     bool useAnalysisHighlight2 = false,
     bool enableAsserts = false,
+    String? dartBinary,
   }) async {
     if (_process != null) {
       throw Exception('Process already started');
     }
-    var dartBinary = Platform.executable;
+    dartBinary ??= Platform.executable;
 
     // The integration tests run 3x faster when run from snapshots
     // (you need to run test.py with --use-sdk).
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index b2d7548..c1a528b 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -612,14 +612,11 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
-  /// The index in the list of libraries that could be imported to make this
-  /// suggestion accessible in the file where completion was requested. The
-  /// server provides this list of libraries together with suggestions, so that
-  /// information about the library can be shared for multiple suggestions.
-  /// This field is omitted if the library is already imported, so that the
-  /// suggestion can be inserted as is, or if getSuggestions was used rather
-  /// than getSuggestions2.
-  int? libraryUriToImportIndex;
+  /// True if the suggestion is for an element from a not yet imported library.
+  /// This field is omitted if the element is declared locally, or is from
+  /// library is already imported, so that the suggestion can be inserted as
+  /// is, or if getSuggestions was used rather than getSuggestions2.
+  bool? isNotImported;
 
   CompletionSuggestion(
       this.kind,
@@ -645,7 +642,7 @@
       this.hasNamedParameters,
       this.parameterName,
       this.parameterType,
-      this.libraryUriToImportIndex});
+      this.isNotImported});
 
   factory CompletionSuggestion.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -784,11 +781,10 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
-      int? libraryUriToImportIndex;
-      if (json.containsKey('libraryUriToImportIndex')) {
-        libraryUriToImportIndex = jsonDecoder.decodeInt(
-            jsonPath + '.libraryUriToImportIndex',
-            json['libraryUriToImportIndex']);
+      bool? isNotImported;
+      if (json.containsKey('isNotImported')) {
+        isNotImported = jsonDecoder.decodeBool(
+            jsonPath + '.isNotImported', json['isNotImported']);
       }
       return CompletionSuggestion(kind, relevance, completion, selectionOffset,
           selectionLength, isDeprecated, isPotential,
@@ -808,7 +804,7 @@
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
           parameterType: parameterType,
-          libraryUriToImportIndex: libraryUriToImportIndex);
+          isNotImported: isNotImported);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
     }
@@ -888,9 +884,9 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
-    var libraryUriToImportIndex = this.libraryUriToImportIndex;
-    if (libraryUriToImportIndex != null) {
-      result['libraryUriToImportIndex'] = libraryUriToImportIndex;
+    var isNotImported = this.isNotImported;
+    if (isNotImported != null) {
+      result['isNotImported'] = isNotImported;
     }
     return result;
   }
@@ -927,7 +923,7 @@
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
           parameterType == other.parameterType &&
-          libraryUriToImportIndex == other.libraryUriToImportIndex;
+          isNotImported == other.isNotImported;
     }
     return false;
   }
@@ -957,7 +953,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
-        libraryUriToImportIndex,
+        isNotImported,
       ]);
 }
 
@@ -1238,12 +1234,17 @@
   /// this field will not be defined.
   String? aliasedType;
 
+  /// If the element belongs to a library, the URI of the library. Otherwise,
+  /// this field will not be defined.
+  String? libraryUri;
+
   Element(this.kind, this.name, this.flags,
       {this.location,
       this.parameters,
       this.returnType,
       this.typeParameters,
-      this.aliasedType});
+      this.aliasedType,
+      this.libraryUri});
 
   factory Element.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1293,12 +1294,18 @@
         aliasedType = jsonDecoder.decodeString(
             jsonPath + '.aliasedType', json['aliasedType']);
       }
+      String? libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      }
       return Element(kind, name, flags,
           location: location,
           parameters: parameters,
           returnType: returnType,
           typeParameters: typeParameters,
-          aliasedType: aliasedType);
+          aliasedType: aliasedType,
+          libraryUri: libraryUri);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Element', json);
     }
@@ -1337,6 +1344,10 @@
     if (aliasedType != null) {
       result['aliasedType'] = aliasedType;
     }
+    var libraryUri = this.libraryUri;
+    if (libraryUri != null) {
+      result['libraryUri'] = libraryUri;
+    }
     return result;
   }
 
@@ -1353,7 +1364,8 @@
           parameters == other.parameters &&
           returnType == other.returnType &&
           typeParameters == other.typeParameters &&
-          aliasedType == other.aliasedType;
+          aliasedType == other.aliasedType &&
+          libraryUri == other.libraryUri;
     }
     return false;
   }
@@ -1368,6 +1380,7 @@
         returnType,
         typeParameters,
         aliasedType,
+        libraryUri,
       );
 }
 
@@ -1869,6 +1882,7 @@
 ///   DYNAMIC_PARAMETER_REFERENCE
 ///   ENUM
 ///   ENUM_CONSTANT
+///   EXTENSION
 ///   FIELD
 ///   FIELD_STATIC
 ///   FUNCTION
@@ -1982,6 +1996,9 @@
   static const HighlightRegionType ENUM_CONSTANT =
       HighlightRegionType._('ENUM_CONSTANT');
 
+  static const HighlightRegionType EXTENSION =
+      HighlightRegionType._('EXTENSION');
+
   /// Deprecated - no longer sent.
   static const HighlightRegionType FIELD = HighlightRegionType._('FIELD');
 
@@ -2197,6 +2214,7 @@
     DYNAMIC_PARAMETER_REFERENCE,
     ENUM,
     ENUM_CONSTANT,
+    EXTENSION,
     FIELD,
     FIELD_STATIC,
     FUNCTION,
@@ -2301,6 +2319,8 @@
         return ENUM;
       case 'ENUM_CONSTANT':
         return ENUM_CONSTANT;
+      case 'EXTENSION':
+        return EXTENSION;
       case 'FIELD':
         return FIELD;
       case 'FIELD_STATIC':
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 00b690a..3baa946 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.32.8';
+const String PROTOCOL_VERSION = '1.32.9';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -138,7 +138,11 @@
 const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_COMPLETION_MODE =
+    'completionMode';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_INVOCATION_COUNT =
+    'invocationCount';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_MAX_RESULTS = 'maxResults';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS2_TIMEOUT = 'timeout';
@@ -167,8 +171,6 @@
     'subscriptions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_IS_INCOMPLETE =
     'isIncomplete';
-const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_LIBRARY_URIS_TO_IMPORT =
-    'libraryUrisToImport';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_OFFSET =
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 c375b0c..413c551 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -4698,6 +4698,15 @@
   /// to true.
   int maxResults;
 
+  /// The mode of code completion being invoked. If no value is provided, BASIC
+  /// will be assumed. BASIC is also the only currently supported.
+  CompletionMode? completionMode;
+
+  /// The number of times that the user has invoked code completion at the same
+  /// code location, counting from 1. If no value is provided, 1 will be
+  /// assumed.
+  int? invocationCount;
+
   /// The approximate time in milliseconds that the server should spend. The
   /// server will perform some steps anyway, even if it takes longer than the
   /// specified timeout. This field is intended to be used for benchmarking,
@@ -4705,7 +4714,7 @@
   int? timeout;
 
   CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults,
-      {this.timeout});
+      {this.completionMode, this.invocationCount, this.timeout});
 
   factory CompletionGetSuggestions2Params.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4730,11 +4739,23 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'maxResults');
       }
+      CompletionMode? completionMode;
+      if (json.containsKey('completionMode')) {
+        completionMode = CompletionMode.fromJson(
+            jsonDecoder, jsonPath + '.completionMode', json['completionMode']);
+      }
+      int? invocationCount;
+      if (json.containsKey('invocationCount')) {
+        invocationCount = jsonDecoder.decodeInt(
+            jsonPath + '.invocationCount', json['invocationCount']);
+      }
       int? timeout;
       if (json.containsKey('timeout')) {
         timeout = jsonDecoder.decodeInt(jsonPath + '.timeout', json['timeout']);
       }
       return CompletionGetSuggestions2Params(file, offset, maxResults,
+          completionMode: completionMode,
+          invocationCount: invocationCount,
           timeout: timeout);
     } else {
       throw jsonDecoder.mismatch(
@@ -4753,6 +4774,14 @@
     result['file'] = file;
     result['offset'] = offset;
     result['maxResults'] = maxResults;
+    var completionMode = this.completionMode;
+    if (completionMode != null) {
+      result['completionMode'] = completionMode.toJson();
+    }
+    var invocationCount = this.invocationCount;
+    if (invocationCount != null) {
+      result['invocationCount'] = invocationCount;
+    }
     var timeout = this.timeout;
     if (timeout != null) {
       result['timeout'] = timeout;
@@ -4774,6 +4803,8 @@
       return file == other.file &&
           offset == other.offset &&
           maxResults == other.maxResults &&
+          completionMode == other.completionMode &&
+          invocationCount == other.invocationCount &&
           timeout == other.timeout;
     }
     return false;
@@ -4784,6 +4815,8 @@
         file,
         offset,
         maxResults,
+        completionMode,
+        invocationCount,
         timeout,
       );
 }
@@ -4794,7 +4827,6 @@
 ///   "replacementOffset": int
 ///   "replacementLength": int
 ///   "suggestions": List<CompletionSuggestion>
-///   "libraryUrisToImport": List<String>
 ///   "isIncomplete": bool
 /// }
 ///
@@ -4820,31 +4852,16 @@
   /// (if isIncomplete was true).
   ///
   /// This list contains suggestions from both imported, and not yet imported
-  /// libraries. Items from not yet imported libraries will have
-  /// libraryUriToImportIndex set, which is an index into the
-  /// libraryUrisToImport in this response.
+  /// libraries. Items from not yet imported libraries will have isNotImported
+  /// set to true.
   List<CompletionSuggestion> suggestions;
 
-  /// The list of libraries with declarations that are not yet available in the
-  /// file where completion was requested, most often because the library is
-  /// not yet imported. The declarations still might be included into the
-  /// suggestions, and the client should use getSuggestionDetails2 on selection
-  /// to make the library available in the file.
-  ///
-  /// Each item is the URI of a library, such as package:foo/bar.dart or
-  /// file:///home/me/workspace/foo/test/bar_test.dart.
-  List<String> libraryUrisToImport;
-
   /// True if the number of suggestions after filtering was greater than the
   /// requested maxResults.
   bool isIncomplete;
 
-  CompletionGetSuggestions2Result(
-      this.replacementOffset,
-      this.replacementLength,
-      this.suggestions,
-      this.libraryUrisToImport,
-      this.isIncomplete);
+  CompletionGetSuggestions2Result(this.replacementOffset,
+      this.replacementLength, this.suggestions, this.isIncomplete);
 
   factory CompletionGetSuggestions2Result.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -4874,15 +4891,6 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'suggestions');
       }
-      List<String> libraryUrisToImport;
-      if (json.containsKey('libraryUrisToImport')) {
-        libraryUrisToImport = jsonDecoder.decodeList(
-            jsonPath + '.libraryUrisToImport',
-            json['libraryUrisToImport'],
-            jsonDecoder.decodeString);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'libraryUrisToImport');
-      }
       bool isIncomplete;
       if (json.containsKey('isIncomplete')) {
         isIncomplete = jsonDecoder.decodeBool(
@@ -4890,8 +4898,8 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'isIncomplete');
       }
-      return CompletionGetSuggestions2Result(replacementOffset,
-          replacementLength, suggestions, libraryUrisToImport, isIncomplete);
+      return CompletionGetSuggestions2Result(
+          replacementOffset, replacementLength, suggestions, isIncomplete);
     } else {
       throw jsonDecoder.mismatch(
           jsonPath, 'completion.getSuggestions2 result', json);
@@ -4913,7 +4921,6 @@
     result['suggestions'] = suggestions
         .map((CompletionSuggestion value) => value.toJson())
         .toList();
-    result['libraryUrisToImport'] = libraryUrisToImport;
     result['isIncomplete'] = isIncomplete;
     return result;
   }
@@ -4933,8 +4940,6 @@
           replacementLength == other.replacementLength &&
           listEqual(suggestions, other.suggestions,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
-          listEqual(libraryUrisToImport, other.libraryUrisToImport,
-              (String a, String b) => a == b) &&
           isIncomplete == other.isIncomplete;
     }
     return false;
@@ -4945,7 +4950,6 @@
         replacementOffset,
         replacementLength,
         suggestions,
-        libraryUrisToImport,
         isIncomplete,
       );
 }
@@ -5090,6 +5094,58 @@
   int get hashCode => id.hashCode;
 }
 
+/// CompletionMode
+///
+/// enum {
+///   BASIC
+///   SMART
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionMode implements Enum {
+  /// Basic code completion invocation type, and the default for this
+  /// enumeration.
+  static const CompletionMode BASIC = CompletionMode._('BASIC');
+
+  /// Smart code completion, currently not implemented.
+  static const CompletionMode SMART = CompletionMode._('SMART');
+
+  /// A list containing all of the enum values that are defined.
+  static const List<CompletionMode> VALUES = <CompletionMode>[BASIC, SMART];
+
+  @override
+  final String name;
+
+  const CompletionMode._(this.name);
+
+  factory CompletionMode(String name) {
+    switch (name) {
+      case 'BASIC':
+        return BASIC;
+      case 'SMART':
+        return SMART;
+    }
+    throw Exception('Illegal enum value: $name');
+  }
+
+  factory CompletionMode.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    if (json is String) {
+      try {
+        return CompletionMode(json);
+      } catch (_) {
+        // Fall through
+      }
+    }
+    throw jsonDecoder.mismatch(jsonPath, 'CompletionMode', json);
+  }
+
+  @override
+  String toString() => 'CompletionMode.$name';
+
+  String toJson() => name;
+}
+
 /// completion.registerLibraryPaths params
 ///
 /// {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index a6f4d42..65409ce 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,6 +1,11 @@
-## 3.1.0-dev
+## 3.2.0
+* Deprecated `changes` getter in `File` and `Folder`, use `watch()` instead.
+
+## 3.1.0
 * New internal API for `package:dart_style`.
 * Removed deprecated non-API `MockSdk` class.
+* Removed deprecated `AnalysisDriver` constructor.
+* Updated the current language version to `2.17`.
 
 ## 3.0.0
 * Removed deprecated `DartType.aliasElement/aliasArguments`.
diff --git a/pkg/analyzer/README.md b/pkg/analyzer/README.md
index d35c78b..6f5102e 100644
--- a/pkg/analyzer/README.md
+++ b/pkg/analyzer/README.md
@@ -3,7 +3,7 @@
 This package provides a library that performs static analysis
 of Dart code. It is useful for tool integration and embedding.
 
-End-users should use the [dartanalyzer][] command-line tool
+End-users should use the [dart analyze][] command-line tool
 to analyze their Dart code.
 
 Integrators that want to add Dart support to their editor
@@ -14,7 +14,7 @@
 
 ## Configuring the analyzer
 
-Both `dartanalyzer` and Dart Analysis Server can be configured with an
+Both `dart analyze` and Dart Analysis Server can be configured with an
 `analysis_options.yaml` file (using an `.analysis_options` file is deprecated).
 This YAML file can control which files and paths are analyzed,
 which lints are applied, and more.
@@ -24,7 +24,7 @@
 
 The analysis options file should live at the root of your project (for example,
 next to your `pubspec.yaml`). Different embedders of analyzer, such as
-`dartanalyzer` or Dart Analysis Server, may choose to find the file in various
+`dart analyze` or Dart Analysis Server, may choose to find the file in various
 different ways. Consult their documentation to learn more.
 
 Here is an example file that instructs the analyzer to ignore two files:
@@ -71,7 +71,7 @@
 Many tools embed this library, such as:
 
 * [dart format] - a formatter for Dart code
-* [dartdoc] - a documentation generator for Dart code
+* [dart doc] - a documentation generator for Dart code
 * [Dart Analysis Server][analysis_sever] - a stateful server that supports IDEs and editors
 
 ## Support
@@ -97,12 +97,12 @@
 See the [LICENSE] file.
 
 [serverapi]: https://htmlpreview.github.io/?https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/doc/api.html
-[dartanalyzer]: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer_cli#dartanalyzer
+[dart analyze]: https://dart.dev/tools/dart-analyze
 [list]: https://groups.google.com/a/dartlang.org/forum/#!forum/analyzer-discuss
 [lintrules]: https://dart-lang.github.io/linter/lints/
 [glob]: https://pub.dev/packages/glob
 [LICENSE]: https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/LICENSE
 [dart format]: https://github.com/dart-lang/dart_style
-[dartdoc]: https://github.com/dart-lang/dartdoc
+[dart doc]: https://github.com/dart-lang/dartdoc
 [analysis_sever]: https://github.com/dart-lang/sdk/tree/main/pkg/analysis_server
 [custom_analysis]: https://dart.dev/guides/language/analysis-options
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index a0b7a9c..748df11 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -402,6 +402,8 @@
 
   R? visitConstructorReference(ConstructorReference node);
 
+  R? visitConstructorSelector(ConstructorSelector node);
+
   R? visitContinueStatement(ContinueStatement node);
 
   R? visitDeclaredIdentifier(DeclaredIdentifier node);
@@ -418,6 +420,8 @@
 
   R? visitEmptyStatement(EmptyStatement node);
 
+  R? visitEnumConstantArguments(EnumConstantArguments node);
+
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node);
 
   R? visitEnumDeclaration(EnumDeclaration node);
@@ -1365,6 +1369,20 @@
   ConstructorElement? get staticElement;
 }
 
+/// The name of a constructor being invoked.
+///
+///    constructorSelector ::=
+///        '.' identifier
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConstructorSelector implements AstNode {
+  /// Return the constructor name.
+  SimpleIdentifier get name;
+
+  /// Return the period before the constructor name.
+  Token get period;
+}
+
 /// A continue statement.
 ///
 ///    continueStatement ::=
@@ -1563,10 +1581,41 @@
   Token get semicolon;
 }
 
+/// The arguments part of an enum constant.
+///
+///    enumConstantArguments ::=
+///        [TypeArgumentList]? [ConstructorSelector]? [ArgumentList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class EnumConstantArguments implements AstNode {
+  /// Return the explicit arguments (there are always implicit `index` and
+  /// `name` leading arguments) to the invoked constructor.
+  ArgumentList get argumentList;
+
+  /// Return the selector of the constructor that is invoked by this enum
+  /// constant, or `null` if the default constructor is invoked.
+  ConstructorSelector? get constructorSelector;
+
+  /// Return the type arguments applied to the enclosing enum declaration
+  /// when invoking the constructor, or `null` if no type arguments were
+  /// provided.
+  TypeArgumentList? get typeArguments;
+}
+
 /// The declaration of an enum constant.
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class EnumConstantDeclaration implements Declaration {
+  /// Return the explicit arguments (there are always implicit `index` and
+  /// `name` leading arguments) to the invoked constructor, or `null` if this
+  /// constant does not provide any explicit arguments.
+  EnumConstantArguments? get arguments;
+
+  /// Return the constructor that is invoked by this enum constant, or `null`
+  /// if the AST structure has not been resolved, or if the constructor could
+  /// not be resolved.
+  ConstructorElement? get constructorElement;
+
   /// Return the name of the constant.
   SimpleIdentifier get name;
 }
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index a77a83e..309fcf1 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -230,6 +230,9 @@
       visitExpression(node);
 
   @override
+  R? visitConstructorSelector(ConstructorSelector node) => visitNode(node);
+
+  @override
   R? visitContinueStatement(ContinueStatement node) => visitStatement(node);
 
   R? visitDeclaration(Declaration node) => visitAnnotatedNode(node);
@@ -259,6 +262,9 @@
   R? visitEmptyStatement(EmptyStatement node) => visitStatement(node);
 
   @override
+  R? visitEnumConstantArguments(EnumConstantArguments node) => visitNode(node);
+
+  @override
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
       visitDeclaration(node);
 
@@ -803,6 +809,12 @@
   }
 
   @override
+  R? visitConstructorSelector(ConstructorSelector node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitContinueStatement(ContinueStatement node) {
     node.visitChildren(this);
     return null;
@@ -851,6 +863,12 @@
   }
 
   @override
+  R? visitEnumConstantArguments(EnumConstantArguments node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     node.visitChildren(this);
     return null;
@@ -1511,6 +1529,9 @@
   R? visitConstructorReference(ConstructorReference node) => null;
 
   @override
+  R? visitConstructorSelector(ConstructorSelector node) => null;
+
+  @override
   R? visitContinueStatement(ContinueStatement node) => null;
 
   @override
@@ -1535,6 +1556,9 @@
   R? visitEmptyStatement(EmptyStatement node) => null;
 
   @override
+  R? visitEnumConstantArguments(EnumConstantArguments node) => null;
+
+  @override
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node) => null;
 
   @override
@@ -1917,6 +1941,9 @@
   R? visitConstructorReference(ConstructorReference node) => _throw(node);
 
   @override
+  R? visitConstructorSelector(ConstructorSelector node) => _throw(node);
+
+  @override
   R? visitContinueStatement(ContinueStatement node) => _throw(node);
 
   @override
@@ -1941,6 +1968,9 @@
   R? visitEmptyStatement(EmptyStatement node) => _throw(node);
 
   @override
+  R? visitEnumConstantArguments(EnumConstantArguments node) => _throw(node);
+
+  @override
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node) => _throw(node);
 
   @override
@@ -2466,6 +2496,14 @@
   }
 
   @override
+  T? visitConstructorSelector(ConstructorSelector node) {
+    stopwatch.start();
+    T? result = _baseVisitor.visitConstructorSelector(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T? visitContinueStatement(ContinueStatement node) {
     stopwatch.start();
     T? result = _baseVisitor.visitContinueStatement(node);
@@ -2530,6 +2568,14 @@
   }
 
   @override
+  T? visitEnumConstantArguments(EnumConstantArguments node) {
+    stopwatch.start();
+    T? result = _baseVisitor.visitEnumConstantArguments(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T? visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     stopwatch.start();
     T? result = _baseVisitor.visitEnumConstantDeclaration(node);
@@ -3387,6 +3433,9 @@
   R? visitConstructorReference(ConstructorReference node) => visitNode(node);
 
   @override
+  R? visitConstructorSelector(ConstructorSelector node) => visitNode(node);
+
+  @override
   R? visitContinueStatement(ContinueStatement node) => visitNode(node);
 
   @override
@@ -3412,6 +3461,9 @@
   R? visitEmptyStatement(EmptyStatement node) => visitNode(node);
 
   @override
+  R? visitEnumConstantArguments(EnumConstantArguments node) => visitNode(node);
+
+  @override
   R? visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
       visitNode(node);
 
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 25895fe..3555ef1 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -216,6 +216,10 @@
   CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
   CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
+  CompileTimeErrorCode
+      .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
+  CompileTimeErrorCode
+      .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS,
   CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
   CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
   CompileTimeErrorCode.INCONSISTENT_CASE_EXPRESSION_TYPES,
@@ -247,7 +251,6 @@
   CompileTimeErrorCode.INVALID_CAST_METHOD,
   CompileTimeErrorCode.INVALID_CAST_NEW_EXPR,
   CompileTimeErrorCode.INVALID_CONSTANT,
-  CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT,
   CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS,
   CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE,
@@ -256,6 +259,7 @@
   CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
   CompileTimeErrorCode.INVALID_OVERRIDE,
   CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS,
+  CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION,
   CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST,
   CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP,
   CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET,
@@ -282,16 +286,13 @@
   CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL,
   CompileTimeErrorCode.MISSING_DART_LIBRARY,
   CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
+  CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
   CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT,
   CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
   CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
   CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
   CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR,
-  CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
   CompileTimeErrorCode.MIXIN_DEFERRED_CLASS,
-  CompileTimeErrorCode.MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES,
-  CompileTimeErrorCode.MIXIN_INFERENCE_NO_MATCHING_CLASS,
-  CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
   CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
   CompileTimeErrorCode.MIXIN_INSTANTIATE,
   CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
@@ -364,6 +365,8 @@
   CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
   CompileTimeErrorCode.PART_OF_NON_PART,
   CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY,
+  CompileTimeErrorCode
+      .POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
   CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER,
   CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
   CompileTimeErrorCode.PREFIX_SHADOWED_BY_LOCAL_DECLARATION,
@@ -402,6 +405,9 @@
   CompileTimeErrorCode.SHARED_DEFERRED_PREFIX,
   CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
   CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+  CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+  CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
+  CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
   CompileTimeErrorCode.SUPER_IN_EXTENSION,
   CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT,
   CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 0a2bd5d..96f5b84 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -12,7 +12,13 @@
 
 /// [File]s are leaf [Resource]s which contain data.
 abstract class File implements Resource {
-  /// Watch for changes to this file
+  /// Watch for changes to this file.
+  ///
+  /// File watchers are initialized asynchronously so modifications made for a
+  /// short period after calling this getter may be lost. Use [watch()] and
+  /// await the `ready` [Future] that completes once initialization is
+  /// complete.
+  @Deprecated('Use watch() instead')
   Stream<WatchEvent> get changes;
 
   /// Synchronously get the length of the file.
@@ -47,6 +53,13 @@
   /// an exception is thrown.
   File renameSync(String newPath);
 
+  /// Watch for changes to this file.
+  ///
+  /// Watchers are initialized asynchronously. Until [ResourceWatcher.ready]
+  /// completes, events are not guaranteed.
+  @override
+  ResourceWatcher watch();
+
   /// Synchronously write the given [bytes] to the file. The new content will
   /// replace any existing content.
   ///
@@ -75,6 +88,12 @@
 abstract class Folder implements Resource {
   /// Watch for changes to the files inside this folder (and in any nested
   /// folders, including folders reachable via links).
+  ///
+  /// Folder watchers are initialized asynchronously so modifications made for a
+  /// short period after calling this getter may be lost. Use [watch()] and
+  /// await the `ready` [Future] that completes once initialization is
+  /// complete.
+  @Deprecated('Use watch() instead')
   Stream<WatchEvent> get changes;
 
   /// Return `true` if this folder is a file system root.
@@ -120,6 +139,14 @@
   ///
   /// On I/O errors, this will throw [FileSystemException].
   List<Resource> getChildren();
+
+  /// Watch for changes to the files inside this folder (and in any nested
+  /// folders, including folders reachable via links).
+  ///
+  /// Watchers are initialized asynchronously. Until [ResourceWatcher.ready]
+  /// completes, events are not guaranteed.
+  @override
+  ResourceWatcher watch();
 }
 
 /// The abstract class [Resource] is an abstraction of file or folder.
@@ -169,6 +196,9 @@
 
   /// Return a Uri representing this resource.
   Uri toUri();
+
+  /// Watch for changes to this resource.
+  ResourceWatcher watch();
 }
 
 /// Instances of the class [ResourceProvider] convert [String] paths into
@@ -205,6 +235,24 @@
   Folder? getStateLocation(String pluginId);
 }
 
+/// Abstraction over a [Watcher] that has a [Future] to indicate when the
+/// watcher is ready.
+///
+/// The [ready] event will not fire until a listener has been set up on
+/// [changes] and the watcher initialization is complete.
+class ResourceWatcher {
+  final Stream<WatchEvent> changes;
+
+  /// An event that fires when the watcher is fully initialized and ready to
+  /// produce events.
+  ///
+  /// This event will not fire until a listener has been set up on [changes] and
+  /// the watcher initialization is complete.
+  final Future<void> ready;
+
+  ResourceWatcher(this.changes, this.ready);
+}
+
 extension FolderExtension on Folder {
   /// Return this folder and all its ancestors.
   Iterable<Folder> get withAncestors sync* {
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 21ffb07..53c2a00 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -9,8 +9,9 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/source_resource.dart';
+import 'package:meta/meta.dart';
 import 'package:path/path.dart' as pathos;
-import 'package:watcher/watcher.dart';
+import 'package:watcher/watcher.dart' hide Watcher;
 
 /// An in-memory implementation of [ResourceProvider].
 /// Use `/` as a path separator.
@@ -22,8 +23,20 @@
 
   final pathos.Context _pathContext;
 
-  MemoryResourceProvider({pathos.Context? context})
-      : _pathContext = context ??= pathos.style == pathos.Style.windows
+  /// An artificial delay that's waited when initializing watchers.
+  ///
+  /// This allows mirroring how the real fs watcher works, where events may be
+  /// lost between creating the watcher and its `ready` event firing.
+  ///
+  /// Like the real file watcher, the `ready` event also requires a listener
+  /// to be attached before it will fire.
+  @visibleForTesting
+  final Duration? delayWatcherInitialization;
+
+  MemoryResourceProvider({
+    pathos.Context? context,
+    this.delayWatcherInitialization,
+  }) : _pathContext = context ??= pathos.style == pathos.Style.windows
             // On Windows, ensure that the current drive matches
             // the drive inserted by MemoryResourceProvider.convertPath
             // so that packages are mapped to the correct drive
@@ -567,21 +580,7 @@
 
   _MemoryResource(this.provider, this.path);
 
-  Stream<WatchEvent> get changes {
-    StreamController<WatchEvent> streamController =
-        StreamController<WatchEvent>();
-    if (!provider._pathToWatchers.containsKey(path)) {
-      provider._pathToWatchers[path] = <StreamController<WatchEvent>>[];
-    }
-    provider._pathToWatchers[path]!.add(streamController);
-    streamController.done.then((_) {
-      provider._pathToWatchers[path]!.remove(streamController);
-      if (provider._pathToWatchers[path]!.isEmpty) {
-        provider._pathToWatchers.remove(path);
-      }
-    });
-    return streamController.stream;
-  }
+  Stream<WatchEvent> get changes => watch().changes;
 
   @override
   int get hashCode => path.hashCode;
@@ -608,6 +607,50 @@
 
   @override
   Uri toUri() => provider.pathContext.toUri(path);
+
+  /// Watch for changes to the files inside this folder (and in any nested
+  /// folders, including folders reachable via links).
+  ///
+  /// If [provider.delayWatcherInitialization] is not `null`, this method will
+  /// wait for this amount of time before it starts capturing/streaming events
+  /// to simulate the delay that occurs when initializing a real file system
+  /// watcher.
+  @override
+  ResourceWatcher watch() {
+    final streamController = StreamController<WatchEvent>();
+    final ready = Completer<void>();
+
+    /// A helper that sets up the watcher that may be called synchronously
+    /// or delayed, depending on the value of
+    /// [provider.delayWatcherInitialization].
+    void setupWatcher() {
+      var watchers = provider._pathToWatchers[path] ??= [];
+      watchers.add(streamController);
+      streamController.done.then((_) {
+        watchers.remove(streamController);
+        if (watchers.isEmpty) {
+          provider._pathToWatchers.remove(path);
+        }
+      });
+      ready.complete();
+    }
+
+    final delayWatcherInitialization = provider.delayWatcherInitialization;
+    if (delayWatcherInitialization != null) {
+      // Wrap this inside onListen so that (like the real watcher) it will only
+      // fire after a listener is attached.
+      streamController.onListen = () {
+        Future<void>.delayed(delayWatcherInitialization, () {
+          streamController.onListen = null;
+          setupWatcher();
+        });
+      };
+    } else {
+      setupWatcher();
+    }
+
+    return ResourceWatcher(streamController.stream, ready.future);
+  }
 }
 
 class _ResourceData {}
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 00d6da8..2fe9521 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -123,7 +123,7 @@
       : super(provider, file);
 
   @override
-  Stream<WatchEvent> get changes => _file.changes;
+  Stream<WatchEvent> get changes => watch().changes;
 
   @override
   bool get exists => provider.hasOverlay(path) || _resource.exists;
@@ -204,6 +204,9 @@
   }
 
   @override
+  ResourceWatcher watch() => _file.watch();
+
+  @override
   void writeAsBytesSync(List<int> bytes) {
     writeAsStringSync(String.fromCharCodes(bytes));
   }
@@ -234,7 +237,7 @@
       : super(provider, folder);
 
   @override
-  Stream<WatchEvent> get changes => _folder.changes;
+  Stream<WatchEvent> get changes => watch().changes;
 
   @override
   bool get exists => provider._hasOverlayIn(path) || _resource.exists;
@@ -313,6 +316,9 @@
     }
     return children.values.toList();
   }
+
+  @override
+  ResourceWatcher watch() => _folder.watch();
 }
 
 /// The base class for resources from an [OverlayResourceProvider].
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index bc4791d..5a2c317 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -97,7 +97,7 @@
   _PhysicalFile(io.File file) : super(file);
 
   @override
-  Stream<WatchEvent> get changes => FileWatcher(_entry.path).events;
+  Stream<WatchEvent> get changes => watch().changes;
 
   @override
   int get lengthSync {
@@ -180,6 +180,12 @@
   Uri toUri() => Uri.file(path);
 
   @override
+  ResourceWatcher watch() {
+    final watcher = FileWatcher(_entry.path);
+    return ResourceWatcher(watcher.events, watcher.ready);
+  }
+
+  @override
   void writeAsBytesSync(List<int> bytes) {
     try {
       _file.writeAsBytesSync(bytes);
@@ -203,14 +209,7 @@
   _PhysicalFolder(io.Directory directory) : super(directory);
 
   @override
-  Stream<WatchEvent> get changes =>
-      DirectoryWatcher(_entry.path).events.handleError((Object error) {},
-          test: (error) =>
-              error is io.FileSystemException &&
-              // Don't suppress "Directory watcher closed," so the outer
-              // listener can see the interruption & act on it.
-              !error.message
-                  .startsWith("Directory watcher closed unexpectedly"));
+  Stream<WatchEvent> get changes => watch().changes;
 
   @override
   bool get isRoot {
@@ -308,6 +307,18 @@
 
   @override
   Uri toUri() => Uri.directory(path);
+
+  @override
+  ResourceWatcher watch() {
+    final watcher = DirectoryWatcher(_entry.path);
+    final events = watcher.events.handleError((Object error) {},
+        test: (error) =>
+            error is io.FileSystemException &&
+            // Don't suppress "Directory watcher closed," so the outer
+            // listener can see the interruption & act on it.
+            !error.message.startsWith("Directory watcher closed unexpectedly"));
+    return ResourceWatcher(events, watcher.ready);
+  }
 }
 
 /// A `dart:io` based implementation of [Resource].
diff --git a/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart b/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
index 9becaf1..be9069c 100644
--- a/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
+++ b/pkg/analyzer/lib/src/clients/build_resolvers/build_resolvers.dart
@@ -51,7 +51,7 @@
 
   var logger = PerformanceLog(null);
   var scheduler = AnalysisDriverScheduler(logger);
-  var driver = AnalysisDriver.tmp1(
+  var driver = AnalysisDriver(
     scheduler: scheduler,
     logger: logger,
     resourceProvider: resourceProvider,
diff --git a/pkg/analyzer/lib/src/context/context_root.dart b/pkg/analyzer/lib/src/context/context_root.dart
deleted file mode 100644
index 5155947..0000000
--- a/pkg/analyzer/lib/src/context/context_root.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:path/path.dart' as path;
-
-/// Information about the root directory associated with an analysis context.
-///
-/// Clients may not extend, implement or mix-in this class.
-class ContextRoot {
-  /// The path context to use when manipulating paths.
-  final path.Context pathContext;
-
-  /// The absolute path of the root directory containing the files to be
-  /// analyzed.
-  final String root;
-
-  /// A list of the absolute paths of files and directories within the root
-  /// directory that should not be analyzed.
-  final List<String> exclude;
-
-  /// An informative value for the file path that the analysis options were read
-  /// from. This value can be `null` if there is no analysis options file or if
-  /// the location of the file has not yet been discovered.
-  String? optionsFilePath;
-
-  /// Initialize a newly created context root.
-  ContextRoot(this.root, this.exclude, {required this.pathContext});
-
-  @override
-  int get hashCode => Object.hash(root, exclude);
-
-  @override
-  bool operator ==(Object other) {
-    if (other is ContextRoot) {
-      return root == other.root &&
-          _listEqual(exclude, other.exclude, (String a, String b) => a == b);
-    }
-    return false;
-  }
-
-  /// Return `true` if the file with the given [filePath] is contained within
-  /// this context root. A file contained in a context root if it is within the
-  /// context [root] neither explicitly excluded or within one of the excluded
-  /// directories.
-  bool containsFile(String filePath) {
-    if (!pathContext.isWithin(root, filePath)) {
-      return false;
-    }
-    for (String excluded in exclude) {
-      if (filePath == excluded || pathContext.isWithin(excluded, filePath)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /// Compare the lists [listA] and [listB], using [itemEqual] to compare list
-  /// elements.
-  bool _listEqual<T>(
-      List<T>? listA, List<T>? listB, bool Function(T a, T b) itemEqual) {
-    if (listA == null) {
-      return listB == null;
-    }
-    if (listB == null) {
-      return false;
-    }
-    if (listA.length != listB.length) {
-      return false;
-    }
-    for (int i = 0; i < listA.length; i++) {
-      if (!itemEqual(listA[i], listB[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index db6b26d..a9c0df3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -95,7 +95,7 @@
       updateAnalysisOptions(options);
     }
 
-    var driver = AnalysisDriver.tmp1(
+    var driver = AnalysisDriver(
       scheduler: scheduler,
       logger: performanceLog,
       resourceProvider: resourceProvider,
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 8b728b5..165e57f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
@@ -83,7 +82,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 193;
+  static const int DATA_VERSION = 201;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
@@ -224,12 +223,7 @@
   /// Whether resolved units should be indexed.
   final bool enableIndex;
 
-  /// The current analysis session.
-  late final AnalysisSessionImpl _currentSession = AnalysisSessionImpl(this);
-
-  /// The current library context, consistent with the [_currentSession].
-  ///
-  /// TODO(scheglov) We probably should tie it into the session.
+  /// The context in which libraries should be analyzed.
   LibraryContext? _libraryContext;
 
   /// Whether `dart:core` has been transitively discovered.
@@ -243,42 +237,7 @@
   ///
   /// The given [SourceFactory] is cloned to ensure that it does not contain a
   /// reference to a [AnalysisContext] in which it could have been used.
-  @Deprecated('Use AnalysisDriver.tmp1() instead')
-  factory AnalysisDriver(
-    AnalysisDriverScheduler scheduler,
-    PerformanceLog logger,
-    ResourceProvider resourceProvider,
-    ByteStore byteStore,
-    // ignore: avoid_unused_constructor_parameters
-    FileContentOverlay? contentOverlay,
-    // ignore: avoid_unused_constructor_parameters
-    ContextRoot? contextRoot,
-    SourceFactory sourceFactory,
-    AnalysisOptionsImpl analysisOptions, {
-    Packages? packages,
-    bool enableIndex = false,
-    SummaryDataStore? externalSummaries,
-    bool retainDataForTesting = false,
-  }) {
-    return AnalysisDriver.tmp1(
-      scheduler: scheduler,
-      logger: logger,
-      resourceProvider: resourceProvider,
-      byteStore: byteStore,
-      sourceFactory: sourceFactory,
-      analysisOptions: analysisOptions,
-      packages: packages ?? Packages.empty,
-      enableIndex: enableIndex,
-      externalSummaries: externalSummaries,
-      retainDataForTesting: retainDataForTesting,
-    );
-  }
-
-  /// Create a new instance of [AnalysisDriver].
-  ///
-  /// The given [SourceFactory] is cloned to ensure that it does not contain a
-  /// reference to a [AnalysisContext] in which it could have been used.
-  AnalysisDriver.tmp1({
+  AnalysisDriver({
     required AnalysisDriverScheduler scheduler,
     required PerformanceLog logger,
     required ResourceProvider resourceProvider,
@@ -309,6 +268,37 @@
     _search = Search(this);
   }
 
+  /// Create a new instance of [AnalysisDriver].
+  ///
+  /// The given [SourceFactory] is cloned to ensure that it does not contain a
+  /// reference to a [AnalysisContext] in which it could have been used.
+  @Deprecated('Use the unnamed constructor instead')
+  AnalysisDriver.tmp1({
+    required AnalysisDriverScheduler scheduler,
+    required PerformanceLog logger,
+    required ResourceProvider resourceProvider,
+    required ByteStore byteStore,
+    required SourceFactory sourceFactory,
+    required AnalysisOptionsImpl analysisOptions,
+    required Packages packages,
+    FileContentCache? fileContentCache,
+    bool enableIndex = false,
+    SummaryDataStore? externalSummaries,
+    bool retainDataForTesting = false,
+  }) : this(
+          scheduler: scheduler,
+          logger: logger,
+          resourceProvider: resourceProvider,
+          byteStore: byteStore,
+          sourceFactory: sourceFactory,
+          analysisOptions: analysisOptions,
+          packages: packages,
+          fileContentCache: fileContentCache,
+          enableIndex: enableIndex,
+          externalSummaries: externalSummaries,
+          retainDataForTesting: retainDataForTesting,
+        );
+
   /// Return the set of files explicitly added to analysis using [addFile].
   Set<String> get addedFiles => _fileTracker.addedFiles;
 
@@ -316,7 +306,9 @@
   AnalysisOptions get analysisOptions => _analysisOptions;
 
   /// Return the current analysis session.
-  AnalysisSessionImpl get currentSession => _currentSession;
+  AnalysisSessionImpl get currentSession {
+    return libraryContext.elementFactory.analysisSession;
+  }
 
   /// Return the stream that produces [ExceptionResult]s.
   Stream<ExceptionResult> get exceptions => _exceptionController.stream;
@@ -342,7 +334,7 @@
   LibraryContext get libraryContext {
     return _libraryContext ??= LibraryContext(
       testView: _testView.libraryContextTestView,
-      session: currentSession,
+      analysisSession: AnalysisSessionImpl(this),
       logger: _logger,
       byteStore: _byteStore,
       analysisOptions: _analysisOptions,
@@ -520,9 +512,7 @@
   /// periodically.
   @visibleForTesting
   void clearLibraryContext() {
-    _libraryContext?.invalidAllLibraries();
     _libraryContext = null;
-    _currentSession.clearHierarchies();
   }
 
   /// Some state on which analysis depends has changed, so the driver needs to be
@@ -659,7 +649,7 @@
 
     FileState file = _fileTracker.getFile(path);
     return FileResultImpl(
-        _currentSession, path, file.uri, file.lineInfo, file.isPart);
+        currentSession, path, file.uri, file.lineInfo, file.isPart);
   }
 
   /// Return the [FileResult] for the Dart file with the given [path].
@@ -1328,17 +1318,15 @@
     var unitElement = libraryContext.computeUnitElement(library, file)
         as CompilationUnitElementImpl;
 
-    var analyzer = LibraryAnalyzer(
-        analysisOptions as AnalysisOptionsImpl,
-        declaredVariables,
-        sourceFactory,
-        libraryContext.analysisContext,
-        libraryContext.elementFactory.libraryOfUri2(library.uriStr),
-        libraryContext.analysisSession.inheritanceManager,
-        library,
-        testingData: testingData);
-
-    var analysisResult = analyzer.analyzeForCompletion(
+    var analysisResult = LibraryAnalyzer(
+      analysisOptions as AnalysisOptionsImpl,
+      declaredVariables,
+      sourceFactory,
+      libraryContext.elementFactory.libraryOfUri2(library.uriStr),
+      libraryContext.elementFactory.analysisSession.inheritanceManager,
+      library,
+      testingData: testingData,
+    ).analyzeForCompletion(
       file: file,
       offset: offset,
       unitElement: unitElement,
@@ -1443,27 +1431,26 @@
 
         libraryContext.load2(library!);
 
-        LibraryAnalyzer analyzer = LibraryAnalyzer(
-            analysisOptions as AnalysisOptionsImpl,
-            declaredVariables,
-            sourceFactory,
-            libraryContext.analysisContext,
-            libraryContext.elementFactory.libraryOfUri2(library.uriStr),
-            libraryContext.analysisSession.inheritanceManager,
-            library,
-            testingData: testingData);
-        Map<FileState, UnitAnalysisResult> results = analyzer.analyze();
+        var results = LibraryAnalyzer(
+          analysisOptions as AnalysisOptionsImpl,
+          declaredVariables,
+          sourceFactory,
+          libraryContext.elementFactory.libraryOfUri2(library.uriStr),
+          libraryContext.elementFactory.analysisSession.inheritanceManager,
+          library,
+          testingData: testingData,
+        ).analyze();
 
         late Uint8List bytes;
         late CompilationUnit resolvedUnit;
-        for (FileState unitFile in results.keys) {
-          UnitAnalysisResult unitResult = results[unitFile]!;
+        for (var unitResult in results) {
           var unitBytes =
               _serializeResolvedUnit(unitResult.unit, unitResult.errors);
-          String unitSignature = _getResolvedUnitSignature(library, unitFile);
+          String unitSignature =
+              _getResolvedUnitSignature(library, unitResult.file);
           String unitKey = _getResolvedUnitKey(unitSignature);
           _byteStore.put(unitKey, unitBytes);
-          if (unitFile == file) {
+          if (unitResult.file == file) {
             bytes = unitBytes;
             resolvedUnit = unitResult.unit;
           }
@@ -1515,21 +1502,19 @@
       _testView.numOfAnalyzedLibraries++;
       libraryContext.load2(library);
 
-      LibraryAnalyzer analyzer = LibraryAnalyzer(
-          analysisOptions as AnalysisOptionsImpl,
-          declaredVariables,
-          sourceFactory,
-          libraryContext.analysisContext,
-          libraryContext.elementFactory.libraryOfUri2(library.uriStr),
-          libraryContext.analysisSession.inheritanceManager,
-          library,
-          testingData: testingData);
-      Map<FileState, UnitAnalysisResult> unitResults = analyzer.analyze();
+      var unitResults = LibraryAnalyzer(
+              analysisOptions as AnalysisOptionsImpl,
+              declaredVariables,
+              sourceFactory,
+              libraryContext.elementFactory.libraryOfUri2(library.uriStr),
+              libraryContext.elementFactory.analysisSession.inheritanceManager,
+              library,
+              testingData: testingData)
+          .analyze();
       var resolvedUnits = <ResolvedUnitResult>[];
 
-      for (var entry in unitResults.entries) {
-        var unitFile = entry.key;
-        var unitResult = entry.value;
+      for (var unitResult in unitResults) {
+        var unitFile = unitResult.file;
         resolvedUnits.add(
           ResolvedUnitResultImpl(
             currentSession,
@@ -1789,6 +1774,10 @@
     _libraryContext?.elementFactory.removeLibraries(
       affected.map((e) => e.uriStr).toSet(),
     );
+
+    _libraryContext?.elementFactory.replaceAnalysisSession(
+      AnalysisSessionImpl(this),
+    );
   }
 
   void _reportException(String path, Object exception, StackTrace stackTrace) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 1fda845..ee40393 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -8,7 +8,7 @@
 
 /// The current version of the Dart language (or, for non-stable releases, the
 /// version of the language currently in the process of being developed).
-const _currentVersion = '2.16.0';
+const _currentVersion = '2.17.0';
 
 /// A map containing information about all known experimental flags.
 final _knownFeatures = <String, ExperimentalFeature>{
@@ -365,7 +365,7 @@
   static const bool constant_update_2018 = true;
 
   /// Expiration status of the experiment "constructor-tearoffs"
-  static const bool constructor_tearoffs = false;
+  static const bool constructor_tearoffs = true;
 
   /// Expiration status of the experiment "control-flow-collections"
   static const bool control_flow_collections = true;
@@ -374,13 +374,13 @@
   static const bool enhanced_enums = false;
 
   /// Expiration status of the experiment "extension-methods"
-  static const bool extension_methods = false;
+  static const bool extension_methods = true;
 
   /// Expiration status of the experiment "extension-types"
   static const bool extension_types = false;
 
   /// Expiration status of the experiment "generic-metadata"
-  static const bool generic_metadata = false;
+  static const bool generic_metadata = true;
 
   /// Expiration status of the experiment "macros"
   static const bool macros = false;
@@ -389,10 +389,10 @@
   static const bool named_arguments_anywhere = false;
 
   /// Expiration status of the experiment "non-nullable"
-  static const bool non_nullable = false;
+  static const bool non_nullable = true;
 
   /// Expiration status of the experiment "nonfunction-type-aliases"
-  static const bool nonfunction_type_aliases = false;
+  static const bool nonfunction_type_aliases = true;
 
   /// Expiration status of the experiment "set-literals"
   static const bool set_literals = true;
@@ -407,7 +407,7 @@
   static const bool test_experiment = false;
 
   /// Expiration status of the experiment "triple-shift"
-  static const bool triple_shift = false;
+  static const bool triple_shift = true;
 
   /// Expiration status of the experiment "value-class"
   static const bool value_class = false;
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 9ce7dda..f9aebb6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -666,6 +666,20 @@
   }
 
   @override
+  visitFieldFormalParameter(FieldFormalParameter node) {
+    var element = node.declaredElement;
+    if (element is FieldFormalParameterElement) {
+      var field = element.field;
+      if (field != null) {
+        recordRelation(
+            field, IndexRelationKind.IS_WRITTEN_BY, node.identifier, true);
+      }
+    }
+
+    return super.visitFieldFormalParameter(node);
+  }
+
+  @override
   void visitImplementsClause(ImplementsClause node) {
     for (NamedType namedType in node.interfaces2) {
       recordSuperType(namedType, IndexRelationKind.IS_IMPLEMENTED_BY);
@@ -836,6 +850,20 @@
   }
 
   @override
+  visitSuperFormalParameter(SuperFormalParameter node) {
+    var element = node.declaredElement;
+    if (element is SuperFormalParameterElementImpl) {
+      var superParameter = element.superConstructorParameter;
+      if (superParameter != null) {
+        recordRelation(superParameter, IndexRelationKind.IS_REFERENCED_BY,
+            node.identifier, true);
+      }
+    }
+
+    return super.visitSuperFormalParameter(node);
+  }
+
+  @override
   void visitWithClause(WithClause node) {
     for (NamedType namedType in node.mixinTypes2) {
       recordSuperType(namedType, IndexRelationKind.IS_MIXED_IN_BY);
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 0b49b4e..347e551 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -51,7 +51,6 @@
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:analyzer/src/util/uri.dart';
-import 'package:pub_semver/pub_semver.dart';
 
 var timerLibraryAnalyzer = Stopwatch();
 var timerLibraryAnalyzerConst = Stopwatch();
@@ -72,17 +71,11 @@
 
 /// Analyzer of a single library.
 class LibraryAnalyzer {
-  /// A marker object used to prevent the initialization of
-  /// [_versionConstraintFromPubspec] when the previous initialization attempt
-  /// failed.
-  static final VersionRange noSpecifiedRange = VersionRange();
   final AnalysisOptionsImpl _analysisOptions;
   final DeclaredVariables _declaredVariables;
   final SourceFactory _sourceFactory;
   final FileState _library;
-
   final InheritanceManager3 _inheritance;
-  final AnalysisContext _context;
 
   final LibraryElementImpl _libraryElement;
 
@@ -92,16 +85,11 @@
   final Map<FileState, RecordingErrorListener> _errorListeners = {};
   final Map<FileState, ErrorReporter> _errorReporters = {};
   final TestingData? _testingData;
-  final List<UsedImportedElements> _usedImportedElementsList = [];
-  final List<UsedLocalElements> _usedLocalElementsList = [];
-
-  final Set<ConstantEvaluationTarget> _constants = {};
 
   LibraryAnalyzer(
       this._analysisOptions,
       this._declaredVariables,
       this._sourceFactory,
-      this._context,
       this._libraryElement,
       this._inheritance,
       this._library,
@@ -113,98 +101,25 @@
   TypeSystemImpl get _typeSystem => _libraryElement.typeSystem;
 
   /// Compute analysis results for all units of the library.
-  Map<FileState, UnitAnalysisResult> analyze() {
-    timerLibraryAnalyzer.start();
-    Map<FileState, CompilationUnitImpl> units = {};
-
-    // Parse all files.
-    timerLibraryAnalyzerFreshUnit.start();
-    for (FileState file in _library.libraryFiles) {
-      units[file] = _parse(file);
-    }
-    timerLibraryAnalyzerFreshUnit.stop();
-
-    // Resolve URIs in directives to corresponding sources.
-    FeatureSet featureSet = units[_library]!.featureSet;
-    units.forEach((file, unit) {
-      _validateFeatureSet(unit, featureSet);
-      _resolveUriBasedDirectives(file, unit);
-    });
-
-    timerLibraryAnalyzerResolve.start();
-    _resolveDirectives(units);
-
-    units.forEach((file, unit) {
-      _resolveFile(file, unit);
-    });
-    timerLibraryAnalyzerResolve.stop();
-
-    timerLibraryAnalyzerConst.start();
-    units.values.forEach(_findConstants);
-    _computeConstants();
-    timerLibraryAnalyzerConst.stop();
-
-    timerLibraryAnalyzerVerify.start();
-    units.forEach((file, unit) {
-      _computeVerifyErrors(file, unit);
-    });
-
-    if (_analysisOptions.hint) {
-      units.forEach((file, unit) {
-        {
-          var visitor = GatherUsedLocalElementsVisitor(_libraryElement);
-          unit.accept(visitor);
-          _usedLocalElementsList.add(visitor.usedElements);
-        }
-        {
-          var visitor = GatherUsedImportedElementsVisitor(_libraryElement);
-          unit.accept(visitor);
-          _usedImportedElementsList.add(visitor.usedElements);
-        }
-      });
-      units.forEach((file, unit) {
-        _computeHints(file, unit);
-      });
-    }
-
-    if (_analysisOptions.lint) {
-      var allUnits = _library.libraryFiles
-          .map((file) => LinterContextUnit(file.content, units[file]!))
-          .toList();
-      for (int i = 0; i < allUnits.length; i++) {
-        _computeLints(_library.libraryFiles[i], allUnits[i], allUnits);
-      }
-    }
-
-    assert(units.values.every(LegacyTypeAsserter.assertLegacyTypes));
-
-    _checkForInconsistentLanguageVersionOverride(units);
-
-    // This must happen after all other diagnostics have been computed but
-    // before the list of diagnostics has been filtered.
-    for (var file in _library.libraryFiles) {
-      IgnoreValidator(
-        _getErrorReporter(file),
-        _getErrorListener(file).errors,
-        _fileToIgnoreInfo[file]!,
-        _fileToLineInfo[file]!,
-        _analysisOptions.unignorableNames,
-      ).reportErrors();
-    }
-
-    timerLibraryAnalyzerVerify.stop();
+  List<UnitAnalysisResult> analyze() {
+    var units = _parseAndResolve();
+    _computeDiagnostics(units);
 
     // Return full results.
-    Map<FileState, UnitAnalysisResult> results = {};
+    var results = <UnitAnalysisResult>[];
     units.forEach((file, unit) {
       List<AnalysisError> errors = _getErrorListener(file).errors;
       errors = _filterIgnoredErrors(file, errors);
-      results[file] = UnitAnalysisResult(file, unit, errors);
+      results.add(UnitAnalysisResult(file, unit, errors));
     });
     timerLibraryAnalyzer.stop();
     return results;
   }
 
+  /// Analyze [file] for a completion result.
+  ///
+  /// This method aims to avoid work that [analyze] does which would be
+  /// unnecessary for a completion request.
   AnalysisForCompletionResult analyzeForCompletion({
     required FileState file,
     required int offset,
@@ -264,8 +179,8 @@
             e.parent is MixinDeclaration;
       });
       if (nodeToResolve != null) {
-        var can = resolverVisitor.prepareForResolving(nodeToResolve);
-        if (can) {
+        var canResolveNode = resolverVisitor.prepareForResolving(nodeToResolve);
+        if (canResolveNode) {
           nodeToResolve.accept(resolverVisitor);
           return AnalysisForCompletionResult(
             parsedUnit: parsedUnit,
@@ -274,11 +189,11 @@
         }
       }
 
-      var resolvedUnits = analyze();
-      var resolvedUnit = resolvedUnits[file]!;
+      var units = _parseAndResolve();
+      var unit = units[file]!;
       return AnalysisForCompletionResult(
-        parsedUnit: resolvedUnit.unit,
-        resolvedNodes: [resolvedUnit.unit],
+        parsedUnit: unit,
+        resolvedNodes: [unit],
       );
     });
   }
@@ -333,12 +248,80 @@
   }
 
   /// Compute [_constants] in all units.
-  void _computeConstants() {
-    computeConstants(_typeProvider, _typeSystem, _declaredVariables,
-        _constants.toList(), _libraryElement.featureSet);
+  void _computeConstants(Iterable<CompilationUnitImpl> units) {
+    var constants = [
+      for (var unit in units) ..._findConstants(unit),
+    ];
+    computeConstants(_declaredVariables, constants, _libraryElement.featureSet);
   }
 
-  void _computeHints(FileState file, CompilationUnit unit) {
+  /// Compute diagnostics in [units], including errors and warnings, hints,
+  /// lints, and a few other cases.
+  void _computeDiagnostics(Map<FileState, CompilationUnitImpl> units) {
+    timerLibraryAnalyzerVerify.start();
+    units.forEach((file, unit) {
+      _computeVerifyErrors(file, unit);
+    });
+
+    if (_analysisOptions.hint) {
+      var usedImportedElements = <UsedImportedElements>[];
+      var usedLocalElements = <UsedLocalElements>[];
+      for (var unit in units.values) {
+        {
+          var visitor = GatherUsedLocalElementsVisitor(_libraryElement);
+          unit.accept(visitor);
+          usedLocalElements.add(visitor.usedElements);
+        }
+        {
+          var visitor = GatherUsedImportedElementsVisitor(_libraryElement);
+          unit.accept(visitor);
+          usedImportedElements.add(visitor.usedElements);
+        }
+      }
+      units.forEach((file, unit) {
+        _computeHints(
+          file,
+          unit,
+          usedImportedElements: usedImportedElements,
+          usedLocalElements: usedLocalElements,
+        );
+      });
+    }
+
+    if (_analysisOptions.lint) {
+      var allUnits = _library.libraryFiles
+          .map((file) => LinterContextUnit(file.content, units[file]!))
+          .toList();
+      for (int i = 0; i < allUnits.length; i++) {
+        _computeLints(_library.libraryFiles[i], allUnits[i], allUnits,
+            analysisOptions: _analysisOptions);
+      }
+    }
+
+    assert(units.values.every(LegacyTypeAsserter.assertLegacyTypes));
+
+    _checkForInconsistentLanguageVersionOverride(units);
+
+    // This must happen after all other diagnostics have been computed but
+    // before the list of diagnostics has been filtered.
+    for (var file in _library.libraryFiles) {
+      IgnoreValidator(
+        _getErrorReporter(file),
+        _getErrorListener(file).errors,
+        _fileToIgnoreInfo[file]!,
+        _fileToLineInfo[file]!,
+        _analysisOptions.unignorableNames,
+      ).reportErrors();
+    }
+    timerLibraryAnalyzerVerify.stop();
+  }
+
+  void _computeHints(
+    FileState file,
+    CompilationUnit unit, {
+    required List<UsedImportedElements> usedImportedElements,
+    required List<UsedLocalElements> usedLocalElements,
+  }) {
     AnalysisErrorListener errorListener = _getErrorListener(file);
     ErrorReporter errorReporter = _getErrorReporter(file);
 
@@ -365,7 +348,7 @@
         declaredVariables: _declaredVariables,
         typeSystem: _typeSystem,
         inheritanceManager: _inheritance,
-        analysisOptions: _context.analysisOptions,
+        analysisOptions: _analysisOptions,
         workspacePackage: _library.workspacePackage,
       ),
     );
@@ -383,19 +366,19 @@
     {
       ImportsVerifier verifier = ImportsVerifier();
       verifier.addImports(unit);
-      _usedImportedElementsList.forEach(verifier.removeUsedElements);
+      usedImportedElements.forEach(verifier.removeUsedElements);
       verifier.generateDuplicateImportHints(errorReporter);
       verifier.generateDuplicateShownHiddenNameHints(errorReporter);
       verifier.generateUnusedImportHints(errorReporter);
       verifier.generateUnusedShownNameHints(errorReporter);
       verifier.generateUnnecessaryImportHints(
-          errorReporter, _usedImportedElementsList);
+          errorReporter, usedImportedElements);
     }
 
     // Unused local elements.
     {
       UsedLocalElements usedElements =
-          UsedLocalElements.merge(_usedLocalElementsList);
+          UsedLocalElements.merge(usedLocalElements);
       UnusedLocalElementsVerifier visitor = UnusedLocalElementsVerifier(
           errorListener, usedElements, _inheritance, _libraryElement);
       unit.accept(visitor);
@@ -413,12 +396,16 @@
     }
   }
 
-  void _computeLints(FileState file, LinterContextUnit currentUnit,
-      List<LinterContextUnit> allUnits) {
+  void _computeLints(
+    FileState file,
+    LinterContextUnit currentUnit,
+    List<LinterContextUnit> allUnits, {
+    required AnalysisOptionsImpl analysisOptions,
+  }) {
     var unit = currentUnit.unit;
     var errorReporter = _getErrorReporter(file);
 
-    var enableTiming = _analysisOptions.enableTiming;
+    var enableTiming = analysisOptions.enableTiming;
     var nodeRegistry = NodeLintRegistry(enableTiming);
 
     var context = LinterContextImpl(
@@ -428,10 +415,10 @@
       _typeProvider,
       _typeSystem,
       _inheritance,
-      _analysisOptions,
+      analysisOptions,
       file.workspacePackage,
     );
-    for (var linter in _analysisOptions.lintRules) {
+    for (var linter in analysisOptions.lintRules) {
       linter.reporter = errorReporter;
       var timer = enableTiming ? lintRegistry.getTimer(linter) : null;
       timer?.start();
@@ -444,7 +431,7 @@
       LinterVisitor(
         nodeRegistry,
         LinterExceptionHandler(
-          propagateExceptions: _analysisOptions.propagateLinterExceptions,
+          propagateExceptions: analysisOptions.propagateLinterExceptions,
         ).logException,
       ),
     );
@@ -522,17 +509,6 @@
     return errors.where((AnalysisError e) => !isIgnored(e)).toList();
   }
 
-  /// Find constants to compute.
-  void _findConstants(CompilationUnit unit) {
-    ConstantFinder constantFinder = ConstantFinder();
-    unit.accept(constantFinder);
-    _constants.addAll(constantFinder.constantsToCompute);
-
-    var dependenciesFinder = ConstantExpressionsDependenciesFinder();
-    unit.accept(dependenciesFinder);
-    _constants.addAll(dependenciesFinder.dependencies);
-  }
-
   RecordingErrorListener _getErrorListener(FileState file) =>
       _errorListeners.putIfAbsent(file, () => RecordingErrorListener());
 
@@ -589,13 +565,47 @@
     String content = file.content;
     var unit = file.parse(errorListener);
 
-    LineInfo lineInfo = unit.lineInfo!;
-    _fileToLineInfo[file] = lineInfo;
+    _fileToLineInfo[file] = unit.lineInfo!;
     _fileToIgnoreInfo[file] = IgnoreInfo.forDart(unit, content);
 
     return unit;
   }
 
+  /// Parse and resolve all files in [_library].
+  Map<FileState, CompilationUnitImpl> _parseAndResolve() {
+    timerLibraryAnalyzer.start();
+    var units = <FileState, CompilationUnitImpl>{};
+
+    // Parse all files.
+    timerLibraryAnalyzerFreshUnit.start();
+    for (FileState file in _library.libraryFiles) {
+      units[file] = _parse(file);
+    }
+    timerLibraryAnalyzerFreshUnit.stop();
+
+    // Resolve URIs in directives to corresponding sources.
+    FeatureSet featureSet = units[_library]!.featureSet;
+    units.forEach((file, unit) {
+      _validateFeatureSet(unit, featureSet);
+      _resolveUriBasedDirectives(file, unit);
+    });
+
+    timerLibraryAnalyzerResolve.start();
+    _resolveDirectives(units);
+
+    units.forEach((file, unit) {
+      _resolveFile(file, unit);
+    });
+    timerLibraryAnalyzerResolve.stop();
+
+    timerLibraryAnalyzerConst.start();
+
+    _computeConstants(units.values);
+    timerLibraryAnalyzerConst.stop();
+
+    return units;
+  }
+
   void _resolveDirectives(Map<FileState, CompilationUnitImpl> units) {
     var definingCompilationUnit = units[_library]!;
     definingCompilationUnit.element = _libraryElement.definingCompilationUnit;
@@ -917,6 +927,19 @@
     }
   }
 
+  /// Find constants in [unit] to compute.
+  static List<ConstantEvaluationTarget> _findConstants(CompilationUnit unit) {
+    ConstantFinder constantFinder = ConstantFinder();
+    unit.accept(constantFinder);
+
+    var dependenciesFinder = ConstantExpressionsDependenciesFinder();
+    unit.accept(dependenciesFinder);
+    return [
+      ...constantFinder.constantsToCompute,
+      ...dependenciesFinder.dependencies,
+    ];
+  }
+
   static bool _hasEmptyCompletionContext(AstNode? node) {
     if (node is DoubleLiteral || node is IntegerLiteral) {
       return true;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 4795da1..c9ee80d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -39,8 +39,6 @@
   final LibraryContextTestView testView;
   final PerformanceLog logger;
   final ByteStore byteStore;
-  final AnalysisSessionImpl analysisSession;
-  final SummaryDataStore? externalSummaries;
   final SummaryDataStore store = SummaryDataStore([]);
 
   late final AnalysisContextImpl analysisContext;
@@ -48,21 +46,35 @@
 
   LibraryContext({
     required this.testView,
-    required AnalysisSessionImpl session,
+    required AnalysisSessionImpl analysisSession,
     required PerformanceLog logger,
     required ByteStore byteStore,
     required AnalysisOptionsImpl analysisOptions,
     required DeclaredVariables declaredVariables,
     required SourceFactory sourceFactory,
-    required this.externalSummaries,
+    required SummaryDataStore? externalSummaries,
   })  : logger = logger,
-        byteStore = byteStore,
-        analysisSession = session {
+        byteStore = byteStore {
     var synchronousSession =
         SynchronousSession(analysisOptions, declaredVariables);
     analysisContext = AnalysisContextImpl(synchronousSession, sourceFactory);
 
-    _createElementFactory();
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      analysisSession,
+      Reference.root(),
+    );
+    if (externalSummaries != null) {
+      for (var bundle in externalSummaries.bundles) {
+        elementFactory.addBundle(
+          BundleReader(
+            elementFactory: elementFactory,
+            resolutionBytes: bundle.resolutionBytes,
+            unitsInformativeBytes: {},
+          ),
+        );
+      }
+    }
   }
 
   /// Computes a [CompilationUnitElement] for the given library/unit pair.
@@ -86,11 +98,6 @@
     return elementFactory.libraryOfUriIfReady(uriStr);
   }
 
-  /// We are about to discard this context, mark all libraries invalid.
-  void invalidAllLibraries() {
-    elementFactory.invalidateAllLibraries();
-  }
-
   /// Load data required to access elements of the given [targetLibrary].
   void load2(FileState targetLibrary) {
     timerLoad2.start();
@@ -222,25 +229,6 @@
     timerLoad2.stop();
   }
 
-  void _createElementFactory() {
-    elementFactory = LinkedElementFactory(
-      analysisContext,
-      analysisSession,
-      Reference.root(),
-    );
-    if (externalSummaries != null) {
-      for (var bundle in externalSummaries!.bundles) {
-        elementFactory.addBundle(
-          BundleReader(
-            elementFactory: elementFactory,
-            resolutionBytes: bundle.resolutionBytes,
-            unitsInformativeBytes: {},
-          ),
-        );
-      }
-    }
-  }
-
   /// Ensure that type provider is created.
   void _createElementFactoryTypeProvider() {
     if (!analysisContext.hasTypeProvider) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 651e0f9..cdd7c72 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -682,7 +682,9 @@
       },
       searchedFiles,
     ));
-    if (parameter.isNamed || parameter.isOptionalPositional) {
+    if (parameter.isNamed ||
+        parameter.isOptionalPositional ||
+        parameter.enclosingElement is ConstructorElement) {
       results.addAll(await _searchReferences(parameter, searchedFiles));
     }
     return results;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index ca91eb4..5218135 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -2725,6 +2725,41 @@
   }
 }
 
+class ConstructorSelectorImpl extends AstNodeImpl
+    implements ConstructorSelector {
+  @override
+  final Token period;
+
+  @override
+  final SimpleIdentifierImpl name;
+
+  ConstructorSelectorImpl({
+    required this.period,
+    required this.name,
+  }) {
+    _becomeParentOf(name);
+  }
+
+  @override
+  Token get beginToken => period;
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => ChildEntities()
+    ..add(period)
+    ..add(name);
+
+  @override
+  Token get endToken => name.token;
+
+  @override
+  E? accept<E>(AstVisitor<E> visitor) {
+    return visitor.visitConstructorSelector(this);
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {}
+}
+
 /// A continue statement.
 ///
 ///    continueStatement ::=
@@ -3242,31 +3277,89 @@
   }
 }
 
+class EnumConstantArgumentsImpl extends AstNodeImpl
+    implements EnumConstantArguments {
+  @override
+  final TypeArgumentListImpl? typeArguments;
+
+  @override
+  final ConstructorSelectorImpl? constructorSelector;
+
+  @override
+  final ArgumentListImpl argumentList;
+
+  EnumConstantArgumentsImpl({
+    required this.typeArguments,
+    required this.constructorSelector,
+    required this.argumentList,
+  }) {
+    _becomeParentOf(typeArguments);
+    _becomeParentOf(constructorSelector);
+    _becomeParentOf(argumentList);
+  }
+
+  @override
+  Token get beginToken =>
+      (typeArguments ?? constructorSelector ?? argumentList).beginToken;
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => ChildEntities()
+    ..add(typeArguments)
+    ..add(constructorSelector)
+    ..add(argumentList);
+
+  @override
+  Token get endToken => argumentList.endToken;
+
+  @override
+  E? accept<E>(AstVisitor<E> visitor) {
+    return visitor.visitEnumConstantArguments(this);
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    typeArguments?.accept(visitor);
+    constructorSelector?.accept(visitor);
+    argumentList.accept(visitor);
+  }
+}
+
 /// The declaration of an enum constant.
 class EnumConstantDeclarationImpl extends DeclarationImpl
     implements EnumConstantDeclaration {
   /// The name of the constant.
   SimpleIdentifierImpl _name;
 
+  @override
+  final EnumConstantArgumentsImpl? arguments;
+
+  @override
+  ConstructorElement? constructorElement;
+
   /// Initialize a newly created enum constant declaration. Either or both of
-  /// the [comment] and [metadata] can be `null` if the constant does not have
-  /// the corresponding attribute. (Technically, enum constants cannot have
-  /// metadata, but we allow it for consistency.)
-  EnumConstantDeclarationImpl(
-      CommentImpl? comment, List<Annotation>? metadata, this._name)
-      : super(comment, metadata) {
+  /// the [documentationComment] and [metadata] can be `null` if the constant
+  /// does not have the corresponding attribute.
+  EnumConstantDeclarationImpl({
+    required CommentImpl? documentationComment,
+    required List<Annotation>? metadata,
+    required SimpleIdentifierImpl name,
+    required this.arguments,
+  })  : _name = name,
+        super(documentationComment, metadata) {
     _becomeParentOf(_name);
+    _becomeParentOf(arguments);
   }
 
   @override
-  Iterable<SyntacticEntity> get childEntities =>
-      super._childEntities..add(_name);
+  Iterable<SyntacticEntity> get childEntities => super._childEntities
+    ..add(_name)
+    ..add(arguments);
 
   @override
   FieldElement get declaredElement => _name.staticElement as FieldElement;
 
   @override
-  Token get endToken => _name.endToken;
+  Token get endToken => (arguments ?? _name).endToken;
 
   @override
   Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
@@ -3286,6 +3379,7 @@
   void visitChildren(AstVisitor visitor) {
     super.visitChildren(visitor);
     _name.accept(visitor);
+    arguments?.accept(visitor);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 806d84e..37cfef3 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -385,7 +385,11 @@
   EnumConstantDeclarationImpl enumConstantDeclaration(Comment? comment,
           List<Annotation>? metadata, SimpleIdentifier name) =>
       EnumConstantDeclarationImpl(
-          comment as CommentImpl?, metadata, name as SimpleIdentifierImpl);
+        documentationComment: comment as CommentImpl?,
+        metadata: metadata,
+        name: name as SimpleIdentifierImpl,
+        arguments: null,
+      );
 
   @Deprecated('Use enumDeclaration2() instead')
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/extensions.dart b/pkg/analyzer/lib/src/dart/ast/extensions.dart
index f30fcca..3df6b5d 100644
--- a/pkg/analyzer/lib/src/dart/ast/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/ast/extensions.dart
@@ -76,6 +76,39 @@
   return null;
 }
 
+extension AstNodeNullableExtension on AstNode? {
+  List<ClassMember> get classMembers {
+    final self = this;
+    if (self is ClassOrMixinDeclaration) {
+      return self.members;
+    } else if (self is EnumDeclaration) {
+      return self.members;
+    } else if (self is ExtensionDeclaration) {
+      return self.members;
+    } else {
+      throw UnimplementedError('(${self.runtimeType}) $self');
+    }
+  }
+}
+
+extension ConstructorDeclarationExtension on ConstructorDeclaration {
+  bool get isNonRedirectingGenerative {
+    // Must be generative.
+    if (externalKeyword != null || factoryKeyword != null) {
+      return false;
+    }
+
+    // Must be non-redirecting.
+    for (var initializer in initializers) {
+      if (initializer is RedirectingConstructorInvocation) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+}
+
 extension ExpressionExtension on Expression {
   /// Return the static type of this expression.
   ///
@@ -104,6 +137,14 @@
     return self;
   }
 
+  FormalParameterList get parentFormalParameterList {
+    var parent = this.parent;
+    if (parent is DefaultFormalParameter) {
+      parent = parent.parent;
+    }
+    return parent as FormalParameterList;
+  }
+
   AstNode get typeOrSelf {
     var self = this;
     if (self is SimpleFormalParameter) {
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index 294a89f..d2c7f88 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -249,6 +249,12 @@
   }
 
   @override
+  void visitConstructorSelector(ConstructorSelector node) {
+    _visitToken(node.period);
+    _visitNode(node.name);
+  }
+
+  @override
   void visitContinueStatement(ContinueStatement node) {
     sink.write('continue');
     _visitNode(node.label, prefix: ' ');
@@ -306,9 +312,17 @@
   }
 
   @override
+  void visitEnumConstantArguments(EnumConstantArguments node) {
+    _visitNode(node.typeArguments);
+    _visitNode(node.constructorSelector);
+    _visitNode(node.argumentList);
+  }
+
+  @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     _visitNodeList(node.metadata, separator: ' ', suffix: ' ');
     _visitNode(node.name);
+    _visitNode(node.arguments);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 4db6958..1aca07f 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -350,6 +350,13 @@
   }
 
   @override
+  bool visitConstructorSelector(ConstructorSelector node) {
+    var other = _other as ConstructorSelector;
+    return isEqualTokens(node.period, other.period) &&
+        isEqualNodes(node.name, other.name);
+  }
+
+  @override
   bool visitContinueStatement(ContinueStatement node) {
     ContinueStatement other = _other as ContinueStatement;
     return isEqualTokens(node.continueKeyword, other.continueKeyword) &&
@@ -415,6 +422,14 @@
   }
 
   @override
+  bool visitEnumConstantArguments(EnumConstantArguments node) {
+    var other = _other as EnumConstantArguments;
+    return isEqualNodes(node.typeArguments, other.typeArguments) &&
+        isEqualNodes(node.constructorSelector, other.constructorSelector) &&
+        isEqualNodes(node.argumentList, other.argumentList);
+  }
+
+  @override
   bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     EnumConstantDeclaration other = _other as EnumConstantDeclaration;
     return isEqualNodes(
@@ -1913,6 +1928,11 @@
   }
 
   @override
+  bool visitConstructorSelector(ConstructorSelector node) {
+    throw UnimplementedError();
+  }
+
+  @override
   bool visitContinueStatement(covariant ContinueStatementImpl node) {
     if (identical(node.label, _oldNode)) {
       node.label = _newNode as SimpleIdentifier;
@@ -1981,6 +2001,11 @@
   bool visitEmptyStatement(EmptyStatement node) => visitNode(node);
 
   @override
+  bool visitEnumConstantArguments(EnumConstantArguments node) {
+    throw UnimplementedError();
+  }
+
+  @override
   bool visitEnumConstantDeclaration(
       covariant EnumConstantDeclarationImpl node) {
     if (identical(node.name, _oldNode)) {
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index cb56ffe..b2b67c8 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -4,20 +4,14 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
 
 /// Compute values of the given [constants] with correct ordering.
-void computeConstants(
-    TypeProvider typeProvider,
-    TypeSystemImpl typeSystem,
-    DeclaredVariables declaredVariables,
-    List<ConstantEvaluationTarget> constants,
-    FeatureSet featureSet) {
+void computeConstants(DeclaredVariables declaredVariables,
+    List<ConstantEvaluationTarget> constants, FeatureSet featureSet) {
   var walker = _ConstantWalker(declaredVariables, featureSet);
 
   for (var constant in constants) {
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index bcbe8fa..9af29c4 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -103,8 +103,7 @@
     if (constKeyword != null) {
       _validateConstructorInitializers(node);
       if (node.factoryKeyword == null) {
-        _validateFieldInitializers(
-            node.parent as ClassOrMixinDeclaration, constKeyword);
+        _validateFieldInitializers(node.parent.classMembers, constKeyword);
       }
     }
     _validateDefaultValues(node.parameters);
@@ -545,12 +544,11 @@
   }
 
   /// Validates that the expressions of any field initializers in
-  /// [classDeclaration] are all compile-time constants. Since this is only
+  /// [members] are all compile-time constants. Since this is only
   /// required if the class has a constant constructor, the error is reported at
   /// [constKeyword], the const keyword on such a constant constructor.
   void _validateFieldInitializers(
-      ClassOrMixinDeclaration classDeclaration, Token constKeyword) {
-    NodeList<ClassMember> members = classDeclaration.members;
+      List<ClassMember> members, Token constKeyword) {
     for (ClassMember member in members) {
       if (member is FieldDeclaration && !member.isStatic) {
         for (VariableDeclaration variableDeclaration
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 514d859..72131f5 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -101,6 +101,17 @@
                 [dartObject.type, constant.type]);
           }
         }
+
+        if (dartObject != null) {
+          var enumConstant = _enumConstant(constant);
+          if (enumConstant != null) {
+            dartObject.updateEnumConstant(
+              index: enumConstant.index,
+              name: enumConstant.name,
+            );
+          }
+        }
+
         constant.evaluationResult =
             EvaluationResultImpl(dartObject, errorListener.errors);
       }
@@ -361,6 +372,21 @@
     return redirectedConstructor;
   }
 
+  static _EnumConstant? _enumConstant(VariableElementImpl element) {
+    if (element is ConstFieldElementImpl && element.isEnumConstant) {
+      var enum_ = element.enclosingElement;
+      if (enum_ is EnumElementImpl) {
+        var index = enum_.constants.indexOf(element);
+        assert(index >= 0);
+        return _EnumConstant(
+          index: index,
+          name: element.name,
+        );
+      }
+    }
+    return null;
+  }
+
   static DartObjectImpl _nullObject(LibraryElementImpl library) {
     return DartObjectImpl(
       library.typeSystem,
@@ -1917,6 +1943,16 @@
   }
 }
 
+class _EnumConstant {
+  final int index;
+  final String name;
+
+  _EnumConstant({
+    required this.index,
+    required this.name,
+  });
+}
+
 /// The result of evaluation the initializers declared on a const constructor.
 class _InitializersEvaluationResult {
   /// The result of a const evaluation of an initializer, if one was performed,
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index b6c4de1..ef76c24 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -932,6 +932,24 @@
     );
   }
 
+  /// Set the `index` and `_name` fields for this enum constant.
+  void updateEnumConstant({
+    required int index,
+    required String name,
+  }) {
+    var fields = _state.fields!;
+    fields['index'] = DartObjectImpl(
+      _typeSystem,
+      _typeSystem.typeProvider.intType,
+      IntState(index),
+    );
+    fields['_name'] = DartObjectImpl(
+      _typeSystem,
+      _typeSystem.typeProvider.stringType,
+      StringState(name),
+    );
+  }
+
   /// Throw an exception if the given [object]'s state does not represent a Type
   /// value.
   void _assertType(DartObjectImpl object) {
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index 27fbe85..2e58795 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -73,6 +73,7 @@
   void writeEnumElement(EnumElementImpl element) {
     _write('enum ');
     _write(element.displayName);
+    _writeTypeParameters(element.typeParameters);
   }
 
   void writeExecutableElement(ExecutableElement element, String name) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 43e9949..b79c1a0 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -21,7 +21,6 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
-import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/display_string_builder.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
@@ -47,6 +46,7 @@
 
 /// A concrete implementation of a [ClassElement].
 abstract class AbstractClassElementImpl extends _ExistingElementImpl
+    with TypeParameterizedElementMixin
     implements ClassElement {
   /// The type defined by the class.
   InterfaceType? _thisType;
@@ -122,6 +122,23 @@
     return _thisType!;
   }
 
+  set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement typeParameter in typeParameters) {
+      (typeParameter as TypeParameterElementImpl).enclosingElement = this;
+    }
+    _typeParameterElements = typeParameters;
+  }
+
+  @override
+  ConstructorElement? get unnamedConstructor {
+    for (ConstructorElement element in constructors) {
+      if (element.name.isEmpty) {
+        return element;
+      }
+    }
+    return null;
+  }
+
   @override
   T? accept<T>(ElementVisitor<T> visitor) => visitor.visitClassElement(this);
 
@@ -160,6 +177,20 @@
   }
 
   @override
+  ConstructorElement? getNamedConstructor(String name) {
+    if (name == 'new') {
+      // A constructor declared as `C.new` is unnamed, and is modeled as such.
+      name = '';
+    }
+    for (ConstructorElement element in constructors) {
+      if (element.name == name) {
+        return element;
+      }
+    }
+    return null;
+  }
+
+  @override
   PropertyAccessorElement? getSetter(String setterName) {
     return getSetterFromAccessors(setterName, accessors);
   }
@@ -412,8 +443,7 @@
 }
 
 /// An [AbstractClassElementImpl] which is a class.
-class ClassElementImpl extends AbstractClassElementImpl
-    with TypeParameterizedElementMixin {
+class ClassElementImpl extends AbstractClassElementImpl {
   /// The superclass of the class, or `null` for [Object].
   InterfaceType? _supertype;
 
@@ -441,9 +471,6 @@
   /// This callback is set during mixins inference to handle reentrant calls.
   List<InterfaceType>? Function(ClassElementImpl)? mixinInferenceCallback;
 
-  /// TODO(scheglov) implement as modifier
-  bool _isSimplyBounded = true;
-
   ElementLinkedData? linkedData;
 
   /// Initialize a newly created class element to have the given [name] at the
@@ -655,15 +682,13 @@
     setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication);
   }
 
-  /// TODO(scheglov) implement as modifier
   @override
   bool get isSimplyBounded {
-    return _isSimplyBounded;
+    return hasModifier(Modifier.SIMPLY_BOUNDED);
   }
 
-  /// TODO(scheglov) implement as modifier
   set isSimplyBounded(bool isSimplyBounded) {
-    _isSimplyBounded = isSimplyBounded;
+    setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded);
   }
 
   @override
@@ -762,34 +787,11 @@
     return super.typeParameters;
   }
 
-  /// Set the type parameters defined for this class to the given
-  /// [typeParameters].
-  set typeParameters(List<TypeParameterElement> typeParameters) {
-    for (TypeParameterElement typeParameter in typeParameters) {
-      (typeParameter as TypeParameterElementImpl).enclosingElement = this;
-    }
-    _typeParameterElements = typeParameters;
-  }
-
-  @override
-  ConstructorElement? get unnamedConstructor {
-    for (ConstructorElement element in constructors) {
-      if (element.name.isEmpty) {
-        return element;
-      }
-    }
-    return null;
-  }
-
   @override
   void appendTo(ElementDisplayStringBuilder builder) {
     builder.writeClassElement(this);
   }
 
-  @override
-  ConstructorElement? getNamedConstructor(String name) =>
-      getNamedConstructorFromList(name, constructors);
-
   void setLinkedData(Reference reference, ElementLinkedData linkedData) {
     this.reference = reference;
     reference.element = this;
@@ -951,20 +953,6 @@
       return implicitConstructor;
     }).toList(growable: false);
   }
-
-  static ConstructorElement? getNamedConstructorFromList(
-      String name, List<ConstructorElement> constructors) {
-    if (name == 'new') {
-      // A constructor declared as `C.new` is unnamed, and is modeled as such.
-      name = '';
-    }
-    for (ConstructorElement element in constructors) {
-      if (element.name == name) {
-        return element;
-      }
-    }
-    return null;
-  }
 }
 
 /// A concrete implementation of a [CompilationUnitElement].
@@ -1255,153 +1243,6 @@
   }
 }
 
-/// A field element representing an enum constant.
-class ConstFieldElementImpl_EnumValue extends ConstFieldElementImpl_ofEnum {
-  final int _index;
-
-  ConstFieldElementImpl_EnumValue(
-      EnumElementImpl enumElement, String name, this._index)
-      : super(enumElement, name);
-
-  @override
-  Expression? get constantInitializer => null;
-
-  @override
-  EvaluationResultImpl? get evaluationResult {
-    if (_evaluationResult == null) {
-      Map<String, DartObjectImpl> fieldMap = <String, DartObjectImpl>{
-        'index': DartObjectImpl(
-          library.typeSystem,
-          library.typeProvider.intType,
-          IntState(_index),
-        ),
-        // TODO(brianwilkerson) There shouldn't be a field with the same name as
-        //  the constant, but we can't remove it until a version of dartdoc that
-        //  doesn't depend on it has been published and pulled into the SDK. The
-        //  map entry below should be removed when
-        //  https://github.com/dart-lang/dartdoc/issues/2318 has been resolved.
-        name: DartObjectImpl(
-          library.typeSystem,
-          library.typeProvider.intType,
-          IntState(_index),
-        ),
-      };
-      DartObjectImpl value = DartObjectImpl(
-        library.typeSystem,
-        type,
-        GenericState(fieldMap),
-      );
-      _evaluationResult = EvaluationResultImpl(value);
-    }
-    return _evaluationResult;
-  }
-
-  @override
-  bool get hasInitializer => false;
-
-  @override
-  bool get isEnumConstant => true;
-
-  @override
-  Element get nonSynthetic => this;
-
-  @override
-  InterfaceType get type =>
-      ElementTypeProvider.current.getFieldType(this) as InterfaceType;
-
-  @override
-  InterfaceType get typeInternal => _enum.thisType;
-}
-
-/// The synthetic `values` field of an enum.
-class ConstFieldElementImpl_EnumValues extends ConstFieldElementImpl_ofEnum {
-  ConstFieldElementImpl_EnumValues(EnumElementImpl enumElement)
-      : super(enumElement, 'values') {
-    isSynthetic = true;
-  }
-
-  @override
-  EvaluationResultImpl get evaluationResult {
-    if (_evaluationResult == null) {
-      var constantValues = <DartObjectImpl>[];
-      for (FieldElement field in _enum.fields) {
-        if (field is ConstFieldElementImpl_EnumValue) {
-          constantValues.add(field.evaluationResult!.value!);
-        }
-      }
-      _evaluationResult = EvaluationResultImpl(
-        DartObjectImpl(
-          library.typeSystem,
-          type,
-          ListState(constantValues),
-        ),
-      );
-    }
-    return _evaluationResult!;
-  }
-
-  @override
-  String get name => 'values';
-
-  @override
-  InterfaceType get type =>
-      ElementTypeProvider.current.getFieldType(this) as InterfaceType;
-
-  @override
-  InterfaceType get typeInternal {
-    if (_type == null) {
-      return _type = library.typeProvider.listType(_enum.thisType);
-    }
-    return _type as InterfaceType;
-  }
-}
-
-/// An abstract constant field of an enum.
-abstract class ConstFieldElementImpl_ofEnum extends ConstFieldElementImpl {
-  final EnumElementImpl _enum;
-
-  ConstFieldElementImpl_ofEnum(this._enum, String name) : super(name, -1) {
-    enclosingElement = _enum;
-  }
-
-  @override
-  set evaluationResult(_) {
-    assert(false);
-  }
-
-  @override
-  bool get isConst => true;
-
-  @override
-  set isConst(bool isConst) {
-    assert(false);
-  }
-
-  @override
-  bool get isConstantEvaluated => true;
-
-  @override
-  set isFinal(bool isFinal) {
-    assert(false);
-  }
-
-  @override
-  bool get isStatic => true;
-
-  @override
-  set isStatic(bool isStatic) {
-    assert(false);
-  }
-
-  @override
-  Element get nonSynthetic => _enum;
-
-  @override
-  set type(DartType type) {
-    assert(false);
-  }
-}
-
 /// A [LocalVariableElement] for a local 'const' variable that has an
 /// initializer.
 class ConstLocalVariableElementImpl extends LocalVariableElementImpl
@@ -1474,8 +1315,8 @@
   }
 
   @override
-  ClassElementImpl get enclosingElement =>
-      super.enclosingElement as ClassElementImpl;
+  AbstractClassElementImpl get enclosingElement =>
+      super.enclosingElement as AbstractClassElementImpl;
 
   @override
   bool get isConst {
@@ -1594,8 +1435,7 @@
   /// of formal parameters, are evaluated.
   void computeConstantDependencies() {
     if (!isConstantEvaluated) {
-      computeConstants(library.typeProvider, library.typeSystem,
-          context.declaredVariables, [this], library.featureSet);
+      computeConstants(context.declaredVariables, [this], library.featureSet);
     }
   }
 }
@@ -1680,8 +1520,7 @@
           '[reference: $reference]',
         );
       }
-      computeConstants(library.typeProvider, library.typeSystem,
-          context.declaredVariables, [this], library.featureSet);
+      computeConstants(context.declaredVariables, [this], library.featureSet);
     }
     return evaluationResult?.value;
   }
@@ -1745,7 +1584,38 @@
 
   @override
   String? get defaultValueCode {
-    return constantInitializer?.toSource();
+    final constantInitializer = this.constantInitializer;
+    if (constantInitializer != null) {
+      return constantInitializer.toSource();
+    }
+
+    if (_superConstructorParameterDefaultValue != null) {
+      return superConstructorParameter?.defaultValueCode;
+    }
+
+    return null;
+  }
+
+  DartObject? get _superConstructorParameterDefaultValue {
+    var superDefault = superConstructorParameter?.computeConstantValue();
+    var superDefaultType = superDefault?.type;
+    var libraryElement = library;
+    if (superDefaultType != null &&
+        libraryElement != null &&
+        libraryElement.typeSystem.isSubtypeOf(superDefaultType, type)) {
+      return superDefault;
+    }
+
+    return null;
+  }
+
+  @override
+  DartObject? computeConstantValue() {
+    if (constantInitializer != null) {
+      return super.computeConstantValue();
+    }
+
+    return _superConstructorParameterDefaultValue;
   }
 }
 
@@ -2031,9 +1901,8 @@
   @override
   DartObject? computeConstantValue() {
     if (evaluationResult == null) {
-      var library = compilationUnit.library;
-      computeConstants(library.typeProvider, library.typeSystem,
-          context.declaredVariables, [this], library.featureSet);
+      computeConstants(context.declaredVariables, [this],
+          compilationUnit.library.featureSet);
     }
     return evaluationResult?.value;
   }
@@ -2795,6 +2664,7 @@
 /// An [AbstractClassElementImpl] which is an enum.
 class EnumElementImpl extends AbstractClassElementImpl {
   ElementLinkedData? linkedData;
+  List<ConstructorElement> _constructors = _Sentinel.constructorElement;
 
   /// Initialize a newly created class element to have the given [name] at the
   /// given [offset] in the file that contains the declaration of this element.
@@ -2802,7 +2672,6 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
-    linkedData?.read(this);
     return _accessors;
   }
 
@@ -2811,25 +2680,23 @@
       <InterfaceType>[...interfaces, supertype];
 
   List<FieldElement> get constants {
-    return fields.where((field) => !field.isSynthetic).toList();
-  }
-
-  List<FieldElement> get constants_unresolved {
-    return _fields.where((field) => !field.isSynthetic).toList();
+    return fields.where((field) => field.isEnumConstant).toList();
   }
 
   @override
   List<ConstructorElement> get constructors {
-    // The equivalent code for enums in the spec shows a single constructor,
-    // but that constructor is not callable (since it is a compile-time error
-    // to subclass, mix-in, implement, or explicitly instantiate an enum).
-    // So we represent this as having no constructors.
-    return const <ConstructorElement>[];
+    return _constructors;
+  }
+
+  set constructors(List<ConstructorElement> constructors) {
+    for (var constructor in constructors) {
+      (constructor as ConstructorElementImpl).enclosingElement = this;
+    }
+    _constructors = constructors;
   }
 
   @override
   List<FieldElement> get fields {
-    linkedData?.read(this);
     return _fields;
   }
 
@@ -2852,7 +2719,13 @@
   bool get isMixinApplication => false;
 
   @override
-  bool get isSimplyBounded => true;
+  bool get isSimplyBounded {
+    return hasModifier(Modifier.SIMPLY_BOUNDED);
+  }
+
+  set isSimplyBounded(bool isSimplyBounded) {
+    setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded);
+  }
 
   @override
   bool get isValidMixin => false;
@@ -2868,10 +2741,17 @@
 
   @override
   List<MethodElement> get methods {
-    linkedData?.read(this);
     return _methods;
   }
 
+  /// Set the methods contained in this class to the given [methods].
+  set methods(List<MethodElement> methods) {
+    for (MethodElement method in methods) {
+      (method as MethodElementImpl).enclosingElement = this;
+    }
+    _methods = methods;
+  }
+
   @override
   List<InterfaceType> get mixins => const <InterfaceType>[];
 
@@ -2887,29 +2767,16 @@
   }
 
   @override
-  List<TypeParameterElement> get typeParameters =>
-      const <TypeParameterElement>[];
-
-  @override
-  ConstructorElement? get unnamedConstructor => null;
+  List<TypeParameterElement> get typeParameters {
+    linkedData?.read(this);
+    return super.typeParameters;
+  }
 
   @override
   void appendTo(ElementDisplayStringBuilder builder) {
     builder.writeEnumElement(this);
   }
 
-  /// Create the only method enums have - `toString()`.
-  void createToStringMethodElement() {
-    var method = MethodElementImpl('toString', -1);
-    method.isSynthetic = true;
-    method.enclosingElement = this;
-    method.reference = reference?.getChild('@method').getChild('toString');
-    _methods = <MethodElement>[method];
-  }
-
-  @override
-  ConstructorElement? getNamedConstructor(String name) => null;
-
   void setLinkedData(Reference reference, ElementLinkedData linkedData) {
     this.reference = reference;
     reference.element = this;
@@ -3337,7 +3204,13 @@
   }
 
   @override
-  bool get isEnumConstant => false;
+  bool get isEnumConstant {
+    return hasModifier(Modifier.ENUM_CONSTANT);
+  }
+
+  set isEnumConstant(bool isEnumConstant) {
+    setModifier(Modifier.ENUM_CONSTANT, isEnumConstant);
+  }
 
   @override
   bool get isExternal {
@@ -3354,6 +3227,20 @@
     setModifier(Modifier.STATIC, isStatic);
   }
 
+  /// Return `true` if this element is a synthetic enum field.
+  ///
+  /// It is synthetic because it is not written explicitly in code, but it
+  /// is different from other synthetic fields, because its getter is also
+  /// synthetic.
+  ///
+  /// Such fields are `index`, `_name`, and `values`.
+  bool get isSyntheticEnumField {
+    return enclosingElement is EnumElementImpl &&
+        isSynthetic &&
+        getter?.isSynthetic == true &&
+        setter == null;
+  }
+
   @override
   ElementKind get kind => ElementKind.FIELD;
 
@@ -3699,13 +3586,7 @@
   final AnalysisContext context;
 
   @override
-  final AnalysisSession session;
-
-  /// If `true`, then this library is valid in the session.
-  ///
-  /// A library becomes invalid when one of its files, or one of its
-  /// dependencies, changes.
-  bool isValid = true;
+  AnalysisSession session;
 
   /// The language version for the library.
   LibraryLanguageVersion? _languageVersion;
@@ -4400,58 +4281,64 @@
   /// Indicates that a class element was defined by an enum declaration.
   static const Modifier ENUM = Modifier('ENUM', 6);
 
+  /// Indicates that the element is an enum constant field.
+  static const Modifier ENUM_CONSTANT = Modifier('ENUM_CONSTANT', 7);
+
   /// Indicates that a class element was defined by an enum declaration.
-  static const Modifier EXTERNAL = Modifier('EXTERNAL', 7);
+  static const Modifier EXTERNAL = Modifier('EXTERNAL', 8);
 
   /// Indicates that the modifier 'factory' was applied to the element.
-  static const Modifier FACTORY = Modifier('FACTORY', 8);
+  static const Modifier FACTORY = Modifier('FACTORY', 9);
 
   /// Indicates that the modifier 'final' was applied to the element.
-  static const Modifier FINAL = Modifier('FINAL', 9);
+  static const Modifier FINAL = Modifier('FINAL', 10);
 
   /// Indicates that an executable element has a body marked as being a
   /// generator.
-  static const Modifier GENERATOR = Modifier('GENERATOR', 10);
+  static const Modifier GENERATOR = Modifier('GENERATOR', 11);
 
   /// Indicates that the pseudo-modifier 'get' was applied to the element.
-  static const Modifier GETTER = Modifier('GETTER', 11);
+  static const Modifier GETTER = Modifier('GETTER', 12);
 
   /// A flag used for libraries indicating that the variable has an explicit
   /// initializer.
-  static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 12);
+  static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 13);
 
   /// A flag used for fields and top-level variables that have implicit type,
   /// and specify when the type has been inferred.
-  static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 13);
+  static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 14);
 
   /// A flag used for libraries indicating that the defining compilation unit
   /// has a `part of` directive, meaning that this unit should be a part,
   /// but is used as a library.
   static const Modifier HAS_PART_OF_DIRECTIVE =
-      Modifier('HAS_PART_OF_DIRECTIVE', 14);
+      Modifier('HAS_PART_OF_DIRECTIVE', 15);
 
   /// Indicates that the associated element did not have an explicit type
   /// associated with it. If the element is an [ExecutableElement], then the
   /// type being referred to is the return type.
-  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 15);
+  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 16);
 
   /// Indicates that modifier 'lazy' was applied to the element.
-  static const Modifier LATE = Modifier('LATE', 16);
+  static const Modifier LATE = Modifier('LATE', 17);
 
   /// Indicates that a class is a mixin application.
-  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 17);
+  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 18);
 
   /// Indicates that the pseudo-modifier 'set' was applied to the element.
-  static const Modifier SETTER = Modifier('SETTER', 18);
+  static const Modifier SETTER = Modifier('SETTER', 19);
+
+  /// See [TypeParameterizedElement.isSimplyBounded].
+  static const Modifier SIMPLY_BOUNDED = Modifier('SIMPLY_BOUNDED', 20);
 
   /// Indicates that the modifier 'static' was applied to the element.
-  static const Modifier STATIC = Modifier('STATIC', 19);
+  static const Modifier STATIC = Modifier('STATIC', 21);
 
   /// Indicates that the element does not appear in the source code but was
   /// implicitly created. For example, if a class does not define any
   /// constructors, an implicit zero-argument constructor will be created and it
   /// will be marked as being synthetic.
-  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 20);
+  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 22);
 
   static const List<Modifier> values = [
     ABSTRACT,
@@ -4461,6 +4348,7 @@
     DART_CORE_OBJECT,
     DEFERRED,
     ENUM,
+    ENUM_CONSTANT,
     EXTERNAL,
     FACTORY,
     FINAL,
@@ -4473,6 +4361,7 @@
     MIXIN_APPLICATION,
     SETTER,
     STATIC,
+    SIMPLY_BOUNDED,
     SYNTHETIC
   ];
 
@@ -5401,6 +5290,11 @@
     return !isFinal;
   }
 
+  void bindReference(Reference reference) {
+    this.reference = reference;
+    reference.element = this;
+  }
+
   void createImplicitAccessors(Reference enclosingRef, String name) {
     getter = PropertyAccessorElementImpl_ImplicitGetter(
       this,
@@ -5485,14 +5379,14 @@
       if (superConstructor != null) {
         var superParameters = superConstructor.parameters;
         if (isNamed) {
-          return superParameters.firstWhereOrNull((e) => e.name == name);
+          return superParameters
+              .firstWhereOrNull((e) => e.isNamed && e.name == name);
         } else {
-          var index = enclosingElement.parameters
-              .whereType<SuperFormalParameterElementImpl>()
-              .toList()
-              .indexOf(this);
-          if (index >= 0 && index < superParameters.length) {
-            return superParameters[index];
+          var index = indexIn(enclosingElement);
+          var positionalSuperParameters =
+              superParameters.where((e) => e.isPositional).toList();
+          if (index >= 0 && index < positionalSuperParameters.length) {
+            return positionalSuperParameters[index];
           }
         }
       }
@@ -5503,6 +5397,14 @@
   @override
   T? accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitSuperFormalParameterElement(this);
+
+  /// Return the index of this super-formal parameter among other super-formals.
+  int indexIn(ConstructorElementImpl enclosingElement) {
+    return enclosingElement.parameters
+        .whereType<SuperFormalParameterElementImpl>()
+        .toList()
+        .indexOf(this);
+  }
 }
 
 /// A concrete implementation of a [TopLevelVariableElement].
@@ -5543,10 +5445,6 @@
 class TypeAliasElementImpl extends _ExistingElementImpl
     with TypeParameterizedElementMixin
     implements TypeAliasElement {
-  /// TODO(scheglov) implement as modifier
-  @override
-  bool isSimplyBounded = true;
-
   /// Is `true` if the element has direct or indirect reference to itself
   /// from anywhere except a class element or type parameter bounds.
   bool hasSelfReference = false;
@@ -5617,6 +5515,15 @@
   }
 
   @override
+  bool get isSimplyBounded {
+    return hasModifier(Modifier.SIMPLY_BOUNDED);
+  }
+
+  set isSimplyBounded(bool isSimplyBounded) {
+    setModifier(Modifier.SIMPLY_BOUNDED, isSimplyBounded);
+  }
+
+  @override
   ElementKind get kind {
     if (isNonFunctionTypeAliasesEnabled) {
       return ElementKind.TYPE_ALIAS;
diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart
index ad00f5e..decbd59 100644
--- a/pkg/analyzer/lib/src/dart/element/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/element/extensions.dart
@@ -103,6 +103,12 @@
   }
 }
 
+extension ExecutableElementExtension on ExecutableElement {
+  bool get isEnumConstructor {
+    return this is ConstructorElement && enclosingElement is EnumElementImpl;
+  }
+}
+
 extension ParameterElementExtensions on ParameterElement {
   /// Return [ParameterElement] with the specified properties replaced.
   ParameterElement copyWith({
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 168cc9a..6195260 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -863,6 +863,7 @@
       result.parameters = resultType.parameters;
 
       var field = FieldElementImpl(variableName, -1);
+      field.enclosingElement = targetClass;
       if (firstAccessor.isGetter) {
         field.getter = result;
         field.type = result.returnType;
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 4df2190..7287b59 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -83,7 +83,8 @@
     List<ParameterElement> elements,
   ) : super(parent) {
     for (var parameter in elements) {
-      if (parameter is! FieldFormalParameterElement) {
+      if (parameter is! FieldFormalParameterElement &&
+          parameter is! SuperFormalParameterElement) {
         _addGetter(parameter);
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/element/subtype.dart b/pkg/analyzer/lib/src/dart/element/subtype.dart
index 85a9387..4c8850c 100644
--- a/pkg/analyzer/lib/src/dart/element/subtype.dart
+++ b/pkg/analyzer/lib/src/dart/element/subtype.dart
@@ -31,21 +31,21 @@
         _objectNone = typeSystem.objectNone,
         _objectQuestion = typeSystem.objectQuestion;
 
-  /// Return `true` if [_T0] is a subtype of [_T1].
-  bool isSubtypeOf(DartType _T0, DartType _T1) {
+  /// Return `true` if [T0_] is a subtype of [T1_].
+  bool isSubtypeOf(DartType T0_, DartType T1_) {
     // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`.
-    if (identical(_T0, _T1)) {
+    if (identical(T0_, T1_)) {
       return true;
     }
 
     // `_` is treated as a top and a bottom type during inference.
-    if (identical(_T0, UnknownInferredType.instance) ||
-        identical(_T1, UnknownInferredType.instance)) {
+    if (identical(T0_, UnknownInferredType.instance) ||
+        identical(T1_, UnknownInferredType.instance)) {
       return true;
     }
 
-    var T0 = _T0 as TypeImpl;
-    var T1 = _T1 as TypeImpl;
+    var T0 = T0_ as TypeImpl;
+    var T1 = T1_ as TypeImpl;
 
     var T1_nullability = T1.nullabilitySuffix;
     var T0_nullability = T0.nullabilitySuffix;
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
index 620289c..873531a 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.g.dart
@@ -64,9 +64,43 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field that's declared in a
+  // subclass of `Struct` and has the type `Pointer` also has an annotation
+  // associated with it.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `p`, which
+  // has the type `Pointer` and is declared in a subclass of `Struct`, has the
+  // annotation `@Double()`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   [!@Double()!]
+  //   external Pointer<Int8> p;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the annotations from the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   external Pointer<Int8> p;
+  // }
+  // ```
   static const FfiCode ANNOTATION_ON_POINTER_FIELD = FfiCode(
     'ANNOTATION_ON_POINTER_FIELD',
-    "Fields in a struct class whose type is 'Pointer' should not have any "
+    "Fields in a struct class whose type is 'Pointer' shouldn't have any "
         "annotations.",
     correctionMessage: "Try removing the annotation.",
   );
@@ -75,6 +109,56 @@
    * Parameters:
    * 0: the name of the argument
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an invocation of either
+  // `Pointer.asFunction` or `DynamicLibrary.lookupFunction` has an `isLeaf`
+  // argument whose value isn't a constant expression.
+  //
+  // The analyzer also produces this diagnostic when the value of the
+  // `exceptionalReturn` argument of `Pointer.fromFunction`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the value of the
+  // `isLeaf` argument is a parameter, and hence isn't a constant:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int Function(int) fromPointer(
+  //     Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
+  //   return p.asFunction(isLeaf: [!isLeaf!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If there's a suitable constant that can be used, then replace the argument
+  // with a constant:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // const isLeaf = false;
+  //
+  // int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+  //   return p.asFunction(isLeaf: isLeaf);
+  // }
+  // ```
+  //
+  // If there isn't a suitable constant, then replace the argument with a
+  // boolean literal:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+  //   return p.asFunction(isLeaf: true);
+  // }
+  // ```
   static const FfiCode ARGUMENT_MUST_BE_A_CONSTANT = FfiCode(
     'ARGUMENT_MUST_BE_A_CONSTANT',
     "Argument '{0}' must be a constant.",
@@ -84,6 +168,52 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a subclass of either `Struct`
+  // or `Union` is instantiated using a generative constructor.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C` is being
+  // instantiated using a generative constructor:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   external int a;
+  // }
+  //
+  // void f() {
+  //   [!C!]();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you need to allocate the structure described by the class, then use the
+  // `ffi` package to do so:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  // import 'package:ffi/ffi.dart';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   external int a;
+  // }
+  //
+  // void f() {
+  //   final pointer = calloc.allocate<C>(4);
+  //   final c = pointer.ref;
+  //   print(c);
+  //   calloc.free(pointer);
+  // }
+  // ```
   static const FfiCode CREATION_OF_STRUCT_OR_UNION = FfiCode(
     'CREATION_OF_STRUCT_OR_UNION',
     "Subclasses of 'Struct' and 'Union' are backed by native memory, and can't "
@@ -97,9 +227,56 @@
    * 0: the name of the subclass
    * 1: the name of the superclass
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a subclass of `Struct` or
+  // `Union` doesn't have any fields. Having an empty `Struct` or `Union`
+  // isn't supported.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C`, which
+  // extends `Struct`, doesn't declare any fields:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class [!C!] extends Struct {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the class is intended to be a struct, then declare one or more fields:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   external int x;
+  // }
+  // ```
+  //
+  // If the class is intended to be used as a type argument to `Pointer`, then
+  // make it a subclass of `Opaque`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Opaque {}
+  // ```
+  //
+  // If the class isn't intended to be a struct, then remove or change the
+  // extends clause:
+  //
+  // ```dart
+  // class C {}
+  // ```
   static const FfiCode EMPTY_STRUCT = FfiCode(
     'EMPTY_STRUCT',
-    "The class '{0}' can’t be empty because it's a subclass of '{1}'.",
+    "The class '{0}' can't be empty because it's a subclass of '{1}'.",
     correctionMessage:
         "Try adding a field to '{0}' or use a different superclass.",
   );
@@ -107,6 +284,40 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` has more than one annotation describing the native type of the
+  // field.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `x` has two
+  // annotations describing the native type of the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   [!@Int16()!]
+  //   external int x;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove all but one of the annotations:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  // class C extends Struct {
+  //   @Int32()
+  //   external int x;
+  // }
+  // ```
   static const FfiCode EXTRA_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
     'EXTRA_ANNOTATION_ON_STRUCT_FIELD',
     "Fields in a struct class must have exactly one annotation indicating the "
@@ -117,6 +328,41 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` has more than one annotation describing the size of the native
+  // array.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `a0` has two
+  // annotations that specify the size of the native array:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(4)
+  //   [!@Array(8)!]
+  //   external Array<Uint8> a0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove all but one of the annotations:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8)
+  //   external Array<Uint8> a0;
+  // }
+  // ```
   static const FfiCode EXTRA_SIZE_ANNOTATION_CARRAY = FfiCode(
     'EXTRA_SIZE_ANNOTATION_CARRAY',
     "'Array's must have exactly one 'Array' annotation.",
@@ -174,6 +420,45 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor in a subclass of
+  // either `Struct` or `Union` has one or more field initializers.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C` has a
+  // constructor with an initializer for the field `f`:
+  //
+  // ```dart
+  // // @dart = 2.9
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   int f;
+  //
+  //   C() : [!f = 0!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the field initializer:
+  //
+  // ```dart
+  // // @dart = 2.9
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   int f;
+  //
+  //   C();
+  // }
+  // ```
   static const FfiCode FIELD_INITIALIZER_IN_STRUCT = FfiCode(
     'FIELD_INITIALIZER_IN_STRUCT',
     "Constructors in subclasses of 'Struct' and 'Union' can't have field "
@@ -185,6 +470,39 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` has an initializer.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `p` has an
+  // initializer:
+  //
+  // ```dart
+  // // @dart = 2.9
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   Pointer [!p!] = nullptr;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the initializer:
+  //
+  // ```dart
+  // // @dart = 2.9
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   Pointer p;
+  // }
+  // ```
   static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
     'FIELD_IN_STRUCT_WITH_INITIALIZER',
     "Fields in subclasses of 'Struct' and 'Union' can't have initializers.",
@@ -195,6 +513,39 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of either
+  // `Struct` or `Union` isn't marked as being `external`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `a` isn't
+  // marked as being `external`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int16()
+  //   int [!a!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add the required `external` modifier:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int16()
+  //   external int a;
+  // }
+  // ```
   static const FfiCode FIELD_MUST_BE_EXTERNAL_IN_STRUCT = FfiCode(
     'FIELD_MUST_BE_EXTERNAL_IN_STRUCT',
     "Fields of 'Struct' and 'Union' subclasses must be marked external.",
@@ -205,20 +556,93 @@
    * Parameters:
    * 0: the name of the struct class
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a subclass of either `Struct`
+  // or `Union` has a type parameter.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `S` defines
+  // the type parameter `T`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class [!S!]<T> extends Struct {
+  //   external Pointer notEmpty;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the type parameters from the class:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class S extends Struct {
+  //   external Pointer notEmpty;
+  // }
+  // ```
   static const FfiCode GENERIC_STRUCT_SUBCLASS = FfiCode(
     'GENERIC_STRUCT_SUBCLASS',
-    "The class '{0}' can't extend 'Struct' or 'Union' because it is generic.",
+    "The class '{0}' can't extend 'Struct' or 'Union' because '{0}' is "
+        "generic.",
     correctionMessage: "Try removing the type parameters from '{0}'.",
   );
 
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an invocation of the method
+  // `Pointer.fromFunction` has a second argument (the exceptional return
+  // value) and the type to be returned from the invocation is either `void`,
+  // `Handle` or `Pointer`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because a second argument is
+  // provided when the return type of `f` is `void`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = Void Function(Int8);
+  //
+  // void f(int i) {}
+  //
+  // void g() {
+  //   Pointer.fromFunction<T>(f, [!42!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the exception value:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = Void Function(Int8);
+  //
+  // void f(int i) {}
+  //
+  // void g() {
+  //   Pointer.fromFunction<T>(f);
+  // }
+  // ```
   static const FfiCode INVALID_EXCEPTION_VALUE = FfiCode(
     'INVALID_EXCEPTION_VALUE',
-    "The method 'Pointer.fromFunction' must not have an exceptional return "
-        "value (the second argument) when the return type of the function is "
-        "either 'void', 'Handle' or 'Pointer'.",
+    "The method 'Pointer.fromFunction' can't have an exceptional return value "
+        "(the second argument) when the return type of the function is either "
+        "'void', 'Handle' or 'Pointer'.",
     correctionMessage: "Try removing the exceptional return value.",
   );
 
@@ -226,6 +650,46 @@
    * Parameters:
    * 0: the type of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` has a type other than `int`, `double`, `Array`, `Pointer`, or
+  // subtype of `Struct` or `Union`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `str` has
+  // the type `String`, which isn't one of the allowed types for fields in a
+  // subclass of `Struct`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   external [!String!] s;
+  //
+  //   @Int32()
+  //   external int i;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Use one of the allowed types for the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  // import 'package:ffi/ffi.dart';
+  //
+  // class C extends Struct {
+  //   external Pointer<Utf8> s;
+  //
+  //   @Int32()
+  //   external int i;
+  // }
+  // ```
   static const FfiCode INVALID_FIELD_TYPE_IN_STRUCT = FfiCode(
     'INVALID_FIELD_TYPE_IN_STRUCT',
     "Fields in struct classes can't have the type '{0}'. They can only be "
@@ -239,27 +703,167 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the value of the `isLeaf`
+  // argument in an invocation of either `Pointer.asFunction` or
+  // `DynamicLibrary.lookupFunction` is `true` and the function that would be
+  // returned would have a return type of `Handle`.
+  //
+  // The analyzer also produces this diagnostic when the value of the `isLeaf`
+  // argument in an `FfiNative` annotation is `true` and the type argument on
+  // the annotation is a function type whose return type is `Handle`.
+  //
+  // In all of these cases, leaf calls are only supported for the types `bool`,
+  // `int`, `float`, `double`, and, as a return type `void`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the function `p`
+  // returns a `Handle`, but the `isLeaf` argument is `true`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Handle Function()>> p) {
+  //   [!p.asFunction<Object Function()>(isLeaf: true)!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function returns a handle, then remove the `isLeaf` argument:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Handle Function()>> p) {
+  //   p.asFunction<Object Function()>();
+  // }
+  // ```
+  //
+  // If the function returns one of the supported types, then correct the type
+  // information:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Int32 Function()>> p) {
+  //   p.asFunction<int Function()>(isLeaf: true);
+  // }
+  // ```
   static const FfiCode LEAF_CALL_MUST_NOT_RETURN_HANDLE = FfiCode(
     'LEAF_CALL_MUST_NOT_RETURN_HANDLE',
-    "FFI leaf call must not return a Handle.",
+    "FFI leaf call can't return a 'Handle'.",
     correctionMessage: "Try changing the return type to primitive or struct.",
   );
 
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the value of the `isLeaf`
+  // argument in an invocation of either `Pointer.asFunction` or
+  // `DynamicLibrary.lookupFunction` is `true` and the function that would be
+  // returned would have a parameter of type `Handle`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the function `p` has a
+  // parameter of type `Handle`, but the `isLeaf` argument is `true`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+  //   [!p.asFunction<void Function(Object)>(isLeaf: true)!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function has at least one parameter of type `Handle`, then remove
+  // the `isLeaf` argument:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+  //   p.asFunction<void Function(Object)>();
+  // }
+  // ```
+  //
+  // If none of the function's parameters are `Handle`s, then correct the type
+  // information:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
+  //   p.asFunction<void Function(int)>(isLeaf: true);
+  // }
+  // ```
   static const FfiCode LEAF_CALL_MUST_NOT_TAKE_HANDLE = FfiCode(
     'LEAF_CALL_MUST_NOT_TAKE_HANDLE',
-    "FFI leaf call must not take arguments of type Handle.",
+    "FFI leaf call can't take arguments of type 'Handle'.",
     correctionMessage: "Try changing the argument type to primitive or struct.",
   );
 
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the annotation on a field in a
+  // subclass of `Struct` or `Union` doesn't match the Dart type of the field.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the annotation
+  // `Double` doesn't match the Dart type `int`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   [!@Double()!]
+  //   external int x;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the field is correct, then change the annotation to match:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   external int x;
+  // }
+  // ```
+  //
+  // If the annotation is correct, then change the type of the field to match:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Double()
+  //   external double x;
+  // }
+  // ```
   static const FfiCode MISMATCHED_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
     'MISMATCHED_ANNOTATION_ON_STRUCT_FIELD',
-    "The annotation does not match the declared type of the field.",
+    "The annotation doesn't match the declared type of the field.",
     correctionMessage:
         "Try using a different annotation or changing the declared type to "
         "match.",
@@ -268,6 +872,41 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` or `Union` whose type requires an annotation doesn't have one.
+  // The Dart types `int`, `double`, and `Array` are used to represent multiple
+  // C types, and the annotation specifies which of the compatible C types the
+  // field represents.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `x` doesn't
+  // have an annotation indicating the underlying width of the integer value:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   external [!int!] x;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add an appropriate annotation to the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int64()
+  //   external int x;
+  // }
+  // ```
   static const FfiCode MISSING_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
     'MISSING_ANNOTATION_ON_STRUCT_FIELD',
     "Fields in a struct class must either have the type 'Pointer' or an "
@@ -278,11 +917,49 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an invocation of the method
+  // `Pointer.fromFunction` doesn't have a second argument (the exceptional
+  // return value) when the type to be returned from the invocation is neither
+  // `void`, `Handle`, nor `Pointer`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type returned by
+  // `f` is expected to be an 8-bit integer but the call to `fromFunction`
+  // doesn't include an exceptional return argument:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int f(int i) => i * 2;
+  //
+  // void g() {
+  //   Pointer.[!fromFunction!]<Int8 Function(Int8)>(f);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add an exceptional return type:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int f(int i) => i * 2;
+  //
+  // void g() {
+  //   Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
+  // }
+  // ```
   static const FfiCode MISSING_EXCEPTION_VALUE = FfiCode(
     'MISSING_EXCEPTION_VALUE',
     "The method 'Pointer.fromFunction' must have an exceptional return value "
         "(the second argument) when the return type of the function is neither "
-        "'void', 'Handle' or 'Pointer'.",
+        "'void', 'Handle', nor 'Pointer'.",
     correctionMessage: "Try adding an exceptional return value.",
   );
 
@@ -290,6 +967,46 @@
    * Parameters:
    * 0: the type of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of
+  // `Struct` or `Union` doesn't have a type annotation. Every field must have
+  // an explicit type, and the type must either be `int`, `double`, `Pointer`,
+  // or a subclass of either `Struct` or `Union`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `str`
+  // doesn't have a type annotation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   external var [!str!];
+  //
+  //   @Int32()
+  //   external int i;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Explicitly specify the type of the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  // import 'package:ffi/ffi.dart';
+  //
+  // class C extends Struct {
+  //   external Pointer<Utf8> str;
+  //
+  //   @Int32()
+  //   external int i;
+  // }
+  // ```
   static const FfiCode MISSING_FIELD_TYPE_IN_STRUCT = FfiCode(
     'MISSING_FIELD_TYPE_IN_STRUCT',
     "Fields in struct classes must have an explicitly declared type of 'int', "
@@ -300,10 +1017,45 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field in a subclass of either
+  // `Struct` or `Union` has a type of `Array` but doesn't have a single
+  // `Array` annotation indicating the dimensions of the array.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `a0` doesn't
+  // have an `Array` annotation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   external [!Array<Uint8>!] a0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Ensure that there's exactly one `Array` annotation on the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8)
+  //   external Array<Uint8> a0;
+  // }
+  // ```
   static const FfiCode MISSING_SIZE_ANNOTATION_CARRAY = FfiCode(
     'MISSING_SIZE_ANNOTATION_CARRAY',
-    "'Array's must have exactly one 'Array' annotation.",
-    correctionMessage: "Try adding a 'Array' annotation.",
+    "Fields of type 'Array' must have exactly one 'Array' annotation.",
+    correctionMessage:
+        "Try adding an 'Array' annotation, or removing all but one of the "
+        "annotations.",
   );
 
   /**
@@ -311,6 +1063,47 @@
    * 0: the type that should be a valid dart:ffi native type.
    * 1: the name of the function whose invocation depends on this relationship
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an invocation of either
+  // `Pointer.fromFunction` or `DynamicLibrary.lookupFunction` has a type
+  // argument(whether explicit or inferred) that isn't a native function type.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type `T` can be
+  // any subclass of `Function` but the type argument for `fromFunction` is
+  // required to be a native function type:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int f(int i) => i * 2;
+  //
+  // class C<T extends Function> {
+  //   void g() {
+  //     Pointer.fromFunction<[!T!]>(f, 0);
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Use a native function type as the type argument to the invocation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // int f(int i) => i * 2;
+  //
+  // class C<T extends Function> {
+  //   void g() {
+  //     Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
+  //   }
+  // }
+  // ```
   static const FfiCode MUST_BE_A_NATIVE_FUNCTION_TYPE = FfiCode(
     'MUST_BE_A_NATIVE_FUNCTION_TYPE',
     "The type '{0}' given to '{1}' must be a valid 'dart:ffi' native function "
@@ -325,6 +1118,64 @@
    * 1: the supertype that the subtype is compared to
    * 2: the name of the function whose invocation depends on this relationship
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic in two cases:
+  // - In an invocation of `Pointer.fromFunction` where the type argument
+  //   (whether explicit or inferred) isn't a supertype of the type of the
+  //   function passed as the first argument to the method.
+  // - In an invocation of `DynamicLibrary.lookupFunction` where the first type
+  //   argument isn't a supertype of the second type argument.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type of the
+  // function `f` (`String Function(int)`) isn't a subtype of the type
+  // argument `T` (`Int8 Function(Int8)`):
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = Int8 Function(Int8);
+  //
+  // double f(double i) => i;
+  //
+  // void g() {
+  //   Pointer.fromFunction<T>([!f!], 5.0);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function is correct, then change the type argument to match:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = Float Function(Float);
+  //
+  // double f(double i) => i;
+  //
+  // void g() {
+  //   Pointer.fromFunction<T>(f, 5.0);
+  // }
+  // ```
+  //
+  // If the type argument is correct, then change the function to match:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = Int8 Function(Int8);
+  //
+  // int f(int i) => i;
+  //
+  // void g() {
+  //   Pointer.fromFunction<T>(f, 5);
+  // }
+  // ```
   static const FfiCode MUST_BE_A_SUBTYPE = FfiCode(
     'MUST_BE_A_SUBTYPE',
     "The type '{0}' must be a subtype of '{1}' for '{2}'.",
@@ -335,10 +1186,50 @@
    * Parameters:
    * 0: the name of the function, method, or constructor having type arguments
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type arguments to a method
+  // are required to be known at compile time, but a type parameter, whose
+  // value can't be known at compile time, is used as a type argument.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type argument to
+  // `Pointer.asFunction` must be known at compile time, but the type parameter
+  // `R`, which isn't known at compile time, is being used as the type
+  // argument:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef T = int Function(int);
+  //
+  // class C<R extends T> {
+  //   void m(Pointer<NativeFunction<T>> p) {
+  //     p.asFunction<[!R!]>();
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove any uses of type parameters:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C {
+  //   void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
+  //     p.asFunction<int Function(int)>();
+  //   }
+  // }
+  // ```
   static const FfiCode NON_CONSTANT_TYPE_ARGUMENT = FfiCode(
     'NON_CONSTANT_TYPE_ARGUMENT',
-    "The type arguments to '{0}' must be compile time constants but type "
-        "parameters are not constants.",
+    "The type arguments to '{0}' must be known at compile time, so they can't "
+        "be type parameters.",
     correctionMessage: "Try changing the type argument to be a constant type.",
   );
 
@@ -346,10 +1237,53 @@
    * Parameters:
    * 0: the type that should be a valid dart:ffi native type.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the method `asFunction` is
+  // invoked on a pointer to a native function, but the signature of the native
+  // function isn't a valid C function signature.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because function signature
+  // associated with the pointer `p` (`FNative`) isn't a valid C function
+  // signature:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef FNative = int Function(int);
+  // typedef F = int Function(int);
+  //
+  // class C {
+  //   void f(Pointer<NativeFunction<FNative>> p) {
+  //     p.asFunction<[!F!]>();
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Make the `NativeFunction` signature a valid C signature:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // typedef FNative = Int8 Function(Int8);
+  // typedef F = int Function(int);
+  //
+  // class C {
+  //   void f(Pointer<NativeFunction<FNative>> p) {
+  //     p.asFunction<F>();
+  //   }
+  // }
+  // ```
   static const FfiCode NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER = FfiCode(
     'NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER',
-    "The type argument for the pointer '{0}' must be a valid 'NativeFunction' "
-        "in order to use 'asFunction'.",
+    "Can't invoke 'asFunction' because the function signature '{0}' for the "
+        "pointer isn't a valid C function signature.",
     correctionMessage:
         "Try changing the function argument in 'NativeFunction' to only use "
         "NativeTypes.",
@@ -358,6 +1292,39 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a dimension given in an `Array`
+  // annotation is less than or equal to zero (`0`).
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because an array dimension of
+  // `-1` was provided:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class MyStruct extends Struct {
+  //   @Array([!-8!])
+  //   external Array<Uint8> a0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Change the dimension to be a positive integer:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class MyStruct extends Struct {
+  //   @Array(8)
+  //   external Array<Uint8> a0;
+  // }
+  // ```
   static const FfiCode NON_POSITIVE_ARRAY_DIMENSION = FfiCode(
     'NON_POSITIVE_ARRAY_DIMENSION',
     "Array dimensions must be positive numbers.",
@@ -368,11 +1335,46 @@
    * Parameters:
    * 0: the type of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type argument for the class
+  // `Array` isn't one of the valid types: either a native integer, `Float`,
+  // `Double`, `Pointer`, or subtype of `Struct`, `Union`, or
+  // `AbiSpecificInteger`.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type argument to
+  // `Array` is `Void`, and `Void` isn't one of the valid types:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8)
+  //   external Array<[!Void!]> a0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Change the type argument to one of the valid types:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8)
+  //   external Array<Uint8> a0;
+  // }
+  // ```
   static const FfiCode NON_SIZED_TYPE_ARGUMENT = FfiCode(
     'NON_SIZED_TYPE_ARGUMENT',
-    "Type arguments to '{0}' can't have the type '{1}'. They can only be "
-        "declared as native integer, 'Float', 'Double', 'Pointer', or subtype "
-        "of 'Struct', 'Union', or 'AbiSpecificInteger'.",
+    "The type '{1}' isn't a valid type argument for '{0}'. The type argument "
+        "must be a native integer, 'Float', 'Double', 'Pointer', or subtype of "
+        "'Struct', 'Union', or 'AbiSpecificInteger'.",
     correctionMessage:
         "Try using a native integer, 'Float', 'Double', 'Pointer', or subtype "
         "of 'Struct', 'Union', or 'AbiSpecificInteger'.",
@@ -381,6 +1383,40 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a subclass of `Struct` has more
+  // than one `Packed` annotation.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C`, which
+  // is a subclass of `Struct`, has two `Packed` annotations:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(1)
+  // [!@Packed(1)!]
+  // class C extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove all but one of the annotations:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(1)
+  // class C extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  // ```
   static const FfiCode PACKED_ANNOTATION = FfiCode(
     'PACKED_ANNOTATION',
     "Structs must have at most one 'Packed' annotation.",
@@ -390,6 +1426,39 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the argument to the `Packed`
+  // annotation isn't one of the allowed values: 1, 2, 4, 8, or 16.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the argument to the
+  // `Packed` annotation (`3`) isn't one of the allowed values:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed([!3!])
+  // class C extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Change the alignment to be one of the allowed values:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(4)
+  // class C extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  // ```
   static const FfiCode PACKED_ANNOTATION_ALIGNMENT = FfiCode(
     'PACKED_ANNOTATION_ALIGNMENT',
     "Only packing to 1, 2, 4, 8, and 16 bytes is supported.",
@@ -402,10 +1471,86 @@
    * 0: the name of the outer struct
    * 1: the name of the struct being nested
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a subclass of `Struct` that is
+  // annotated as being `Packed` declares a field whose type is also a subclass
+  // of `Struct` and the field's type is either not packed or is packed less
+  // tightly.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `Outer`,
+  // which is a subclass of `Struct` and is packed on 1-byte boundaries,
+  // declared a field whose type (`Inner`) is packed on 8-byte boundaries:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(8)
+  // class Inner extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  //
+  // @Packed(1)
+  // class Outer extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  //
+  //   external [!Inner!] nestedLooselyPacked;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the inner struct should be packed more tightly, then change the
+  // argument to the inner struct's `Packed` annotation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(1)
+  // class Inner extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  //
+  // @Packed(1)
+  // class Outer extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  //
+  //   external Inner nestedLooselyPacked;
+  // }
+  // ```
+  //
+  // If the outer struct should be packed less tightly, then change the
+  // argument to the outer struct's `Packed` annotation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // @Packed(8)
+  // class Inner extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  // }
+  //
+  // @Packed(8)
+  // class Outer extends Struct {
+  //   external Pointer<Uint8> notEmpty;
+  //
+  //   external Inner nestedLooselyPacked;
+  // }
+  // ```
+  //
+  // If the inner struct doesn't have an annotation and should be packed, then
+  // add an annotation.
+  //
+  // If the inner struct doesn't have an annotation and the outer struct
+  // shouldn't be packed, then remove its annotation.
   static const FfiCode PACKED_NESTING_NON_PACKED = FfiCode(
     'PACKED_NESTING_NON_PACKED',
     "Nesting the non-packed or less tightly packed struct '{0}' in a packed "
-        "struct '{1}' is not supported.",
+        "struct '{1}' isn't supported.",
     correctionMessage:
         "Try packing the nested struct or packing the nested struct more "
         "tightly.",
@@ -414,6 +1559,53 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the number of dimensions
+  // specified in an `Array` annotation doesn't match the number of nested
+  // arrays specified by the type of a field.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `a0` has a
+  // type with three nested arrays, but only two dimensions are given in the
+  // `Array` annotation:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   [!@Array(8, 8)!]
+  //   external Array<Array<Array<Uint8>>> a0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the field is correct, then fix the annotation to have the
+  // required number of dimensions:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8, 8, 4)
+  //   external Array<Array<Array<Uint8>>> a0;
+  // }
+  // ```
+  //
+  // If the type of the field is wrong, then fix the type of the field:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Array(8, 8)
+  //   external Array<Array<Uint8>> a0;
+  // }
+  // ```
   static const FfiCode SIZE_ANNOTATION_DIMENSIONS = FfiCode(
     'SIZE_ANNOTATION_DIMENSIONS',
     "'Array's must have an 'Array' annotation that matches the dimensions.",
@@ -425,6 +1617,46 @@
    * 0: the name of the subclass
    * 1: the name of the class being extended, implemented, or mixed in
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a class extends any FFI class
+  // other than `Struct` or `Union`, or implements or mixes in any FFI class.
+  // `Struct` and `Union` are the only FFI classes that can be subtyped, and
+  // then only by extending them.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C` extends
+  // `Double`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends [!Double!] {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the class should extend either `Struct` or `Union`, then change the
+  // declaration of the class:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class C extends Struct {
+  //   @Int32()
+  //   external int i;
+  // }
+  // ```
+  //
+  // If the class shouldn't extend either `Struct` or `Union`, then remove any
+  // references to FFI classes:
+  //
+  // ```dart
+  // class C {}
+  // ```
   static const FfiCode SUBTYPE_OF_FFI_CLASS_IN_EXTENDS = FfiCode(
     'SUBTYPE_OF_FFI_CLASS',
     "The class '{0}' can't extend '{1}'.",
@@ -440,7 +1672,7 @@
   static const FfiCode SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS = FfiCode(
     'SUBTYPE_OF_FFI_CLASS',
     "The class '{0}' can't implement '{1}'.",
-    correctionMessage: "Try extending 'Struct' or 'Union'.",
+    correctionMessage: "Try implementing 'Allocator' or 'Finalizable'.",
     uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS',
   );
 
@@ -461,6 +1693,50 @@
    * 0: the name of the subclass
    * 1: the name of the class being extended, implemented, or mixed in
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a class extends, implements, or
+  // mixes in a class that extends either `Struct` or `Union`. Classes can only
+  // extend either `Struct` or `Union` directly.
+  //
+  // For more information about FFI, see [C interop using dart:ffi][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `C` extends
+  // `S`, and `S` extends `Struct`:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class S extends Struct {
+  //   external Pointer f;
+  // }
+  //
+  // class C extends [!S!] {
+  //   external Pointer g;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you're trying to define a struct or union that shares some fields
+  // declared by a different struct or union, then extend `Struct` or `Union`
+  // directly and copy the shared fields:
+  //
+  // ```dart
+  // import 'dart:ffi';
+  //
+  // class S extends Struct {
+  //   external Pointer f;
+  // }
+  //
+  // class C extends Struct {
+  //   external Pointer f;
+  //
+  //   external Pointer g;
+  // }
+  // ```
   static const FfiCode SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS = FfiCode(
     'SUBTYPE_OF_STRUCT_CLASS',
     "The class '{0}' can't extend '{1}' because '{1}' is a subtype of "
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index 8c78fc5..6f9b09b 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -3051,6 +3051,7 @@
     correctionMessage:
         "Try removing the code point or using the Unicode escape sequence "
         "'\\u{0}'.",
+    hasPublishedDocs: true,
   );
 
   /**
@@ -3096,6 +3097,7 @@
     correctionMessage:
         "Try removing the code point or using the Unicode escape sequence "
         "'\\u{0}'.",
+    hasPublishedDocs: true,
   );
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index d3ba759..0652729 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -47,14 +47,9 @@
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:pub_semver/pub_semver.dart';
 
 /// Analyzer of a single library.
 class LibraryAnalyzer {
-  /// A marker object used to prevent the initialization of
-  /// [_versionConstraintFromPubspec] when the previous initialization attempt
-  /// failed.
-  static final VersionRange noSpecifiedRange = VersionRange();
   final AnalysisOptionsImpl _analysisOptions;
   final DeclaredVariables _declaredVariables;
   final SourceFactory _sourceFactory;
@@ -180,7 +175,9 @@
   /// TODO(scheglov) Remove after https://github.com/dart-lang/sdk/issues/31925
   void _clearConstantEvaluationResults() {
     for (var constant in _libraryConstants) {
-      if (constant is ConstFieldElementImpl_ofEnum) continue;
+      if (constant is ConstFieldElementImpl && constant.isEnumConstant) {
+        continue;
+      }
       if (constant is ConstVariableElement) {
         constant.evaluationResult = null;
       }
@@ -196,8 +193,8 @@
 
   /// Compute [_constants] in all units.
   void _computeConstants() {
-    computeConstants(_typeProvider, _typeSystem, _declaredVariables,
-        _constants.toList(), _libraryElement.featureSet);
+    computeConstants(
+        _declaredVariables, _constants.toList(), _libraryElement.featureSet);
   }
 
   void _computeDiagnostics({
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 0391099..192c94c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -432,35 +432,6 @@
     }
   }
 
-  /// Given an [argumentList] and the [executableElement] that will be invoked
-  /// using those argument, compute the list of parameters that correspond to
-  /// the list of arguments. An error will be reported if any of the arguments
-  /// cannot be matched to a parameter. Return the parameters that correspond to
-  /// the arguments, or `null` if no correspondence could be computed.
-  ///
-  /// TODO(scheglov) this is duplicate
-  List<ParameterElement?>? _resolveArgumentsToFunction(
-      ArgumentList argumentList, ExecutableElement? executableElement) {
-    if (executableElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = executableElement.parameters;
-    return _resolveArgumentsToParameters(argumentList, parameters);
-  }
-
-  /// Given an [argumentList] and the [parameters] related to the element that
-  /// will be invoked using those arguments, compute the list of parameters that
-  /// correspond to the list of arguments. An error will be reported if any of
-  /// the arguments cannot be matched to a parameter. Return the parameters that
-  /// correspond to the arguments.
-  ///
-  /// TODO(scheglov) this is duplicate
-  List<ParameterElement?> _resolveArgumentsToParameters(
-      ArgumentList argumentList, List<ParameterElement> parameters) {
-    return ResolverVisitor.resolveArgumentsToParameters(
-        argumentList, parameters, _errorReporter.reportErrorForNode);
-  }
-
   void _resolveConstructorInvocationArguments(AnnotationImpl node) {
     var argumentList = node.arguments;
     // error will be reported in ConstantVerifier
@@ -470,10 +441,12 @@
     // resolve arguments to parameters
     var constructor = node.element;
     if (constructor is ConstructorElement) {
-      var parameters = _resolveArgumentsToFunction(argumentList, constructor);
-      if (parameters != null) {
-        argumentList.correspondingStaticParameters = parameters;
-      }
+      argumentList.correspondingStaticParameters =
+          ResolverVisitor.resolveArgumentsToParameters(
+        argumentList: argumentList,
+        parameters: constructor.parameters,
+        errorReporter: _errorReporter,
+      );
     }
   }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
index f824a1e..625037b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -88,7 +88,9 @@
         // Fix up the parameter elements based on inferred method.
         arguments.correspondingStaticParameters =
             ResolverVisitor.resolveArgumentsToParameters(
-                arguments, inferred.parameters, null);
+          argumentList: arguments,
+          parameters: inferred.parameters,
+        );
 
         constructorName.type2.type = inferred.returnType;
 
@@ -118,8 +120,8 @@
     _inferArgumentTypes(node);
     _resolver.visitArgumentList(node.argumentList,
         whyNotPromotedList: whyNotPromotedList);
-    node.accept(_resolver.elementResolver);
-    node.accept(_resolver.typeAnalyzer);
+    _resolver.elementResolver.visitInstanceCreationExpression(node);
+    _resolver.typeAnalyzer.visitInstanceCreationExpression(node);
     _resolver.checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index d7a8fd2..765d3d5 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -190,7 +190,9 @@
       // Fix up the parameter elements based on inferred method.
       arguments.correspondingStaticParameters =
           ResolverVisitor.resolveArgumentsToParameters(
-              arguments, inferred.parameters, null);
+        argumentList: arguments,
+        parameters: inferred.parameters,
+      );
       node.staticInvokeType = inferred;
     }
   }
@@ -272,12 +274,11 @@
   ///
   /// @param expression the node whose type is to be recorded
   /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplication
   void recordStaticType(ExpressionImpl expression, DartType type) {
     var hooks = _migrationResolutionHooks;
     if (hooks != null) {
-      type = hooks.modifyExpressionType(expression, type);
+      type = hooks.modifyExpressionType(
+          expression, type, InferenceContext.getContext(expression));
     }
 
     expression.staticType = type;
@@ -381,7 +382,9 @@
     // Get the parameters that correspond to the uninstantiated generic.
     List<ParameterElement?> rawParameters =
         ResolverVisitor.resolveArgumentsToParameters(
-            argumentList, rawType.parameters, null);
+      argumentList: argumentList,
+      parameters: rawType.parameters,
+    );
 
     List<ParameterElement> params = <ParameterElement>[];
     List<DartType> argTypes = <DartType>[];
@@ -537,9 +540,9 @@
     FunctionType invokeType,
   ) {
     var parameters = ResolverVisitor.resolveArgumentsToParameters(
-      argumentList,
-      invokeType.parameters,
-      _errorReporter.reportErrorForNode,
+      argumentList: argumentList,
+      parameters: invokeType.parameters,
+      errorReporter: _errorReporter,
     );
     argumentList.correspondingStaticParameters = parameters;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index ab438c7..2c26796 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -195,24 +195,6 @@
     return type is InterfaceType && type.isDartCoreFunction;
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplicate
-  void _recordStaticType(ExpressionImpl expression, DartType type) {
-    var hooks = _resolver.migrationResolutionHooks;
-    if (hooks != null) {
-      type = hooks.modifyExpressionType(expression, type);
-    }
-
-    expression.staticType = type;
-    if (_resolver.typeSystem.isBottom(type)) {
-      _resolver.flowAnalysis.flow?.handleExit();
-    }
-  }
-
   void _reportInstanceAccessToStaticMember(
     SimpleIdentifier nameNode,
     ExecutableElement element,
@@ -842,7 +824,7 @@
     DartType getterReturnType,
   ) {
     var targetType = _resolveTypeParameter(getterReturnType);
-    _recordStaticType(node.methodName, targetType);
+    _inferenceHelper.recordStaticType(node.methodName, targetType);
 
     ExpressionImpl functionExpression;
     var target = node.target;
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index e4476e7..a108a8b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -125,16 +125,6 @@
     }
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplicate
-  void _recordStaticType(ExpressionImpl expression, DartType type) {
-    _inferenceHelper.recordStaticType(expression, type);
-  }
-
   void _resolve1(PrefixExpressionImpl node) {
     Token operator = node.operator;
     TokenType operatorType = operator.type;
@@ -195,7 +185,7 @@
   void _resolve2(PrefixExpressionImpl node) {
     TokenType operator = node.operator.type;
     if (identical(node.readType, NeverTypeImpl.instance)) {
-      _recordStaticType(node, NeverTypeImpl.instance);
+      _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
     } else {
       // The other cases are equivalent to invoking a method.
       var staticMethodElement = node.staticElement;
@@ -216,7 +206,7 @@
           }
         }
       }
-      _recordStaticType(node, staticType);
+      _inferenceHelper.recordStaticType(node, staticType);
     }
     _resolver.nullShortingTermination(node);
   }
@@ -232,7 +222,7 @@
     _resolver.boolExpressionVerifier.checkForNonBoolNegationExpression(operand,
         whyNotPromoted: whyNotPromoted);
 
-    _recordStaticType(node, _typeProvider.boolType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
 
     _resolver.flowAnalysis.flow?.logicalNot_end(node, operand);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
index eb97c1f..4a1e23d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -44,8 +44,8 @@
     }
 
     if (identical(node.prefix.staticType, NeverTypeImpl.instance)) {
-      _recordStaticType(identifier, NeverTypeImpl.instance);
-      _recordStaticType(node, NeverTypeImpl.instance);
+      _inferenceHelper.recordStaticType(identifier, NeverTypeImpl.instance);
+      _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
       return;
     }
 
@@ -92,8 +92,8 @@
       // breaking change release.
       type = _inferenceHelper.inferTearOff(node, identifier, type);
     }
-    _recordStaticType(identifier, type);
-    _recordStaticType(node, type);
+    _inferenceHelper.recordStaticType(identifier, type);
+    _inferenceHelper.recordStaticType(node, type);
   }
 
   /// Return the type that should be recorded for a node that resolved to the given accessor.
@@ -142,16 +142,6 @@
     return true;
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplicate
-  void _recordStaticType(ExpressionImpl expression, DartType type) {
-    _inferenceHelper.recordStaticType(expression, type);
-  }
-
   /// TODO(scheglov) this is duplicate
   void _setExtensionIdentifierType(IdentifierImpl node) {
     if (node is SimpleIdentifierImpl && node.inDeclarationContext()) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 8138fda..7145bd0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -348,13 +348,13 @@
           name: name,
           nameOffset: nameOffset,
           parameterKind: node.kind,
-        );
+        )..constantInitializer = node.defaultValue;
       } else {
         element = DefaultParameterElementImpl(
           name: name,
           nameOffset: nameOffset,
           parameterKind: node.kind,
-        );
+        )..constantInitializer = node.defaultValue;
       }
       _elementHolder.addParameter(element);
 
@@ -383,7 +383,6 @@
           defaultValue.accept(this);
         });
       });
-      element.defaultValueCode = defaultValue.toSource();
     }
   }
 
@@ -395,6 +394,15 @@
 
     node.metadata.accept(this);
     _setElementAnnotations(node.metadata, element.metadata);
+
+    var arguments = node.arguments;
+    if (arguments != null) {
+      _withElementWalker(null, () {
+        _withElementHolder(ElementHolder(element), () {
+          arguments.accept(this);
+        });
+      });
+    }
   }
 
   @override
@@ -407,8 +415,13 @@
 
     _withElementWalker(ElementWalker.forClass(element), () {
       _withNameScope(() {
+        _buildTypeParameterElements(node.typeParameters);
+        node.typeParameters?.accept(this);
+
         _defineElements(element.accessors);
+        _defineElements(element.methods);
         node.constants.accept(this);
+        node.members.accept(this);
       });
     });
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index 1f9befa..16c0251 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -11,16 +11,18 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
 class SimpleIdentifierResolver {
   final ResolverVisitor _resolver;
-  final FlowAnalysisHelper? _flowAnalysis;
 
-  SimpleIdentifierResolver(this._resolver, this._flowAnalysis);
+  final InvocationInferenceHelper _inferenceHelper;
+
+  SimpleIdentifierResolver(this._resolver)
+      : _inferenceHelper = _resolver.inferenceHelper;
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
@@ -101,24 +103,6 @@
     return false;
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplicate
-  void _recordStaticType(ExpressionImpl expression, DartType type) {
-    var hooks = _resolver.migrationResolutionHooks;
-    if (hooks != null) {
-      type = hooks.modifyExpressionType(expression, type);
-    }
-
-    expression.staticType = type;
-    if (_resolver.typeSystem.isBottom(type)) {
-      _flowAnalysis?.flow?.handleExit();
-    }
-  }
-
   void _resolve1(SimpleIdentifierImpl node) {
     //
     // Synthetic identifiers have been already reported during parsing.
@@ -180,21 +164,15 @@
         !identical(element, enclosingClass)) {
       // This error is now reported by the parser.
       element = null;
-    } else if ((element is PrefixElement?) &&
-        (element == null || !_isValidAsPrefix(node))) {
+    } else if (element is PrefixElement && !_isValidAsPrefix(node)) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+        node,
+        [element.name],
+      );
+    } else if (element == null) {
       // TODO(brianwilkerson) Recover from this error.
-      if (_isConstructorReturnType(node)) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
-      } else if (parent is Annotation) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
-      } else if (element != null) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-            node,
-            [element.name]);
-      } else if (node.name == "await" && _resolver.enclosingFunction != null) {
+      if (node.name == "await" && _resolver.enclosingFunction != null) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
           node,
@@ -267,7 +245,7 @@
       staticType =
           _resolver.inferenceHelper.inferTearOff(node, node, staticType);
     }
-    _recordStaticType(node, staticType);
+    _inferenceHelper.recordStaticType(node, staticType);
   }
 
   /// TODO(scheglov) this is duplicate
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index a9fce6a..bb7a033 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -676,24 +676,6 @@
     }
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) Inline this.
-  void _recordStaticType(ExpressionImpl expression, DartType type) {
-    expression.staticType = type;
-//    if (type == null) {
-//      expression.staticType = _dynamicType;
-//    } else {
-//      expression.staticType = type;
-//      if (identical(type, NeverTypeImpl.instance)) {
-//        _flowAnalysis?.flow?.handleExit();
-//      }
-//    }
-  }
-
   void _resolveListLiteral2(ListLiteralImpl node) {
     var typeArguments = node.typeArguments?.arguments;
 
@@ -703,12 +685,9 @@
       if (typeArguments.length == 1) {
         elementType = typeArguments[0].typeOrThrow;
       }
-      _recordStaticType(
-        node,
-        _typeProvider.listElement.instantiate(
-          typeArguments: [elementType],
-          nullabilitySuffix: _noneOrStarSuffix,
-        ),
+      node.staticType = _typeProvider.listElement.instantiate(
+        typeArguments: [elementType],
+        nullabilitySuffix: _noneOrStarSuffix,
       );
       return;
     }
@@ -721,12 +700,12 @@
     if (inferred != listDynamicType) {
       // TODO(brianwilkerson) Determine whether we need to make the inferred
       //  type non-nullable here or whether it will already be non-nullable.
-      _recordStaticType(node, inferred!);
+      node.staticType = inferred!;
       return;
     }
 
     // If we have no type arguments and couldn't infer any, use dynamic.
-    _recordStaticType(node, listDynamicType);
+    node.staticType = listDynamicType;
   }
 
   void _resolveSetOrMapLiteral2(SetOrMapLiteralImpl node) {
@@ -739,24 +718,18 @@
       if (typeArguments.length == 1) {
         node.becomeSet();
         var elementType = typeArguments[0].typeOrThrow;
-        _recordStaticType(
-          node,
-          _typeProvider.setElement.instantiate(
-            typeArguments: [elementType],
-            nullabilitySuffix: _noneOrStarSuffix,
-          ),
+        node.staticType = _typeProvider.setElement.instantiate(
+          typeArguments: [elementType],
+          nullabilitySuffix: _noneOrStarSuffix,
         );
         return;
       } else if (typeArguments.length == 2) {
         node.becomeMap();
         var keyType = typeArguments[0].typeOrThrow;
         var valueType = typeArguments[1].typeOrThrow;
-        _recordStaticType(
-          node,
-          _typeProvider.mapElement.instantiate(
-            typeArguments: [keyType, valueType],
-            nullabilitySuffix: _noneOrStarSuffix,
-          ),
+        node.staticType = _typeProvider.mapElement.instantiate(
+          typeArguments: [keyType, valueType],
+          nullabilitySuffix: _noneOrStarSuffix,
         );
         return;
       }
@@ -787,7 +760,7 @@
     // TODO(brianwilkerson) Decide whether the literalType needs to be made
     //  non-nullable here or whether that will have happened in
     //  _inferSetOrMapLiteralType.
-    _recordStaticType(node, literalType);
+    node.staticType = literalType;
   }
 
   DartType _toMapType(SetOrMapLiteral node, DartType? contextType,
diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart
index 11ad6a2..6681a49 100644
--- a/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart
+++ b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart
@@ -69,6 +69,41 @@
     ]);
   }
 
+  /// Return a diagnostic indicating that [member] is not a correct override of
+  /// [superMember].
+  AnalysisError invalidOverride(
+      Source source,
+      ErrorCode? errorCode,
+      AstNode errorNode,
+      ExecutableElement member,
+      ExecutableElement superMember) {
+    errorCode ??= CompileTimeErrorCode.INVALID_OVERRIDE;
+    // Elements enclosing members that can participate in overrides are always
+    // named, so we can safely assume `_thisMember.enclosingElement.name` and
+    // `superMember.enclosingElement.name` are non-`null`.
+    return AnalysisError(
+        source, errorNode.offset, errorNode.length, errorCode, [
+      member.name,
+      member.enclosingElement.name!,
+      member.type,
+      superMember.enclosingElement.name!,
+      superMember.type,
+    ], [
+      // Only include the context location for INVALID_OVERRIDE because for
+      // some other types this location is not ideal (for example
+      // INVALID_IMPLEMENTATION_OVERRIDE may provide the subclass as superMember
+      // if the subclass has an abstract member and the superclass has the
+      // concrete).
+      if (errorCode == CompileTimeErrorCode.INVALID_OVERRIDE)
+        DiagnosticMessageImpl(
+            filePath: superMember.source.fullName,
+            message: "The member being overridden.",
+            offset: superMember.nonSynthetic.nameOffset,
+            length: superMember.nonSynthetic.nameLength,
+            url: null)
+    ]);
+  }
+
   /// Return a diagnostic indicating that the given [identifier] was referenced
   /// before it was declared.
   AnalysisError referencedBeforeDeclaration(
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 42f8ae1..edeba68 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -3483,9 +3483,10 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when there's more than one field
-  // formal parameter for the same field in a constructor's parameter list. It
-  // isn't useful to assign a value that will immediately be overwritten.
+  // The analyzer produces this diagnostic when there's more than one
+  // initializing formal parameter for the same field in a constructor's
+  // parameter list. It isn't useful to assign a value that will immediately be
+  // overwritten.
   //
   // #### Example
   //
@@ -3502,7 +3503,7 @@
   //
   // #### Common fixes
   //
-  // Remove one of the field formal parameters:
+  // Remove one of the initializing formal parameters:
   //
   // ```dart
   // class C {
@@ -4521,27 +4522,30 @@
 
   static const CompileTimeErrorCode EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER =
       CompileTimeErrorCode(
-    'EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER',
-    "External fields cannot have initializers.",
+    'EXTERNAL_WITH_INITIALIZER',
+    "External fields can't have initializers.",
     correctionMessage:
         "Try removing the field initializer or the 'external' keyword from the "
         "field declaration.",
+    uniqueName: 'EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER',
   );
 
   static const CompileTimeErrorCode EXTERNAL_FIELD_INITIALIZER =
       CompileTimeErrorCode(
-    'EXTERNAL_FIELD_INITIALIZER',
-    "External fields cannot have initializers.",
+    'EXTERNAL_WITH_INITIALIZER',
+    "External fields can't have initializers.",
     correctionMessage:
         "Try removing the initializer or the 'external' keyword.",
+    uniqueName: 'EXTERNAL_FIELD_INITIALIZER',
   );
 
   static const CompileTimeErrorCode EXTERNAL_VARIABLE_INITIALIZER =
       CompileTimeErrorCode(
-    'EXTERNAL_VARIABLE_INITIALIZER',
-    "External variables cannot have initializers.",
+    'EXTERNAL_WITH_INITIALIZER',
+    "External variables can't have initializers.",
     correctionMessage:
         "Try removing the initializer or the 'external' keyword.",
+    uniqueName: 'EXTERNAL_VARIABLE_INITIALIZER',
   );
 
   /**
@@ -4748,7 +4752,8 @@
   // #### Example
   //
   // The following code produces this diagnostic because the field `f` is
-  // initialized both by a field formal parameter and in the initializer list:
+  // initialized both by an initializing formal parameter and in the
+  // initializer list:
   //
   // ```dart
   // class C {
@@ -4806,14 +4811,14 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when a factory constructor has a
-  // field formal parameter. Factory constructors can't assign values to fields
-  // because no instance is created; hence, there is no field to assign.
+  // The analyzer produces this diagnostic when a factory constructor has an
+  // initializing formal parameter. Factory constructors can't assign values to
+  // fields because no instance is created; hence, there is no field to assign.
   //
   // #### Example
   //
   // The following code produces this diagnostic because the factory constructor
-  // uses a field formal parameter:
+  // uses an initializing formal parameter:
   //
   // ```dart
   // class C {
@@ -4825,7 +4830,7 @@
   //
   // #### Common fixes
   //
-  // Replace the field formal parameter with a normal parameter:
+  // Replace the initializing formal parameter with a normal parameter:
   //
   // ```dart
   // class C {
@@ -4921,8 +4926,8 @@
   // #### Examples
   //
   // The following code produces this diagnostic because the constructor
-  // `C.zero`, which redirects to the constructor `C`, has a field formal
-  // parameter that initializes the field `f`:
+  // `C.zero`, which redirects to the constructor `C`, has an initializing
+  // formal parameter that initializes the field `f`:
   //
   // ```dart
   // class C {
@@ -4950,8 +4955,8 @@
   //
   // #### Common fixes
   //
-  // If the initialization is done by a field formal parameter, then use a
-  // normal parameter:
+  // If the initialization is done by an initializing formal parameter, then
+  // use a normal parameter:
   //
   // ```dart
   // class C {
@@ -4991,14 +4996,16 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when the type of a field formal
-  // parameter isn't assignable to the type of the field being initialized.
+  // The analyzer produces this diagnostic when the type of an initializing
+  // formal parameter isn't assignable to the type of the field being
+  // initialized.
   //
   // #### Example
   //
-  // The following code produces this diagnostic because the field formal
-  // parameter has the type `String`, but the type of the field is `int`. The
-  // parameter must have a type that is a subtype of the field's type.
+  // The following code produces this diagnostic because the initializing
+  // formal parameter has the type `String`, but the type of the field is
+  // `int`. The parameter must have a type that is a subtype of the field's
+  // type.
   //
   // ```dart
   // class C {
@@ -5034,8 +5041,8 @@
   // ```
   //
   // If the types of both the field and the parameter are correct, then use an
-  // initializer rather than a field formal parameter to convert the parameter
-  // value into a value of the correct type:
+  // initializer rather than an initializing formal parameter to convert the
+  // parameter value into a value of the correct type:
   //
   // ```dart
   // class C {
@@ -5136,7 +5143,7 @@
   //
   // For instance fields, you can add an initializer as shown in the previous
   // example, or you can initialize the field in every constructor. You can
-  // initialize the field by using a field formal parameter:
+  // initialize the field by using an initializing formal parameter:
   //
   // ```dart
   // class C {
@@ -5188,8 +5195,8 @@
   //
   // #### Common fixes
   //
-  // If the value should be passed in to the constructor directly, then use a
-  // field formal parameter to initialize the field `value`:
+  // If the value should be passed in to the constructor directly, then use an
+  // initializing formal parameter to initialize the field `value`:
   //
   // ```dart
   // class C {
@@ -5952,6 +5959,28 @@
     hasPublishedDocs: true,
   );
 
+  static const CompileTimeErrorCode
+      IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT =
+      CompileTimeErrorCode(
+    'IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT',
+    "The named parameter '{0}' is required in the implicitly invoked unnamed "
+        "constructor of '{1}'.",
+    correctionMessage:
+        "Try declaring corresponding named super-parameter, or explicitly "
+        "invoking a different constructor.",
+  );
+
+  static const CompileTimeErrorCode
+      IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS =
+      CompileTimeErrorCode(
+    'IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS',
+    "The implicitly invoked unnamed constructor of '{0}' expects {1} "
+        "positional arguments, but {2} found.",
+    correctionMessage:
+        "Try declaring positional super-parameters, or explicitly invoking a "
+        "different constructor.",
+  );
+
   /**
    * Parameters:
    * 0: the uri pointing to a library
@@ -6174,14 +6203,14 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when a static field is initialized in
-  // a constructor using either a field formal parameter or an assignment in the
-  // initializer list.
+  // The analyzer produces this diagnostic when a static field is initialized
+  // in a constructor using either an initializing formal parameter or an
+  // assignment in the initializer list.
   //
   // #### Example
   //
-  // The following code produces this diagnostic because the static field `a` is
-  // being initialized by the field formal parameter `this.a`:
+  // The following code produces this diagnostic because the static field `a`
+  // is being initialized by the initializing formal parameter `this.a`:
   //
   // ```dart
   // class C {
@@ -6239,10 +6268,10 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when a field formal parameter is
-  // found in a constructor in a class that doesn't declare the field being
-  // initialized. Constructors can't initialize fields that aren't declared and
-  // fields that are inherited from superclasses.
+  // The analyzer produces this diagnostic when an initializing formal
+  // parameter is found in a constructor in a class that doesn't declare the
+  // field being initialized. Constructors can't initialize fields that aren't
+  // declared and fields that are inherited from superclasses.
   //
   // #### Example
   //
@@ -6991,7 +7020,7 @@
   static const CompileTimeErrorCode INVALID_CAST_LITERAL_MAP =
       CompileTimeErrorCode(
     'INVALID_CAST_LITERAL_MAP',
-    "The map literal type '{0}' isn't of expected type '{1}'. The maps's type "
+    "The map literal type '{0}' isn't of expected type '{1}'. The map's type "
         "can be changed with an explicit generic type arguments or by changing "
         "the key and value types.",
   );
@@ -7045,16 +7074,6 @@
   );
 
   /**
-   * 7.6 Constructors: It is a compile-time error if the name of a constructor
-   * is not a constructor name.
-   */
-  static const CompileTimeErrorCode INVALID_CONSTRUCTOR_NAME =
-      CompileTimeErrorCode(
-    'INVALID_CONSTRUCTOR_NAME',
-    "Invalid constructor name.",
-  );
-
-  /**
    * No parameters.
    */
   // #### Description
@@ -7520,6 +7539,20 @@
 
   /**
    * Parameters:
+   * 0: the super modifier
+   */
+  static const CompileTimeErrorCode INVALID_SUPER_FORMAL_PARAMETER_LOCATION =
+      CompileTimeErrorCode(
+    'INVALID_SUPER_FORMAL_PARAMETER_LOCATION',
+    "Super-formal parameters can only be used in non-redirecting generative "
+        "constructors.",
+    correctionMessage:
+        "Try removing the 'super' modifier, or changing the constructor to be "
+        "non-redirecting and generative.",
+  );
+
+  /**
+   * Parameters:
    * 0: the name of the type parameter
    */
   // #### Description
@@ -8398,35 +8431,38 @@
 
   /**
    * 12.1 Constants: A constant expression is ... a constant list literal.
+   *
+   * Note: This diagnostic is never displayed to the user, so it doesn't need
+   * to be documented.
    */
   static const CompileTimeErrorCode MISSING_CONST_IN_LIST_LITERAL =
       CompileTimeErrorCode(
     'MISSING_CONST_IN_LIST_LITERAL',
-    "List literals must be prefixed with 'const' when used as a constant "
-        "expression.",
-    correctionMessage: "Try adding the keyword 'const' before the literal.",
+    "Seeing this message constitutes a bug. Please report it.",
   );
 
   /**
    * 12.1 Constants: A constant expression is ... a constant map literal.
+   *
+   * Note: This diagnostic is never displayed to the user, so it doesn't need
+   * to be documented.
    */
   static const CompileTimeErrorCode MISSING_CONST_IN_MAP_LITERAL =
       CompileTimeErrorCode(
     'MISSING_CONST_IN_MAP_LITERAL',
-    "Map literals must be prefixed with 'const' when used as a constant "
-        "expression.",
-    correctionMessage: "Try adding the keyword 'const' before the literal.",
+    "Seeing this message constitutes a bug. Please report it.",
   );
 
   /**
    * 12.1 Constants: A constant expression is ... a constant set literal.
+   *
+   * Note: This diagnostic is never displayed to the user, so it doesn't need
+   * to be documented.
    */
   static const CompileTimeErrorCode MISSING_CONST_IN_SET_LITERAL =
       CompileTimeErrorCode(
     'MISSING_CONST_IN_SET_LITERAL',
-    "Set literals must be prefixed with 'const' when used as a constant "
-        "expression.",
-    correctionMessage: "Try adding the keyword 'const' before the literal.",
+    "Seeing this message constitutes a bug. Please report it.",
   );
 
   /**
@@ -8510,6 +8546,20 @@
   );
 
   /**
+   * No parameters.
+   */
+  static const CompileTimeErrorCode
+      MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION =
+      CompileTimeErrorCode(
+    'MISSING_DEFAULT_VALUE_FOR_PARAMETER',
+    "With null safety, use the 'required' keyword, not the '@required' "
+        "annotation.",
+    correctionMessage: "Try removing the '@'.",
+    hasPublishedDocs: true,
+    uniqueName: 'MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION',
+  );
+
+  /**
    * Parameters:
    * 0: the name of the parameter
    */
@@ -8859,16 +8909,6 @@
   );
 
   /**
-   * The <i>mixinMember</i> production allows the same instance or static
-   * members that a class would allow, but no constructors (for now).
-   */
-  static const CompileTimeErrorCode MIXIN_DECLARES_CONSTRUCTOR =
-      CompileTimeErrorCode(
-    'MIXIN_DECLARES_CONSTRUCTOR',
-    "Mixins can't declare constructors.",
-  );
-
-  /**
    * No parameters.
    */
   static const CompileTimeErrorCode MIXIN_DEFERRED_CLASS = CompileTimeErrorCode(
@@ -8879,29 +8919,6 @@
     uniqueName: 'MIXIN_DEFERRED_CLASS',
   );
 
-  static const CompileTimeErrorCode
-      MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES = CompileTimeErrorCode(
-    'MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES',
-    "Type parameters couldn't be inferred for the mixin '{0}' because the base "
-        "class implements the mixin's supertype constraint '{1}' in multiple "
-        "conflicting ways",
-  );
-
-  static const CompileTimeErrorCode MIXIN_INFERENCE_NO_MATCHING_CLASS =
-      CompileTimeErrorCode(
-    'MIXIN_INFERENCE_NO_MATCHING_CLASS',
-    "Type parameters couldn't be inferred for the mixin '{0}' because the base "
-        "class doesn't implement the mixin's supertype constraint '{1}'",
-  );
-
-  static const CompileTimeErrorCode MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION =
-      CompileTimeErrorCode(
-    'MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION',
-    "Type parameters couldn't be inferred for the mixin '{0}' because no type "
-        "parameter substitution could be found matching the mixin's supertype "
-        "constraints",
-  );
-
   /**
    * Parameters:
    * 0: the name of the mixin that is invalid
@@ -11614,6 +11631,20 @@
   );
 
   /**
+   * No parameters.
+   */
+  static const CompileTimeErrorCode
+      POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT =
+      CompileTimeErrorCode(
+    'POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT',
+    "Positional super-formal parameters can't be used when the "
+        "super-constructor invocation has a positional argument.",
+    correctionMessage:
+        "Try removing the 'super' modifier, or changing the super-constructor "
+        "to use named parameters.",
+  );
+
+  /**
    * Parameters:
    * 0: the name of the prefix
    */
@@ -13064,6 +13095,45 @@
   );
 
   /**
+   * Parameters:
+   * 0: the type of super-parameter
+   * 1: the type of associated super-constructor parameter
+   */
+  static const CompileTimeErrorCode
+      SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED =
+      CompileTimeErrorCode(
+    'SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED',
+    "The type '{0}' of this parameter is not a subtype of the type '{1}' of "
+        "the associated super-constructor parameter.",
+    correctionMessage:
+        "Try removing the explicit type annotation from the parameter.",
+  );
+
+  /**
+   * No parameters.
+   */
+  static const CompileTimeErrorCode
+      SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED = CompileTimeErrorCode(
+    'SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED',
+    "No associated named super-constructor parameter.",
+    correctionMessage: "Try changing the name to the name of an existing named "
+        "super-constructor parameter, or creating such named parameter.",
+  );
+
+  /**
+   * No parameters.
+   */
+  static const CompileTimeErrorCode
+      SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL =
+      CompileTimeErrorCode(
+    'SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL',
+    "No associated positional super-constructor parameter.",
+    correctionMessage:
+        "Try using named parameters instead, or adding more positional "
+        "parameters to the super-constructor.",
+  );
+
+  /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It
    * is a compile-time error if a generative constructor of class Object
    * includes a superinitializer.
diff --git a/pkg/analyzer/lib/src/error/correct_override.dart b/pkg/analyzer/lib/src/error/correct_override.dart
index 1066a3c..2169256 100644
--- a/pkg/analyzer/lib/src/error/correct_override.dart
+++ b/pkg/analyzer/lib/src/error/correct_override.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 
 class CorrectOverrideHelper {
@@ -23,6 +24,8 @@
   final ExecutableElement _thisMember;
   FunctionType? _thisTypeForSubtype;
 
+  final DiagnosticFactory _diagnosticFactory = DiagnosticFactory();
+
   CorrectOverrideHelper({
     required LibraryElementImpl library,
     required ExecutableElement thisMember,
@@ -52,20 +55,12 @@
   }) {
     var isCorrect = isCorrectOverrideOf(superMember: superMember);
     if (!isCorrect) {
-      // Elements enclosing members that can participate in overrides are always
-      // named, so we can safely assume `_thisMember.enclosingElement.name` and
-      // `superMember.enclosingElement.name` are non-`null`.
-      errorReporter.reportErrorForNode(
-        errorCode ?? CompileTimeErrorCode.INVALID_OVERRIDE,
-        errorNode,
-        [
-          _thisMember.name,
-          _thisMember.enclosingElement.name!,
-          _thisMember.type,
-          superMember.enclosingElement.name!,
-          superMember.type,
-        ],
-      );
+      errorReporter.reportError(_diagnosticFactory.invalidOverride(
+          errorReporter.source,
+          errorCode,
+          errorNode,
+          _thisMember,
+          superMember));
     }
   }
 
diff --git a/pkg/analyzer/lib/src/error/super_formal_parameters_verifier.dart b/pkg/analyzer/lib/src/error/super_formal_parameters_verifier.dart
new file mode 100644
index 0000000..309ead0
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/super_formal_parameters_verifier.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/listener.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/error/codes.dart';
+
+VerifySuperFormalParametersResult verifySuperFormalParameters({
+  required ConstructorDeclaration constructor,
+  ErrorReporter? errorReporter,
+  bool hasExplicitPositionalArguments = false,
+}) {
+  var result = VerifySuperFormalParametersResult();
+  for (var parameter in constructor.parameters.parameters) {
+    parameter = parameter.notDefault;
+    if (parameter is SuperFormalParameter) {
+      var parameterElement =
+          parameter.declaredElement as SuperFormalParameterElementImpl;
+      if (parameter.isNamed) {
+        result.namedArgumentNames.add(parameterElement.name);
+      } else {
+        result.positionalArgumentCount++;
+        if (hasExplicitPositionalArguments) {
+          errorReporter?.reportErrorForNode(
+            CompileTimeErrorCode
+                .POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
+            parameter.identifier,
+          );
+        }
+      }
+    }
+  }
+  return result;
+}
+
+class VerifySuperFormalParametersResult {
+  /// The count of positional arguments provided by the super-parameters.
+  int positionalArgumentCount = 0;
+
+  /// The names of named arguments provided by the super-parameters.
+  List<String> namedArgumentNames = [];
+}
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 9db6af2..1488253 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -13,12 +13,10 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/diagnostic/diagnostic.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/resolver.dart';
 
 class TypeArgumentsVerifier {
   final AnalysisOptionsImpl _options;
@@ -252,7 +250,7 @@
       return;
     }
     var type = node.typeOrThrow;
-    if (_isMissingTypeArguments(node, type, node.name.staticElement, null)) {
+    if (_isMissingTypeArguments(node, type, node.name.staticElement)) {
       AstNode unwrappedParent = parentEscapingTypeArguments(node);
       if (unwrappedParent is AsExpression || unwrappedParent is IsExpression) {
         // Do not report a "Strict raw type" error in this case; too noisy.
@@ -539,8 +537,7 @@
   ///   contain `_`
   /// - [type] does not have any `dynamic` type arguments.
   /// - the element is marked with `@optionalTypeArgs` from "package:meta".
-  bool _isMissingTypeArguments(AstNode node, DartType type, Element? element,
-      Expression? inferenceContextNode) {
+  bool _isMissingTypeArguments(AstNode node, DartType type, Element? element) {
     List<DartType> typeArguments;
     var alias = type.alias;
     if (alias != null) {
@@ -554,16 +551,6 @@
     // Check if this type has type arguments and at least one is dynamic.
     // If so, we may need to issue a strict-raw-types error.
     if (typeArguments.any((t) => t.isDynamic)) {
-      // If we have an inference context node, check if the type was inferred
-      // from it. Some cases will not have a context type, such as the type
-      // annotation `List` in `List list;`
-      if (inferenceContextNode != null) {
-        var contextType = InferenceContext.getContext(inferenceContextNode);
-        if (contextType != null && UnknownInferredType.isKnown(contextType)) {
-          // Type was inferred from downwards context: not an error.
-          return false;
-        }
-      }
       if (element != null && element.hasOptionalTypeArgs) {
         return false;
       }
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index 9984e82..e9d4b77 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'dart:math' as math;
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -25,6 +26,12 @@
   ClassElement? _enclosingClass;
   ExecutableElement? _enclosingExec;
 
+  /// Non-null when the visitor is inside an [IsExpression]'s type.
+  IsExpression? _enclosingIsExpression;
+
+  /// Non-null when the visitor is inside a [VariableDeclarationList]'s type.
+  VariableDeclarationList? _enclosingVariableDeclaration;
+
   GatherUsedLocalElementsVisitor(this._enclosingLibrary);
 
   @override
@@ -73,6 +80,27 @@
   }
 
   @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    var element = node.declaredElement!;
+    var redirectedConstructor = node.redirectedConstructor;
+    if (redirectedConstructor != null) {
+      var redirectedElement = redirectedConstructor.staticElement;
+      if (redirectedElement != null) {
+        // TODO(scheglov) Only if not _isPubliclyAccessible
+        _matchParameters(
+          element.parameters,
+          redirectedElement.parameters,
+          (first, second) {
+            usedElements.addElement(second);
+          },
+        );
+      }
+    }
+
+    super.visitConstructorDeclaration(node);
+  }
+
+  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     var enclosingExecOld = _enclosingExec;
     try {
@@ -114,6 +142,18 @@
   }
 
   @override
+  void visitIsExpression(IsExpression node) {
+    var enclosingIsExpressionOld = _enclosingIsExpression;
+    node.expression.accept(this);
+    try {
+      _enclosingIsExpression = node;
+      node.type.accept(this);
+    } finally {
+      _enclosingIsExpression = enclosingIsExpressionOld;
+    }
+  }
+
+  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     var enclosingExecOld = _enclosingExec;
     try {
@@ -178,21 +218,22 @@
         usedElements.addElement(element);
       }
     } else {
-      _useIdentifierElement(node, node.readElement);
-      _useIdentifierElement(node, node.writeElement);
-      _useIdentifierElement(node, node.staticElement);
       var parent = node.parent!;
-      // If [node] is a method tear-off, assume all parameters are used.
+      _useIdentifierElement(node, node.readElement, parent: parent);
+      _useIdentifierElement(node, node.writeElement, parent: parent);
+      _useIdentifierElement(node, node.staticElement, parent: parent);
+      var grandparent = parent.parent;
+      // If [node] is a tear-off, assume all parameters are used.
       var functionReferenceIsCall =
           (element is ExecutableElement && parent is MethodInvocation) ||
               // named constructor
               (element is ConstructorElement &&
                   parent is ConstructorName &&
-                  parent.parent is InstanceCreationExpression) ||
+                  grandparent is InstanceCreationExpression) ||
               // unnamed constructor
               (element is ClassElement &&
-                  parent.parent is ConstructorName &&
-                  parent.parent!.parent is InstanceCreationExpression);
+                  grandparent is ConstructorName &&
+                  grandparent.parent is InstanceCreationExpression);
       if (element is ExecutableElement &&
           isIdentifierRead &&
           !functionReferenceIsCall) {
@@ -224,6 +265,19 @@
     }
   }
 
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    node.metadata.accept(this);
+    var enclosingVariableDeclarationOld = _enclosingVariableDeclaration;
+    try {
+      _enclosingVariableDeclaration = node;
+      node.type?.accept(this);
+    } finally {
+      _enclosingVariableDeclaration = enclosingVariableDeclarationOld;
+    }
+    node.variables.accept(this);
+  }
+
   /// Add [element] as a used member and, if [element] is a setter, add its
   /// corresponding getter as a used member.
   void _addMemberAndCorrespondingGetter(Element element) {
@@ -236,7 +290,11 @@
   }
 
   /// Marks the [element] of [node] as used in the library.
-  void _useIdentifierElement(Identifier node, Element? element) {
+  void _useIdentifierElement(
+    Identifier node,
+    Element? element, {
+    required AstNode parent,
+  }) {
     if (element == null) {
       return;
     }
@@ -252,17 +310,17 @@
       return;
     }
     // Ignore places where the element is not actually used.
-    if (node.parent is NamedType) {
+    if (parent is NamedType) {
       if (element is ClassElement) {
-        AstNode parent2 = node.parent!.parent!;
-        if (parent2 is IsExpression) {
-          return;
-        }
-        if (parent2 is VariableDeclarationList) {
+        var enclosingVariableDeclaration = _enclosingVariableDeclaration;
+        if (enclosingVariableDeclaration != null) {
           // If it's a field's type, it still counts as used.
-          if (parent2.parent is! FieldDeclaration) {
+          if (enclosingVariableDeclaration.parent is! FieldDeclaration) {
             return;
           }
+        } else if (_enclosingIsExpression != null) {
+          // An interface type found in an `is` expression is not used.
+          return;
         }
       }
     }
@@ -305,6 +363,51 @@
     // OK
     return true;
   }
+
+  /// Invokes [f] for corresponding positional and named parameters.
+  /// Ignores parameters that don't have a corresponding pair.
+  /// TODO(scheglov) There might be a better place for this function.
+  static void _matchParameters(
+    List<ParameterElement> firstList,
+    List<ParameterElement> secondList,
+    void Function(ParameterElement first, ParameterElement second) f,
+  ) {
+    Map<String, ParameterElement>? firstNamed;
+    Map<String, ParameterElement>? secondNamed;
+    var firstPositional = <ParameterElement>[];
+    var secondPositional = <ParameterElement>[];
+    for (var element in firstList) {
+      if (element.isNamed) {
+        (firstNamed ??= {})[element.name] = element;
+      } else {
+        firstPositional.add(element);
+      }
+    }
+    for (var element in secondList) {
+      if (element.isNamed) {
+        (secondNamed ??= {})[element.name] = element;
+      } else {
+        secondPositional.add(element);
+      }
+    }
+
+    var positionalLength = math.min(
+      firstPositional.length,
+      secondPositional.length,
+    );
+    for (var i = 0; i < positionalLength; i++) {
+      f(firstPositional[i], secondPositional[i]);
+    }
+
+    if (firstNamed != null && secondNamed != null) {
+      for (var firstEntry in firstNamed.entries) {
+        var second = secondNamed[firstEntry.key];
+        if (second != null) {
+          f(firstEntry.value, second);
+        }
+      }
+    }
+  }
 }
 
 /// Instances of the class [UnusedLocalElementsVerifier] traverse an AST
diff --git a/pkg/analyzer/lib/src/error/use_result_verifier.dart b/pkg/analyzer/lib/src/error/use_result_verifier.dart
index 521d5b6..a2bd7bb 100644
--- a/pkg/analyzer/lib/src/error/use_result_verifier.dart
+++ b/pkg/analyzer/lib/src/error/use_result_verifier.dart
@@ -149,6 +149,14 @@
       return parent.target == node;
     }
 
+    if (parent is PrefixedIdentifier) {
+      if (parent.prefix == node) {
+        return true;
+      } else {
+        return _isUsed(parent);
+      }
+    }
+
     if (parent is ParenthesizedExpression ||
         parent is ConditionalExpression ||
         parent is AwaitExpression) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 455a0f6..db03646 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -31,6 +31,7 @@
         templateExpectedButGot,
         templateExpectedIdentifier,
         templateExperimentNotEnabled,
+        templateExtraneousModifier,
         templateInternalProblemUnhandled,
         templateUnexpectedToken;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
@@ -51,7 +52,7 @@
     show translateErrorToken;
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' hide StringToken;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
-    show StringToken, SyntheticStringToken, SyntheticToken;
+    show KeywordToken, StringToken, SyntheticStringToken, SyntheticToken;
 import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -63,6 +64,9 @@
         ClassDeclarationImpl,
         CompilationUnitImpl,
         ConstructorNameImpl,
+        EnumConstantArgumentsImpl,
+        ConstructorSelectorImpl,
+        EnumConstantDeclarationImpl,
         EnumDeclarationImpl,
         ExtensionDeclarationImpl,
         ImportDirectiveImpl,
@@ -1552,6 +1556,13 @@
       if (superKeyword != null) {
         assert(thisKeyword == null,
             "Can't have both 'this' and 'super' in a parameter.");
+        if (keyword is KeywordToken && keyword.keyword == Keyword.VAR) {
+          handleRecoverableError(
+            templateExtraneousModifier.withArguments(keyword),
+            keyword,
+            keyword,
+          );
+        }
         node = ast.superFormalParameter(
             comment: comment,
             metadata: metadata,
@@ -2801,17 +2812,17 @@
   @override
   void handleEnumElement(Token beginToken) {
     debugEvent("EnumElement");
-    var arguments = pop() as MethodInvocationImpl?;
-    var constructorName = pop() as ConstructorNameImpl?;
+    var tmpArguments = pop() as MethodInvocationImpl?;
+    var tmpConstructor = pop() as ConstructorNameImpl?;
 
     if (!enableEnhancedEnums &&
-        (arguments != null ||
-            constructorName != null &&
-                (constructorName.type2.typeArguments != null ||
-                    constructorName.name != null))) {
-      Token token = arguments != null
-          ? arguments.argumentList.beginToken
-          : constructorName!.beginToken;
+        (tmpArguments != null ||
+            tmpConstructor != null &&
+                (tmpConstructor.type2.typeArguments != null ||
+                    tmpConstructor.name != null))) {
+      Token token = tmpArguments != null
+          ? tmpArguments.argumentList.beginToken
+          : tmpConstructor!.beginToken;
       var feature = ExperimentalFeatures.enhanced_enums;
       handleRecoverableError(
         templateExperimentNotEnabled.withArguments(
@@ -2822,6 +2833,37 @@
         token,
       );
     }
+
+    var constant = pop() as EnumConstantDeclarationImpl;
+
+    // Replace the constant to include arguments.
+    if (tmpArguments != null) {
+      TypeArgumentListImpl? typeArguments;
+      ConstructorSelectorImpl? constructorName;
+      if (tmpConstructor != null) {
+        typeArguments = tmpConstructor.type2.typeArguments;
+        var constructorNamePeriod = tmpConstructor.period;
+        var constructorNameId = tmpConstructor.name;
+        if (constructorNamePeriod != null && constructorNameId != null) {
+          constructorName = ConstructorSelectorImpl(
+            period: constructorNamePeriod,
+            name: constructorNameId,
+          );
+        }
+      }
+      constant = EnumConstantDeclarationImpl(
+        documentationComment: constant.documentationComment,
+        metadata: constant.metadata,
+        name: constant.name,
+        arguments: EnumConstantArgumentsImpl(
+          typeArguments: typeArguments,
+          constructorSelector: constructorName,
+          argumentList: tmpArguments.argumentList,
+        ),
+      );
+    }
+
+    push(constant);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index c430007..b32cea7 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
@@ -74,7 +73,7 @@
 /// undeclared variables (which is an error) and names in hide and show
 /// combinators that are not defined in the imported library (which is not an
 /// error).
-class ElementResolver extends SimpleAstVisitor<void> {
+class ElementResolver {
   /// The resolver driving this participant.
   final ResolverVisitor _resolver;
 
@@ -112,24 +111,19 @@
 
   TypeProviderImpl get _typeProvider => _resolver.typeProvider;
 
-  @override
   void visitClassDeclaration(ClassDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitClassTypeAlias(ClassTypeAlias node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitCommentReference(CommentReference node) {
     _commentReferenceResolver.resolve(node);
   }
 
-  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    super.visitConstructorDeclaration(node);
     ConstructorElement element = node.declaredElement!;
     if (element is ConstructorElementImpl) {
       var redirectedNode = node.redirectedConstructor;
@@ -150,7 +144,6 @@
     }
   }
 
-  @override
   void visitConstructorFieldInitializer(
       covariant ConstructorFieldInitializerImpl node) {
     var fieldName = node.fieldName;
@@ -159,7 +152,6 @@
     fieldName.staticElement = fieldElement;
   }
 
-  @override
   void visitConstructorName(covariant ConstructorNameImpl node) {
     var type = node.type2.type;
     if (type == null) {
@@ -183,22 +175,18 @@
     }
   }
 
-  @override
   void visitDeclaredIdentifier(DeclaredIdentifier node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitEnumDeclaration(EnumDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitExportDirective(ExportDirective node) {
     var exportElement = node.element;
     if (exportElement != null) {
@@ -210,43 +198,34 @@
     }
   }
 
-  @override
   void visitExtensionDeclaration(ExtensionDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitFieldFormalParameter(FieldFormalParameter node) {
     _resolveMetadataForParameter(node);
-    super.visitFieldFormalParameter(node);
   }
 
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
     _resolveMetadataForParameter(node);
   }
 
-  @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitImportDirective(covariant ImportDirectiveImpl node) {
     var prefixNode = node.prefix;
     if (prefixNode != null) {
@@ -272,7 +251,6 @@
     }
   }
 
-  @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
     var invokedConstructor = node.constructorName.staticElement;
@@ -284,17 +262,14 @@
     }
   }
 
-  @override
   void visitLibraryDirective(LibraryDirective node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitMethodInvocation(MethodInvocation node,
       {List<WhyNotPromotedGetter>? whyNotPromotedList}) {
     whyNotPromotedList ??= [];
@@ -302,22 +277,18 @@
         node as MethodInvocationImpl, whyNotPromotedList);
   }
 
-  @override
   void visitMixinDeclaration(MixinDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitPartDirective(PartDirective node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitPartOfDirective(PartOfDirective node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitRedirectingConstructorInvocation(
       covariant RedirectingConstructorInvocationImpl node) {
     var enclosingClass = _resolver.enclosingClass;
@@ -348,12 +319,10 @@
     }
   }
 
-  @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     _resolveMetadataForParameter(node);
   }
 
-  @override
   void visitSuperConstructorInvocation(
       covariant SuperConstructorInvocationImpl node) {
     var enclosingClass = _resolver.enclosingClass;
@@ -406,13 +375,16 @@
       return;
     }
     var argumentList = node.argumentList;
-    var parameters = _resolveArgumentsToFunction(argumentList, element);
+    var parameters = _resolveArgumentsToFunction(
+      argumentList,
+      element,
+      enclosingConstructor: node.thisOrAncestorOfType<ConstructorDeclaration>(),
+    );
     if (parameters != null) {
       argumentList.correspondingStaticParameters = parameters;
     }
   }
 
-  @override
   void visitSuperExpression(SuperExpression node) {
     var context = SuperContext.of(node);
     if (context == SuperContext.annotation || context == SuperContext.static) {
@@ -422,20 +394,16 @@
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.SUPER_IN_EXTENSION, node);
     }
-    super.visitSuperExpression(node);
   }
 
-  @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitTypeParameter(TypeParameter node) {
     _resolveAnnotations(node.metadata);
   }
 
-  @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     _resolveAnnotations(node.metadata);
   }
@@ -446,23 +414,19 @@
   /// cannot be matched to a parameter. Return the parameters that correspond to
   /// the arguments, or `null` if no correspondence could be computed.
   List<ParameterElement?>? _resolveArgumentsToFunction(
-      ArgumentList argumentList, ExecutableElement? executableElement) {
+    ArgumentList argumentList,
+    ExecutableElement? executableElement, {
+    ConstructorDeclaration? enclosingConstructor,
+  }) {
     if (executableElement == null) {
       return null;
     }
-    List<ParameterElement> parameters = executableElement.parameters;
-    return _resolveArgumentsToParameters(argumentList, parameters);
-  }
-
-  /// Given an [argumentList] and the [parameters] related to the element that
-  /// will be invoked using those arguments, compute the list of parameters that
-  /// correspond to the list of arguments. An error will be reported if any of
-  /// the arguments cannot be matched to a parameter. Return the parameters that
-  /// correspond to the arguments.
-  List<ParameterElement?> _resolveArgumentsToParameters(
-      ArgumentList argumentList, List<ParameterElement> parameters) {
     return ResolverVisitor.resolveArgumentsToParameters(
-        argumentList, parameters, _errorReporter.reportErrorForNode);
+      argumentList: argumentList,
+      parameters: executableElement.parameters,
+      errorReporter: _errorReporter,
+      enclosingConstructor: enclosingConstructor,
+    );
   }
 
   /// Resolve the names in the given [combinators] in the scope of the given
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 1d7d77c..6746259 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -37,6 +37,7 @@
 import 'package:analyzer/src/error/literal_element_verifier.dart';
 import 'package:analyzer/src/error/required_parameters_verifier.dart';
 import 'package:analyzer/src/error/return_type_verifier.dart';
+import 'package:analyzer/src/error/super_formal_parameters_verifier.dart';
 import 'package:analyzer/src/error/type_arguments_verifier.dart';
 import 'package:analyzer/src/error/use_result_verifier.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
@@ -201,11 +202,7 @@
 
   /// The class containing the AST nodes being visited, or `null` if we are not
   /// in the scope of a class.
-  ClassElementImpl? _enclosingClass;
-
-  /// The enum containing the AST nodes being visited, or `null` if we are not
-  /// in the scope of an enum.
-  ClassElement? _enclosingEnum;
+  ClassElement? _enclosingClass;
 
   /// The element of the extension being visited, or `null` if we are not
   /// in the scope of an extension.
@@ -280,11 +277,8 @@
   /// should not be modified in the middle of visiting a tree and requires an
   /// analyzer-provided Impl instance to work.
   set enclosingClass(ClassElement? classElement) {
-    assert(classElement is ClassElementImpl);
     assert(_enclosingClass == null);
-    assert(_enclosingEnum == null);
     assert(_enclosingExecutable.element == null);
-    _enclosingClass = classElement as ClassElementImpl;
   }
 
   /// The language team is thinking about adding abstract fields, or external
@@ -562,13 +556,13 @@
 
   @override
   void visitEnumDeclaration(EnumDeclaration node) {
-    var outerEnum = _enclosingEnum;
+    var outerClass = _enclosingClass;
     try {
-      _enclosingEnum = node.declaredElement;
+      _enclosingClass = node.declaredElement;
       _duplicateDefinitionVerifier.checkEnum(node);
       super.visitEnumDeclaration(node);
     } finally {
-      _enclosingEnum = outerEnum;
+      _enclosingClass = outerClass;
     }
   }
 
@@ -1140,6 +1134,46 @@
   }
 
   @override
+  void visitSuperFormalParameter(SuperFormalParameter node) {
+    super.visitSuperFormalParameter(node);
+
+    var constructor = node.parentFormalParameterList.parent;
+    if (!(constructor is ConstructorDeclaration &&
+        constructor.isNonRedirectingGenerative)) {
+      errorReporter.reportErrorForToken(
+        CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION,
+        node.superKeyword,
+      );
+      return;
+    }
+
+    var element = node.declaredElement as SuperFormalParameterElementImpl;
+    var superParameter = element.superConstructorParameter;
+
+    if (superParameter == null) {
+      errorReporter.reportErrorForNode(
+        node.isNamed
+            ? CompileTimeErrorCode
+                .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED
+            : CompileTimeErrorCode
+                .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+        node.identifier,
+      );
+      return;
+    }
+
+    if (!_currentLibrary.typeSystem
+        .isSubtypeOf(element.type, superParameter.type)) {
+      errorReporter.reportErrorForNode(
+        CompileTimeErrorCode
+            .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+        node.identifier,
+        [element.type, superParameter.type],
+      );
+    }
+  }
+
+  @override
   void visitSwitchCase(SwitchCase node) {
     _withHiddenElements(node.statements, () {
       _duplicateDefinitionVerifier.checkStatements(node.statements);
@@ -1288,7 +1322,6 @@
           CompileTimeErrorCode.IMPLEMENTS_REPEATED);
       _checkImplementsSuperClass(implementsClause);
       _checkMixinsSuperClass(withClause);
-      _checkMixinInference(node, withClause);
       _checkForMixinWithConflictingPrivateMember(withClause, superclass);
       _checkForConflictingGenerics(node);
       if (node is ClassDeclaration) {
@@ -1765,23 +1798,23 @@
   }
 
   /// Verify all conflicts between type variable and enclosing class.
-  /// TODO(scheglov)
   void _checkForConflictingClassTypeVariableErrorCodes() {
-    for (TypeParameterElement typeParameter
-        in _enclosingClass!.typeParameters) {
+    var enclosingClass = _enclosingClass!;
+    for (TypeParameterElement typeParameter in enclosingClass.typeParameters) {
       String name = typeParameter.name;
       // name is same as the name of the enclosing class
-      if (_enclosingClass!.name == name) {
-        var code = _enclosingClass!.isMixin
+      if (enclosingClass.name == name) {
+        var code = enclosingClass.isMixin
             ? CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN
             : CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS;
         errorReporter.reportErrorForElement(code, typeParameter, [name]);
       }
       // check members
-      if (_enclosingClass!.getMethod(name) != null ||
-          _enclosingClass!.getGetter(name) != null ||
-          _enclosingClass!.getSetter(name) != null) {
-        var code = _enclosingClass!.isMixin
+      if (enclosingClass.getNamedConstructor(name) != null ||
+          enclosingClass.getMethod(name) != null ||
+          enclosingClass.getGetter(name) != null ||
+          enclosingClass.getSetter(name) != null) {
+        var code = enclosingClass.isMixin
             ? CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN
             : CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS;
         errorReporter.reportErrorForElement(code, typeParameter, [name]);
@@ -1943,9 +1976,11 @@
   /// [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD].
   bool _checkForConstConstructorWithNonConstSuper(
       ConstructorDeclaration constructor) {
-    if (!_enclosingExecutable.isConstConstructor) {
+    var enclosingClass = _enclosingClass;
+    if (enclosingClass == null || !_enclosingExecutable.isConstConstructor) {
       return false;
     }
+
     // OK, const factory, checked elsewhere
     if (constructor.factoryKeyword != null) {
       return false;
@@ -1953,7 +1988,7 @@
 
     // check for mixins
     var instanceFields = <FieldElement>[];
-    for (var mixin in _enclosingClass!.mixins) {
+    for (var mixin in enclosingClass.mixins) {
       instanceFields.addAll(mixin.element.fields.where((field) {
         if (field.isStatic) {
           return false;
@@ -1989,6 +2024,11 @@
       return true;
     }
 
+    // Enum(s) always call a const super-constructor.
+    if (enclosingClass.isEnum) {
+      return false;
+    }
+
     // try to find and check super constructor invocation
     for (ConstructorInitializer initializer in constructor.initializers) {
       if (initializer is SuperConstructorInvocation) {
@@ -2004,7 +2044,7 @@
       }
     }
     // no explicit super constructor invocation, check default constructor
-    var supertype = _enclosingClass!.supertype;
+    var supertype = enclosingClass.supertype;
     if (supertype == null) {
       return false;
     }
@@ -4159,15 +4199,6 @@
       return;
     }
 
-    // TODO(scheglov) Restore when working on errors.
-    if (_currentLibrary.featureSet.isEnabled(Feature.super_parameters)) {
-      if (constructor.parameters.parameters.any((parameter) {
-        return parameter.notDefault is SuperFormalParameter;
-      })) {
-        return;
-      }
-    }
-
     // Ignore if the constructor has either an implicit super constructor
     // invocation or a redirecting constructor invocation.
     for (ConstructorInitializer constructorInitializer
@@ -4185,37 +4216,88 @@
       return;
     }
     ClassElement superElement = superType.element;
+
     if (superElement.constructors
         .every((constructor) => constructor.isFactory)) {
       // Already reported [NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS].
       return;
     }
+
     var superUnnamedConstructor = superElement.unnamedConstructor;
     superUnnamedConstructor = superUnnamedConstructor != null
         ? _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor)
         : superUnnamedConstructor;
-    if (superUnnamedConstructor != null) {
-      if (superUnnamedConstructor.isFactory) {
-        errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
-            constructor.returnType,
-            [superUnnamedConstructor]);
-      } else if (!superUnnamedConstructor.isDefaultConstructor) {
-        Identifier returnType = constructor.returnType;
-        var name = constructor.name;
-        int offset = returnType.offset;
-        int length = (name != null ? name.end : returnType.end) - offset;
-        errorReporter.reportErrorForOffset(
-            CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
-            offset,
-            length,
-            [superType]);
-      }
-    } else {
+    if (superUnnamedConstructor == null) {
       errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
-          constructor.returnType,
-          [superElement.name]);
+        CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
+        constructor.returnType,
+        [superElement.name],
+      );
+      return;
+    }
+
+    if (superUnnamedConstructor.isFactory) {
+      errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
+        constructor.returnType,
+        [superUnnamedConstructor],
+      );
+      return;
+    }
+
+    var requiredPositionalParameterCount = superUnnamedConstructor.parameters
+        .where((parameter) => parameter.isRequiredPositional)
+        .length;
+    var requiredNamedParameters = superUnnamedConstructor.parameters
+        .where((parameter) => parameter.isRequiredNamed)
+        .map((parameter) => parameter.name)
+        .toSet();
+
+    void reportError(ErrorCode errorCode, List<Object> arguments) {
+      Identifier returnType = constructor.returnType;
+      var name = constructor.name;
+      int offset = returnType.offset;
+      int length = (name != null ? name.end : returnType.end) - offset;
+      errorReporter.reportErrorForOffset(errorCode, offset, length, arguments);
+    }
+
+    if (!_currentLibrary.featureSet.isEnabled(Feature.super_parameters)) {
+      if (requiredPositionalParameterCount != 0 ||
+          requiredNamedParameters.isNotEmpty) {
+        reportError(
+          CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
+          [superType],
+        );
+      }
+      return;
+    }
+
+    var superParametersResult = verifySuperFormalParameters(
+      constructor: constructor,
+      errorReporter: errorReporter,
+    );
+    requiredNamedParameters.removeAll(
+      superParametersResult.namedArgumentNames,
+    );
+
+    if (requiredPositionalParameterCount >
+        superParametersResult.positionalArgumentCount) {
+      reportError(
+        CompileTimeErrorCode
+            .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+        [
+          superType,
+          requiredPositionalParameterCount,
+          superParametersResult.positionalArgumentCount,
+        ],
+      );
+    }
+    for (var requiredNamedParameterName in requiredNamedParameters) {
+      reportError(
+        CompileTimeErrorCode
+            .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
+        [requiredNamedParameterName, superType],
+      );
     }
   }
 
@@ -4326,9 +4408,6 @@
     if (identical(enclosingElement, _enclosingClass)) {
       return;
     }
-    if (identical(enclosingElement, _enclosingEnum)) {
-      return;
-    }
     if (enclosingElement is! ClassElement) {
       return;
     }
@@ -4675,56 +4754,6 @@
     }
   }
 
-  void _checkMixinInference(
-      NamedCompilationUnitMember node, WithClause? withClause) {
-    if (withClause == null) {
-      return;
-    }
-    var classElement = node.declaredElement as ClassElement;
-    var supertype = classElement.supertype;
-
-    var interfacesMerger = InterfacesMerger(typeSystem);
-    interfacesMerger.addWithSupertypes(supertype);
-
-    for (var namedType in withClause.mixinTypes2) {
-      var mixinType = namedType.type;
-      if (mixinType is InterfaceType) {
-        var mixinElement = mixinType.element;
-        if (namedType.typeArguments == null) {
-          var mixinSupertypeConstraints = typeSystem
-              .gatherMixinSupertypeConstraintsForInference(mixinElement);
-          if (mixinSupertypeConstraints.isNotEmpty) {
-            var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
-              namedType,
-              mixinSupertypeConstraints,
-              interfacesMerger.typeList,
-            );
-            if (matchingInterfaceTypes != null) {
-              // Try to pattern match matchingInterfaceType against
-              // mixinSupertypeConstraint to find the correct set of type
-              // parameters to apply to the mixin.
-              var inferredTypeArguments = typeSystem.matchSupertypeConstraints(
-                mixinElement,
-                mixinSupertypeConstraints,
-                matchingInterfaceTypes,
-                genericMetadataIsEnabled: _currentLibrary.featureSet
-                    .isEnabled(Feature.generic_metadata),
-              );
-              if (inferredTypeArguments == null) {
-                errorReporter.reportErrorForToken(
-                    CompileTimeErrorCode
-                        .MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
-                    namedType.name.beginToken,
-                    [namedType]);
-              }
-            }
-          }
-        }
-        interfacesMerger.addWithSupertypes(mixinType);
-      }
-    }
-  }
-
   /// Checks the class for problems with the superclass, mixins, or implemented
   /// interfaces.
   void _checkMixinInheritance(MixinDeclaration node, OnClause? onClause,
@@ -4856,66 +4885,32 @@
               parameterName ?? parameter,
             );
           }
-        } else if (defaultValuesAreExpected && parameter.defaultValue == null) {
-          var type = parameter.declaredElement!.type;
-          if (typeSystem.isPotentiallyNonNullable(type)) {
-            var parameterName = _parameterName(parameter);
-            errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
-              parameterName ?? parameter,
-              [parameterName?.name ?? '?'],
-            );
+        } else if (defaultValuesAreExpected) {
+          var parameterElement = parameter.declaredElement!;
+          if (!parameterElement.hasDefaultValue) {
+            var type = parameterElement.type;
+            if (typeSystem.isPotentiallyNonNullable(type)) {
+              var parameterName = _parameterName(parameter);
+              if (parameterElement.hasRequired) {
+                errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode
+                      .MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
+                  parameterName ?? parameter,
+                );
+              } else {
+                errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
+                  parameterName ?? parameter,
+                  [parameterName?.name ?? '?'],
+                );
+              }
+            }
           }
         }
       }
     }
   }
 
-  InterfaceType? _findInterfaceTypeForMixin(NamedType mixin,
-      InterfaceType supertypeConstraint, List<InterfaceType> interfaceTypes) {
-    var element = supertypeConstraint.element;
-    InterfaceType? foundInterfaceType;
-    for (var interfaceType in interfaceTypes) {
-      if (interfaceType.element != element) continue;
-      if (foundInterfaceType == null) {
-        foundInterfaceType = interfaceType;
-      } else {
-        if (interfaceType != foundInterfaceType) {
-          errorReporter.reportErrorForToken(
-              CompileTimeErrorCode
-                  .MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES,
-              mixin.name.beginToken,
-              [mixin, supertypeConstraint]);
-        }
-      }
-    }
-    if (foundInterfaceType == null) {
-      errorReporter.reportErrorForToken(
-          CompileTimeErrorCode.MIXIN_INFERENCE_NO_MATCHING_CLASS,
-          mixin.name.beginToken,
-          [mixin, supertypeConstraint]);
-    }
-    return foundInterfaceType;
-  }
-
-  List<InterfaceType>? _findInterfaceTypesForConstraints(
-      NamedType mixin,
-      List<InterfaceType> supertypeConstraints,
-      List<InterfaceType> interfaceTypes) {
-    var result = <InterfaceType>[];
-    for (var constraint in supertypeConstraints) {
-      var interfaceType =
-          _findInterfaceTypeForMixin(mixin, constraint, interfaceTypes);
-      if (interfaceType == null) {
-        // No matching interface type found, so inference fails.  The error has
-        // already been reported.
-        return null;
-      }
-      result.add(interfaceType);
-    }
-    return result;
-  }
-
   /// Given an [expression] in a switch case whose value is expected to be an
   /// enum constant, return the name of the constant.
   String? _getConstantName(Expression expression) {
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 53ec6ae..3735ddd 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -24,6 +24,7 @@
   static const _allocatorExtensionName = 'AllocatorAlloc';
   static const _arrayClassName = 'Array';
   static const _dartFfiLibraryName = 'dart.ffi';
+  static const _finalizableClassName = 'Finalizable';
   static const _isLeafParamName = 'isLeaf';
   static const _opaqueClassName = 'Opaque';
   static const _ffiNativeName = 'FfiNative';
@@ -116,7 +117,8 @@
     void checkSupertype(NamedType typename, FfiCode subtypeOfFfiCode,
         FfiCode subtypeOfStructCode) {
       final superName = typename.name.staticElement?.name;
-      if (superName == _allocatorClassName) {
+      if (superName == _allocatorClassName ||
+          superName == _finalizableClassName) {
         return;
       }
       if (typename.ffiClass != null) {
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index 75fa4d3..9891065 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -39,137 +39,3 @@
     return arguments[index].toString();
   });
 }
-
-/// Very limited printf implementation, supports only %s and %d.
-String _printf(String fmt, List args) {
-  StringBuffer sb = StringBuffer();
-  bool markFound = false;
-  int argIndex = 0;
-  for (int i = 0; i < fmt.length; i++) {
-    int c = fmt.codeUnitAt(i);
-    if (c == 0x25) {
-      if (markFound) {
-        sb.writeCharCode(c);
-        markFound = false;
-      } else {
-        markFound = true;
-      }
-      continue;
-    }
-    if (markFound) {
-      markFound = false;
-      // %d
-      if (c == 0x64) {
-        sb.write(args[argIndex++]);
-        continue;
-      }
-      // %s
-      if (c == 0x73) {
-        sb.write(args[argIndex++]);
-        continue;
-      }
-      // unknown
-      throw ArgumentError('[$fmt][$i] = 0x${c.toRadixString(16)}');
-    } else {
-      sb.writeCharCode(c);
-    }
-  }
-  return sb.toString();
-}
-
-class Character {
-  static const int MAX_VALUE = 0xffff;
-  static const int MAX_CODE_POINT = 0x10ffff;
-  static const int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
-  static const int MIN_LOW_SURROGATE = 0xDC00;
-  static const int MIN_HIGH_SURROGATE = 0xD800;
-
-  static int digit(int codePoint, int radix) {
-    if (radix != 16) {
-      throw ArgumentError("only radix == 16 is supported");
-    }
-    if (0x30 <= codePoint && codePoint <= 0x39) {
-      return codePoint - 0x30;
-    }
-    if (0x41 <= codePoint && codePoint <= 0x46) {
-      return 0xA + (codePoint - 0x41);
-    }
-    if (0x61 <= codePoint && codePoint <= 0x66) {
-      return 0xA + (codePoint - 0x61);
-    }
-    return -1;
-  }
-
-  static bool isDigit(int c) => c >= 0x30 && c <= 0x39;
-
-  static bool isLetter(int c) =>
-      c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
-
-  static bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
-
-  static bool isWhitespace(int c) =>
-      c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
-
-  static String toChars(int codePoint) {
-    if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
-      throw ArgumentError();
-    }
-    if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
-      return String.fromCharCode(codePoint);
-    }
-    int offset = codePoint - MIN_SUPPLEMENTARY_CODE_POINT;
-    int c0 = ((offset & 0x7FFFFFFF) >> 10) + MIN_HIGH_SURROGATE;
-    int c1 = (offset & 0x3ff) + MIN_LOW_SURROGATE;
-    return String.fromCharCodes([c0, c1]);
-  }
-}
-
-@deprecated
-abstract class Enum<E extends Enum<E>> implements Comparable<E> {
-  /// The name of this enum constant, as declared in the enum declaration.
-  final String name;
-
-  /// The position in the enum declaration.
-  final int ordinal;
-
-  const Enum(this.name, this.ordinal);
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(E other) => ordinal - other.ordinal;
-
-  @override
-  String toString() => name;
-}
-
-@deprecated
-class PrintStringWriter extends PrintWriter {
-  final StringBuffer _sb = StringBuffer();
-
-  @override
-  void print(Object x) {
-    _sb.write(x);
-  }
-
-  @override
-  String toString() => _sb.toString();
-}
-
-abstract class PrintWriter {
-  void newLine() {
-    print('\n');
-  }
-
-  void print(Object x);
-
-  void printf(String fmt, List args) {
-    print(_printf(fmt, args));
-  }
-
-  void println(String s) {
-    print(s);
-    newLine();
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/java_io.dart b/pkg/analyzer/lib/src/generated/java_io.dart
deleted file mode 100644
index 4751bc4..0000000
--- a/pkg/analyzer/lib/src/generated/java_io.dart
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:io";
-
-import 'package:path/path.dart' as path;
-
-@Deprecated('Use ResourceProvider and path context instead.')
-class JavaFile {
-  @deprecated
-  static path.Context pathContext = path.context;
-  static final String separator = Platform.pathSeparator;
-  static final int separatorChar = Platform.pathSeparator.codeUnitAt(0);
-  late final String _path;
-  JavaFile(String path) {
-    _path = path;
-  }
-  JavaFile.fromUri(Uri uri) : this(path.context.fromUri(uri));
-  JavaFile.relative(JavaFile base, String child) {
-    if (child.isEmpty) {
-      _path = base._path;
-    } else {
-      _path = path.context.join(base._path, child);
-    }
-  }
-  @override
-  int get hashCode => _path.hashCode;
-  @override
-  bool operator ==(Object other) {
-    return other is JavaFile && other._path == _path;
-  }
-
-  bool exists() {
-    if (_newFile().existsSync()) {
-      return true;
-    }
-    if (_newDirectory().existsSync()) {
-      return true;
-    }
-    return false;
-  }
-
-  JavaFile getAbsoluteFile() => JavaFile(getAbsolutePath());
-  String getAbsolutePath() {
-    String abolutePath = path.context.absolute(_path);
-    abolutePath = path.context.normalize(abolutePath);
-    return abolutePath;
-  }
-
-  JavaFile getCanonicalFile() => JavaFile(getCanonicalPath());
-  String getCanonicalPath() {
-    return _newFile().resolveSymbolicLinksSync();
-  }
-
-  String getName() => path.context.basename(_path);
-  String? getParent() {
-    var result = path.context.dirname(_path);
-    // "." or  "/" or  "C:\"
-    if (result.length < 4) return null;
-    return result;
-  }
-
-  JavaFile? getParentFile() {
-    var parent = getParent();
-    if (parent == null) return null;
-    return JavaFile(parent);
-  }
-
-  String getPath() => _path;
-  bool isDirectory() {
-    return _newDirectory().existsSync();
-  }
-
-  bool isExecutable() {
-    return _newFile().statSync().mode & 0x111 != 0;
-  }
-
-  bool isFile() {
-    return _newFile().existsSync();
-  }
-
-  int lastModified() {
-    try {
-      return _newFile().lastModifiedSync().millisecondsSinceEpoch;
-    } catch (exception) {
-      return -1;
-    }
-  }
-
-  List<JavaFile> listFiles() {
-    var files = <JavaFile>[];
-    var entities = _newDirectory().listSync();
-    for (FileSystemEntity entity in entities) {
-      files.add(JavaFile(entity.path));
-    }
-    return files;
-  }
-
-  String readAsStringSync() => _newFile().readAsStringSync();
-  @override
-  String toString() => _path.toString();
-  Uri toURI() {
-    String absolutePath = getAbsolutePath();
-    return path.context.toUri(absolutePath);
-  }
-
-  Directory _newDirectory() => Directory(_path);
-  File _newFile() => File(_path);
-}
diff --git a/pkg/analyzer/lib/src/generated/migration.dart b/pkg/analyzer/lib/src/generated/migration.dart
index 6bd94fa..0da672d 100644
--- a/pkg/analyzer/lib/src/generated/migration.dart
+++ b/pkg/analyzer/lib/src/generated/migration.dart
@@ -23,7 +23,8 @@
   /// Called after the resolver has determined the type of an expression node.
   /// Should return the type that the expression has after migrations have been
   /// applied.
-  DartType modifyExpressionType(Expression expression, DartType dartType);
+  DartType modifyExpressionType(
+      Expression expression, DartType dartType, DartType? contextType);
 
   /// Called after the resolver has inferred the type of a function literal
   /// parameter.  Should return the type that the parameter has after migrations
@@ -31,6 +32,11 @@
   DartType modifyInferredParameterType(
       ParameterElement parameter, DartType type);
 
+  /// Called at the beginning of visiting a binary expression, to report the
+  /// context type of the binary expression.
+  void reportBinaryExpressionContext(
+      BinaryExpression node, DartType? contextType);
+
   /// Called after the resolver has determined the read and write types
   /// of the assignment expression.
   void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ddcbc07..5820062 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -60,6 +60,7 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/dead_code_verifier.dart';
 import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
+import 'package:analyzer/src/error/super_formal_parameters_verifier.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error_detection_helpers.dart';
@@ -160,10 +161,10 @@
   }
 }
 
-/// Base class for visitors that perform resolution.  This class keeps track of
-/// some of the basic information that is needed by resolution stages, such as
-/// the defining library and the error reporter.
-abstract class ResolverBase extends UnifyingAstVisitor<void> {
+/// Instances of the class `ResolverVisitor` are used to resolve the nodes
+/// within a single compilation unit.
+class ResolverVisitor extends ThrowingAstVisitor<void>
+    with ErrorDetectionHelpers {
   /// The element for the library containing the compilation unit being visited.
   final LibraryElementImpl definingLibrary;
 
@@ -173,22 +174,9 @@
   /// The object used to access the types from the core library.
   final TypeProviderImpl typeProvider;
 
-  /// The error reporter that will be informed of any errors that are found
-  /// during resolution.
+  @override
   final ErrorReporter errorReporter;
 
-  ResolverBase(this.definingLibrary, this.source, this.typeProvider,
-      AnalysisErrorListener errorListener)
-      : errorReporter = ErrorReporter(
-          errorListener,
-          source,
-          isNonNullableByDefault: definingLibrary.isNonNullableByDefault,
-        );
-}
-
-/// Instances of the class `ResolverVisitor` are used to resolve the nodes
-/// within a single compilation unit.
-class ResolverVisitor extends ResolverBase with ErrorDetectionHelpers {
   /// The class containing the AST nodes being visited,
   /// or `null` if we are not in the scope of a class.
   ClassElement? enclosingClass;
@@ -291,7 +279,7 @@
       InstanceCreationExpressionResolver(this);
 
   late final SimpleIdentifierResolver _simpleIdentifierResolver =
-      SimpleIdentifierResolver(this, flowAnalysis);
+      SimpleIdentifierResolver(this);
 
   late final PropertyElementResolver _propertyElementResolver =
       PropertyElementResolver(this);
@@ -325,7 +313,7 @@
             definingLibrary,
             source,
             definingLibrary.typeSystem,
-            typeProvider,
+            typeProvider as TypeProviderImpl,
             errorListener,
             featureSet ??
                 definingLibrary.context.analysisOptions.contextFeatures,
@@ -335,19 +323,22 @@
 
   ResolverVisitor._(
       this.inheritance,
-      LibraryElementImpl definingLibrary,
-      Source source,
+      this.definingLibrary,
+      this.source,
       this.typeSystem,
-      TypeProvider typeProvider,
+      this.typeProvider,
       AnalysisErrorListener errorListener,
       FeatureSet featureSet,
       this.flowAnalysis,
       this._migratableAstInfoProvider,
       MigrationResolutionHooks? migrationResolutionHooks)
-      : _featureSet = featureSet,
-        migrationResolutionHooks = migrationResolutionHooks,
-        super(definingLibrary, source, typeProvider as TypeProviderImpl,
-            errorListener) {
+      : errorReporter = ErrorReporter(
+          errorListener,
+          source,
+          isNonNullableByDefault: definingLibrary.isNonNullableByDefault,
+        ),
+        _featureSet = featureSet,
+        migrationResolutionHooks = migrationResolutionHooks {
     var analysisOptions =
         definingLibrary.context.analysisOptions as AnalysisOptionsImpl;
 
@@ -411,7 +402,7 @@
     elementResolver = ElementResolver(this,
         migratableAstInfoProvider: _migratableAstInfoProvider);
     inferenceContext = InferenceContext._(this);
-    typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
+    typeAnalyzer = StaticTypeAnalyzer(this);
     _functionReferenceResolver =
         FunctionReferenceResolver(this, _isNonNullableByDefault);
   }
@@ -1068,6 +1059,13 @@
   }
 
   @override
+  void visitAdjacentStrings(AdjacentStrings node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitAdjacentStrings(node as AdjacentStringsImpl);
+  }
+
+  @override
   void visitAnnotation(covariant AnnotationImpl node) {
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     _annotationResolver.resolve(node, whyNotPromotedList);
@@ -1153,13 +1151,13 @@
       flow?.equalityOp_end(
           node.parent as Expression, secondArg, secondArg.typeOrThrow);
     }
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
   }
 
   @override
   void visitAsExpression(AsExpression node) {
-    super.visitAsExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitAsExpression(node as AsExpressionImpl);
     flowAnalysis.asExpression(node);
     insertGenericFunctionInstantiation(node);
   }
@@ -1207,22 +1205,36 @@
       var futureUnion = _createFutureOr(contextType);
       InferenceContext.setType(node.expression, futureUnion);
     }
-    super.visitAwaitExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitAwaitExpression(node as AwaitExpressionImpl);
     insertGenericFunctionInstantiation(node);
   }
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
+    var migrationResolutionHooks = this.migrationResolutionHooks;
+    if (migrationResolutionHooks != null) {
+      migrationResolutionHooks.reportBinaryExpressionContext(
+          node, InferenceContext.getContext(node));
+    }
     _binaryExpressionResolver.resolve(node as BinaryExpressionImpl);
     insertGenericFunctionInstantiation(node);
   }
 
   @override
+  void visitBlock(Block node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
     try {
       inferenceContext.pushFunctionBodyContext(node);
       _thisAccessTracker.enterFunctionBody(node);
-      super.visitBlockFunctionBody(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
     } finally {
       _thisAccessTracker.exitFunctionBody(node);
       inferenceContext.popFunctionBodyContext(node);
@@ -1232,7 +1244,9 @@
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
     flowAnalysis.flow?.booleanLiteral(node, node.value);
-    super.visitBooleanLiteral(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitBooleanLiteral(node as BooleanLiteralImpl);
   }
 
   @override
@@ -1242,8 +1256,6 @@
     // of the statement.
     //
     checkUnreachableNode(node);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
     flowAnalysis.breakStatement(node);
   }
 
@@ -1260,13 +1272,18 @@
 
     node.cascadeSections.accept(this);
 
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+    typeAnalyzer.visitCascadeExpression(node);
 
     nullShortingTermination(node);
   }
 
   @override
+  void visitCatchClause(CatchClause node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitClassDeclaration(ClassDeclaration node) {
     //
     // Continue the class resolution.
@@ -1274,9 +1291,9 @@
     var outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement;
-      super.visitClassDeclaration(node);
-      node.accept(elementResolver);
-      node.accept(typeAnalyzer);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitClassDeclaration(node);
     } finally {
       enclosingClass = outerType;
     }
@@ -1284,10 +1301,15 @@
 
   @override
   void visitClassTypeAlias(ClassTypeAlias node) {
-    super.visitClassTypeAlias(node);
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitClassTypeAlias.
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitClassTypeAlias(node);
+  }
+
+  @override
+  void visitComment(Comment node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
@@ -1296,8 +1318,7 @@
     // We do not visit the expression because it needs to be visited in the
     // context of the reference.
     //
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+    elementResolver.visitCommentReference(node);
   }
 
   @override
@@ -1312,8 +1333,6 @@
     for (int i = 0; i < declarationCount; i++) {
       declarations[i].accept(this);
     }
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
   }
 
   @override
@@ -1323,6 +1342,7 @@
     flow?.conditional_conditionBegin();
 
     // TODO(scheglov) Do we need these checks for null?
+    InferenceContext.setType(node.condition, typeProvider.boolType);
     condition.accept(this);
     condition = node.condition;
     var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -1352,8 +1372,7 @@
     }
     elseExpression = node.elseExpression;
 
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+    typeAnalyzer.visitConditionalExpression(node as ConditionalExpressionImpl);
   }
 
   @override
@@ -1375,7 +1394,9 @@
       _enclosingFunction = node.declaredElement;
       assert(_thisType == null);
       _setupThisType();
-      super.visitConstructorDeclaration(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitConstructorDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
       _thisType = null;
@@ -1405,8 +1426,8 @@
     expression.accept(this);
     expression = node.expression;
     var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+    elementResolver.visitConstructorFieldInitializer(
+        node as ConstructorFieldInitializerImpl);
     if (fieldElement != null) {
       if (fieldType != null && expression.staticType != null) {
         var callReference = insertImplicitCallReference(expression);
@@ -1425,7 +1446,7 @@
   @override
   void visitConstructorName(ConstructorName node) {
     node.type2.accept(this);
-    node.accept(elementResolver);
+    elementResolver.visitConstructorName(node as ConstructorNameImpl);
   }
 
   @override
@@ -1434,21 +1455,33 @@
   }
 
   @override
+  void visitConstructorSelector(ConstructorSelector node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitContinueStatement(ContinueStatement node) {
     //
     // We do not visit the label because it needs to be visited in the context
     // of the statement.
     //
     checkUnreachableNode(node);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
     flowAnalysis.continueStatement(node);
   }
 
   @override
+  void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitDeclaredIdentifier(node);
+  }
+
+  @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
     InferenceContext.setType(node.defaultValue, node.declaredElement?.type);
-    super.visitDefaultFormalParameter(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
     ParameterElement element = node.declaredElement!;
 
     if (element is DefaultParameterElementImpl && node.isOfLocalFunction) {
@@ -1477,17 +1510,69 @@
   }
 
   @override
+  void visitDoubleLiteral(DoubleLiteral node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitDoubleLiteral(node as DoubleLiteralImpl);
+  }
+
+  @override
   void visitEmptyFunctionBody(EmptyFunctionBody node) {
     if (resolveOnlyCommentInFunctionBody) {
       return;
     }
-    super.visitEmptyFunctionBody(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitEnumConstantArguments(EnumConstantArguments node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    node as EnumConstantDeclarationImpl;
+
+    node.documentationComment?.accept(this);
     node.metadata.accept(this);
-    super.visitEnumConstantDeclaration(node);
+    checkUnreachableNode(node);
+
+    var element = node.declaredElement as ConstFieldElementImpl;
+    var initializer = element.constantInitializer;
+    if (initializer is InstanceCreationExpression) {
+      var constructor = initializer.constructorName.staticElement;
+      node.constructorElement = constructor;
+      var arguments = node.arguments;
+      if (arguments != null) {
+        var argumentList = arguments.argumentList;
+        if (constructor != null) {
+          InferenceContext.setType(argumentList, constructor.type);
+          argumentList.correspondingStaticParameters =
+              ResolverVisitor.resolveArgumentsToParameters(
+            argumentList: argumentList,
+            parameters: constructor.parameters,
+          );
+          for (var argument in argumentList.arguments) {
+            var parameter = argument.staticParameterElement;
+            if (parameter != null) {
+              InferenceContext.setType(argument, parameter.type);
+            }
+            argument.accept(this);
+          }
+        }
+        arguments.typeArguments?.accept(this);
+      }
+    }
+
+    elementResolver.visitEnumConstantDeclaration(node);
   }
 
   @override
@@ -1498,15 +1583,22 @@
     var outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement;
-      super.visitEnumDeclaration(node);
-      node.accept(elementResolver);
-      node.accept(typeAnalyzer);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitEnumDeclaration(node);
     } finally {
       enclosingClass = outerType;
     }
   }
 
   @override
+  void visitExportDirective(ExportDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitExportDirective(node);
+  }
+
+  @override
   void visitExpressionFunctionBody(ExpressionFunctionBody node) {
     if (resolveOnlyCommentInFunctionBody) {
       return;
@@ -1520,7 +1612,8 @@
       );
       _thisAccessTracker.enterFunctionBody(node);
 
-      super.visitExpressionFunctionBody(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
       insertImplicitCallReference(node.expression);
 
       flowAnalysis.flow?.handleExit();
@@ -1533,13 +1626,25 @@
   }
 
   @override
+  void visitExpressionStatement(ExpressionStatement node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitExtendsClause(ExtendsClause node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitExtensionDeclaration(ExtensionDeclaration node) {
     var outerExtension = enclosingExtension;
     try {
       enclosingExtension = node.declaredElement!;
-      super.visitExtensionDeclaration(node);
-      node.accept(elementResolver);
-      node.accept(typeAnalyzer);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitExtensionDeclaration(node);
     } finally {
       enclosingExtension = outerExtension;
     }
@@ -1555,7 +1660,6 @@
     visitArgumentList(node.argumentList,
         whyNotPromotedList: whyNotPromotedList);
 
-    node.accept(elementResolver);
     extensionResolver.resolveOverride(node, whyNotPromotedList);
   }
 
@@ -1565,7 +1669,9 @@
     try {
       assert(_thisType == null);
       _setupThisType();
-      super.visitFieldDeclaration(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitFieldDeclaration(node);
     } finally {
       _thisAccessTracker.exitFieldDeclaration(node);
       _thisType = null;
@@ -1573,11 +1679,24 @@
   }
 
   @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitFieldFormalParameter(node);
+  }
+
+  @override
   void visitForElement(ForElement node) {
     _forResolver.resolveElement(node as ForElementImpl);
   }
 
   @override
+  void visitFormalParameterList(FormalParameterList node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitForStatement(ForStatement node) {
     _forResolver.resolveStatement(node as ForStatementImpl);
     nullSafetyDeadCodeVerifier.flowEnd(node.body);
@@ -1605,7 +1724,9 @@
     var outerFunction = _enclosingFunction;
     try {
       _enclosingFunction = node.declaredElement;
-      super.visitFunctionDeclaration(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitFunctionDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
     }
@@ -1626,10 +1747,12 @@
       flowAnalysis.topLevelDeclaration_exit();
     }
     nullSafetyDeadCodeVerifier.flowEnd(node);
+  }
 
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitFunctionDeclaration
+  @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
@@ -1662,26 +1785,29 @@
 
   @override
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    super.visitFunctionTypeAlias(node);
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitFunctionTypeAlias.
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitFunctionTypeAlias(node);
   }
 
   @override
   void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    super.visitFunctionTypedFormalParameter(node);
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitFunctionTypedFormalParameter.
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
-    super.visitGenericTypeAlias(node);
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitGenericTypeAlias.
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitGenericTypeAlias(node);
   }
 
   @override
@@ -1711,9 +1837,6 @@
     }
 
     flowAnalysis.flow?.ifStatement_end(elseElement != null);
-
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
   }
 
   @override
@@ -1743,9 +1866,25 @@
     }
 
     flowAnalysis.flow?.ifStatement_end(elseStatement != null);
+  }
 
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+  @override
+  void visitImplementsClause(ImplementsClause node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitImportDirective(node as ImportDirectiveImpl);
   }
 
   @override
@@ -1793,8 +1932,29 @@
   }
 
   @override
+  void visitIntegerLiteral(IntegerLiteral node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitIntegerLiteral(node);
+  }
+
+  @override
+  void visitInterpolationExpression(InterpolationExpression node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitInterpolationString(InterpolationString node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitIsExpression(IsExpression node) {
-    super.visitIsExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitIsExpression(node as IsExpressionImpl);
     flowAnalysis.isExpression(node);
   }
 
@@ -1804,11 +1964,19 @@
   @override
   void visitLabeledStatement(LabeledStatement node) {
     flowAnalysis.labeledStatement_enter(node);
-    super.visitLabeledStatement(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
     flowAnalysis.labeledStatement_exit(node);
   }
 
   @override
+  void visitLibraryDirective(LibraryDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitLibraryDirective(node);
+  }
+
+  @override
   void visitLibraryIdentifier(LibraryIdentifier node) {}
 
   @override
@@ -1818,6 +1986,12 @@
   }
 
   @override
+  void visitMapLiteralEntry(MapLiteralEntry node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     flowAnalysis.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
@@ -1830,7 +2004,9 @@
       _enclosingFunction = node.declaredElement;
       assert(_thisType == null);
       _setupThisType();
-      super.visitMethodDeclaration(node);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitMethodDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
       _thisType = null;
@@ -1845,10 +2021,6 @@
     flowAnalysis.executableDeclaration_exit(node.body, false);
     flowAnalysis.topLevelDeclaration_exit();
     nullSafetyDeadCodeVerifier.flowEnd(node);
-
-    node.accept(elementResolver);
-    // Note: no need to call the typeAnalyzer since it does not override
-    // visitMethodDeclaration.
   }
 
   @override
@@ -1897,9 +2069,9 @@
     var outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement!;
-      super.visitMixinDeclaration(node);
-      node.accept(elementResolver);
-      node.accept(typeAnalyzer);
+      checkUnreachableNode(node);
+      node.visitChildren(this);
+      elementResolver.visitMixinDeclaration(node);
     } finally {
       enclosingClass = outerType;
     }
@@ -1908,7 +2080,9 @@
   @override
   void visitNamedExpression(NamedExpression node) {
     InferenceContext.setTypeFromNode(node.expression, node);
-    super.visitNamedExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitNamedExpression(node as NamedExpressionImpl);
     // Any "why not promoted" information that flow analysis had associated with
     // `node.expression` now needs to be forwarded to `node`, so that when
     // `visitArgumentList` iterates through the arguments, it will find it.
@@ -1925,27 +2099,56 @@
   }
 
   @override
-  void visitNode(AstNode node) {
+  void visitNativeClause(NativeClause node) {
     checkUnreachableNode(node);
     node.visitChildren(this);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+  }
+
+  @override
+  void visitNativeFunctionBody(NativeFunctionBody node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
   void visitNullLiteral(NullLiteral node) {
     flowAnalysis.flow?.nullLiteral(node);
-    super.visitNullLiteral(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitNullLiteral(node as NullLiteralImpl);
+  }
+
+  @override
+  void visitOnClause(OnClause node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
     InferenceContext.setTypeFromNode(node.expression, node);
-    super.visitParenthesizedExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer
+        .visitParenthesizedExpression(node as ParenthesizedExpressionImpl);
     flowAnalysis.flow?.parenthesizedExpression(node, node.expression);
   }
 
   @override
+  void visitPartDirective(PartDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitPartDirective(node);
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitPartOfDirective(node);
+  }
+
+  @override
   void visitPostfixExpression(PostfixExpression node) {
     _postfixExpressionResolver.resolve(node as PostfixExpressionImpl);
     insertGenericFunctionInstantiation(node);
@@ -2016,18 +2219,20 @@
     // invocation.
     //
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
-    node.accept(elementResolver);
+    elementResolver.visitRedirectingConstructorInvocation(
+        node as RedirectingConstructorInvocationImpl);
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
     visitArgumentList(node.argumentList,
         whyNotPromotedList: whyNotPromotedList);
-    node.accept(typeAnalyzer);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
 
   @override
   void visitRethrowExpression(RethrowExpression node) {
-    super.visitRethrowExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitRethrowExpression(node as RethrowExpressionImpl);
     flowAnalysis.flow?.handleExit();
   }
 
@@ -2038,7 +2243,8 @@
       inferenceContext.bodyContext?.contextType,
     );
 
-    super.visitReturnStatement(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
 
     inferenceContext.bodyContext?.addReturnExpression(node.expression);
     flowAnalysis.flow?.handleExit();
@@ -2059,14 +2265,29 @@
   void visitShowCombinator(ShowCombinator node) {}
 
   @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitSimpleFormalParameter(node);
+  }
+
+  @override
   void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
     _simpleIdentifierResolver.resolve(node);
     insertGenericFunctionInstantiation(node);
   }
 
   @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitSimpleStringLiteral(node as SimpleStringLiteralImpl);
+  }
+
+  @override
   void visitSpreadElement(SpreadElement node) {
-    super.visitSpreadElement(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
 
     if (!node.isNullAware) {
       nullableDereferenceVerifier.expression(
@@ -2077,6 +2298,13 @@
   }
 
   @override
+  void visitStringInterpolation(StringInterpolation node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitStringInterpolation(node as StringInterpolationImpl);
+  }
+
+  @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     //
     // We visit the argument list, but do not visit the optional identifier
@@ -2084,22 +2312,37 @@
     // invocation.
     //
     var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
-    node.accept(elementResolver);
+    elementResolver.visitSuperConstructorInvocation(
+        node as SuperConstructorInvocationImpl);
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
     visitArgumentList(node.argumentList,
         whyNotPromotedList: whyNotPromotedList);
-    node.accept(typeAnalyzer);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
 
   @override
+  void visitSuperExpression(SuperExpression node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitSuperExpression(node);
+    typeAnalyzer.visitSuperExpression(node as SuperExpressionImpl);
+  }
+
+  @override
+  void visitSuperFormalParameter(SuperFormalParameter node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitSwitchCase(SwitchCase node) {
     checkUnreachableNode(node);
 
     InferenceContext.setType(
         node.expression, _enclosingSwitchStatementExpressionType);
-    super.visitSwitchCase(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
 
     var flow = flowAnalysis.flow;
     if (flow != null && flow.isReachable && _isNonNullableByDefault) {
@@ -2117,7 +2360,8 @@
 
   @override
   void visitSwitchDefault(SwitchDefault node) {
-    super.visitSwitchDefault(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
     nullSafetyDeadCodeVerifier.flowEnd(node);
   }
 
@@ -2156,12 +2400,35 @@
   }
 
   @override
+  void visitSymbolLiteral(SymbolLiteral node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitSymbolLiteral(node as SymbolLiteralImpl);
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitThisExpression(node as ThisExpressionImpl);
+  }
+
+  @override
   void visitThrowExpression(ThrowExpression node) {
-    super.visitThrowExpression(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    typeAnalyzer.visitThrowExpression(node as ThrowExpressionImpl);
     flowAnalysis.flow?.handleExit();
   }
 
   @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitTopLevelVariableDeclaration(node);
+  }
+
+  @override
   void visitTryStatement(TryStatement node) {
     checkUnreachableNode(node);
     var flow = flowAnalysis.flow!;
@@ -2209,6 +2476,31 @@
   }
 
   @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitTypeLiteral(TypeLiteral node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitTypeParameter(node);
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitVariableDeclaration(VariableDeclaration node) {
     _variableDeclarationResolver.resolve(node as VariableDeclarationImpl);
 
@@ -2234,7 +2526,15 @@
       VariableElement variableElement = decl.declaredElement!;
       InferenceContext.setType(decl, variableElement.type);
     }
-    super.visitVariableDeclarationList(node);
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitVariableDeclarationList(node);
+  }
+
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
@@ -2258,8 +2558,12 @@
     nullSafetyDeadCodeVerifier.flowEnd(node.body);
     // TODO(brianwilkerson) If the loop can only be exited because the condition
     // is false, then propagateFalseState(condition);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+  }
+
+  @override
+  void visitWithClause(WithClause node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
   }
 
   @override
@@ -2324,21 +2628,14 @@
   /// will be invoked using those arguments, compute the list of parameters that
   /// correspond to the list of arguments.
   ///
-  /// An error will be reported to [onError] if any of the arguments cannot be
-  /// matched to a parameter. onError will be provided the node of the first
-  /// argument that is not matched. onError can be null to ignore the error.
-  ///
   /// Returns the parameters that correspond to the arguments. If no parameter
   /// matched an argument, that position will be `null` in the list.
-  static List<ParameterElement?> resolveArgumentsToParameters(
-      ArgumentList argumentList,
-      List<ParameterElement> parameters,
-      void Function(ErrorCode errorCode, AstNode node,
-              [List<Object> arguments])?
-          onError) {
-    if (parameters.isEmpty && argumentList.arguments.isEmpty) {
-      return const <ParameterElement>[];
-    }
+  static List<ParameterElement?> resolveArgumentsToParameters({
+    required ArgumentList argumentList,
+    required List<ParameterElement> parameters,
+    ErrorReporter? errorReporter,
+    ConstructorDeclaration? enclosingConstructor,
+  }) {
     int requiredParameterCount = 0;
     int unnamedParameterCount = 0;
     List<ParameterElement> unnamedParameters = <ParameterElement>[];
@@ -2364,32 +2661,11 @@
     List<ParameterElement?> resolvedParameters =
         List<ParameterElement?>.filled(argumentCount, null);
     int positionalArgumentCount = 0;
-    HashSet<String>? usedNames;
     bool noBlankArguments = true;
     Expression? firstUnresolvedArgument;
     for (int i = 0; i < argumentCount; i++) {
       Expression argument = arguments[i];
-      if (argument is NamedExpressionImpl) {
-        var nameNode = argument.name.label;
-        String name = nameNode.name;
-        var element = namedParameters != null ? namedParameters[name] : null;
-        if (element == null) {
-          if (onError != null) {
-            onError(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, nameNode,
-                [name]);
-          }
-        } else {
-          resolvedParameters[i] = element;
-          nameNode.staticElement = element;
-        }
-        usedNames ??= HashSet<String>();
-        if (!usedNames.add(name)) {
-          if (onError != null) {
-            onError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode,
-                [name]);
-          }
-        }
-      } else {
+      if (argument is! NamedExpressionImpl) {
         if (argument is SimpleIdentifier && argument.name.isEmpty) {
           noBlankArguments = false;
         }
@@ -2401,11 +2677,46 @@
         }
       }
     }
-    if (positionalArgumentCount < requiredParameterCount && noBlankArguments) {
-      if (onError != null) {
-        onError(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
-            argumentList, [requiredParameterCount, positionalArgumentCount]);
+
+    Set<String>? usedNames;
+    if (enclosingConstructor != null) {
+      var result = verifySuperFormalParameters(
+        constructor: enclosingConstructor,
+        hasExplicitPositionalArguments: positionalArgumentCount != 0,
+        errorReporter: errorReporter,
+      );
+      positionalArgumentCount += result.positionalArgumentCount;
+      if (result.namedArgumentNames.isNotEmpty) {
+        usedNames = result.namedArgumentNames.toSet();
       }
+    }
+
+    for (int i = 0; i < argumentCount; i++) {
+      Expression argument = arguments[i];
+      if (argument is NamedExpressionImpl) {
+        var nameNode = argument.name.label;
+        String name = nameNode.name;
+        var element = namedParameters != null ? namedParameters[name] : null;
+        if (element == null) {
+          errorReporter?.reportErrorForNode(
+              CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, nameNode, [name]);
+        } else {
+          resolvedParameters[i] = element;
+          nameNode.staticElement = element;
+        }
+        usedNames ??= <String>{};
+        if (!usedNames.add(name)) {
+          errorReporter?.reportErrorForNode(
+              CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]);
+        }
+      }
+    }
+
+    if (positionalArgumentCount < requiredParameterCount && noBlankArguments) {
+      errorReporter?.reportErrorForNode(
+          CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+          argumentList,
+          [requiredParameterCount, positionalArgumentCount]);
     } else if (positionalArgumentCount > unnamedParameterCount &&
         noBlankArguments) {
       ErrorCode errorCode;
@@ -2417,8 +2728,8 @@
       } else {
         errorCode = CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS;
       }
-      if (onError != null) {
-        onError(errorCode, firstUnresolvedArgument!,
+      if (firstUnresolvedArgument != null) {
+        errorReporter?.reportErrorForNode(errorCode, firstUnresolvedArgument,
             [unnamedParameterCount, positionalArgumentCount]);
       }
     }
@@ -2446,7 +2757,7 @@
             definingLibrary,
             source,
             typeSystem,
-            typeProvider,
+            typeProvider as TypeProviderImpl,
             errorListener,
             featureSet,
             FlowAnalysisHelperForMigration(
@@ -2465,7 +2776,7 @@
       var subexpressionToKeep =
           conditionalKnownValue ? node.thenExpression : node.elseExpression;
       subexpressionToKeep.accept(this);
-      typeAnalyzer.recordStaticType(node, subexpressionToKeep.typeOrThrow);
+      inferenceHelper.recordStaticType(node, subexpressionToKeep.typeOrThrow);
     }
   }
 
@@ -2501,9 +2812,22 @@
 ///
 /// TODO(paulberry): migrate the responsibility for all scope resolution into
 /// this visitor.
-class ScopeResolverVisitor extends ResolverBase {
+class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
   static const _nameScopeProperty = 'nameScope';
 
+  /// The element for the library containing the compilation unit being visited.
+  final LibraryElementImpl definingLibrary;
+
+  /// The source representing the compilation unit being visited.
+  final Source source;
+
+  /// The object used to access the types from the core library.
+  final TypeProviderImpl typeProvider;
+
+  /// The error reporter that will be informed of any errors that are found
+  /// during resolution.
+  final ErrorReporter errorReporter;
+
   /// The scope used to resolve identifiers.
   Scope nameScope;
 
@@ -2535,12 +2859,15 @@
   /// [nameScope] is the scope used to resolve identifiers in the node that will
   /// first be visited.  If `null` or unspecified, a new [LibraryScope] will be
   /// created based on [definingLibrary] and [typeProvider].
-  ScopeResolverVisitor(LibraryElementImpl definingLibrary, Source source,
-      TypeProvider typeProvider, AnalysisErrorListener errorListener,
+  ScopeResolverVisitor(this.definingLibrary, this.source, this.typeProvider,
+      AnalysisErrorListener errorListener,
       {Scope? nameScope})
-      : nameScope = nameScope ?? LibraryScope(definingLibrary),
-        super(definingLibrary, source, typeProvider as TypeProviderImpl,
-            errorListener);
+      : errorReporter = ErrorReporter(
+          errorListener,
+          source,
+          isNonNullableByDefault: definingLibrary.isNonNullableByDefault,
+        ),
+        nameScope = nameScope ?? LibraryScope(definingLibrary);
 
   /// Return the implicit label scope in which the current node is being
   /// resolved.
@@ -2742,6 +3069,7 @@
   void visitEnumMembersInScope(EnumDeclaration node) {
     node.documentationComment?.accept(this);
     node.constants.accept(this);
+    node.members.accept(this);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index bcd3487..6bd3016 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -3,14 +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/visitor.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/generated/migration.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
 /// Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they
@@ -20,11 +19,11 @@
 /// * Every element that refers to types should be fully populated.
 /// * Every node representing an expression should be resolved to the Type of the expression.
 /// </ol>
-class StaticTypeAnalyzer extends SimpleAstVisitor<void> {
+class StaticTypeAnalyzer {
   /// The resolver driving the resolution and type analysis.
   final ResolverVisitor _resolver;
 
-  final MigrationResolutionHooks? _migrationResolutionHooks;
+  final InvocationInferenceHelper _inferenceHelper;
 
   /// The object providing access to the types defined by the language.
   late TypeProviderImpl _typeProvider;
@@ -39,35 +38,17 @@
   /// [_resolver] based on the
   ///
   /// @param resolver the resolver driving this participant
-  StaticTypeAnalyzer(this._resolver, this._migrationResolutionHooks) {
+  StaticTypeAnalyzer(this._resolver)
+      : _inferenceHelper = _resolver.inferenceHelper {
     _typeProvider = _resolver.typeProvider;
     _typeSystem = _resolver.typeSystem;
     _dynamicType = _typeProvider.dynamicType;
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplication
-  void recordStaticType(ExpressionImpl expression, DartType type) {
-    var hooks = _migrationResolutionHooks;
-    if (hooks != null) {
-      type = hooks.modifyExpressionType(expression, type);
-    }
-
-    expression.staticType = type;
-    if (_typeSystem.isBottom(type)) {
-      _resolver.flowAnalysis.flow?.handleExit();
-    }
-  }
-
   /// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
   /// `String`.</blockquote>
-  @override
   void visitAdjacentStrings(covariant AdjacentStringsImpl node) {
-    recordStaticType(node, _typeProvider.stringType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
   }
 
   /// The Dart Language Specification, 12.32: <blockquote>... the cast expression <i>e as T</i> ...
@@ -76,35 +57,31 @@
   /// scope.
   ///
   /// The static type of a cast expression <i>e as T</i> is <i>T</i>.</blockquote>
-  @override
   void visitAsExpression(covariant AsExpressionImpl node) {
-    recordStaticType(node, _getType(node.type));
+    _inferenceHelper.recordStaticType(node, _getType(node.type));
   }
 
   /// The Dart Language Specification, 16.29 (Await Expressions):
   ///
   ///   The static type of [the expression "await e"] is flatten(T) where T is
   ///   the static type of e.
-  @override
   void visitAwaitExpression(covariant AwaitExpressionImpl node) {
     var resultType = node.expression.typeOrThrow;
     resultType = _typeSystem.flatten(resultType);
-    recordStaticType(node, resultType);
+    _inferenceHelper.recordStaticType(node, resultType);
   }
 
   /// The Dart Language Specification, 12.4: <blockquote>The static type of a boolean literal is
   /// bool.</blockquote>
-  @override
   void visitBooleanLiteral(covariant BooleanLiteralImpl node) {
-    recordStaticType(node, _typeProvider.boolType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
   }
 
   /// The Dart Language Specification, 12.15.2: <blockquote>A cascaded method invocation expression
   /// of the form <i>e..suffix</i> is equivalent to the expression <i>(t) {t.suffix; return
   /// t;}(e)</i>.</blockquote>
-  @override
   void visitCascadeExpression(covariant CascadeExpressionImpl node) {
-    recordStaticType(node, node.target.typeOrThrow);
+    _inferenceHelper.recordStaticType(node, node.target.typeOrThrow);
   }
 
   /// The Dart Language Specification, 12.19: <blockquote> ... a conditional expression <i>c</i> of
@@ -114,19 +91,16 @@
   ///
   /// The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
   /// and the static type of <i>e<sub>3</sub></i>.</blockquote>
-  @override
   void visitConditionalExpression(covariant ConditionalExpressionImpl node) {
     _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression);
   }
 
   /// The Dart Language Specification, 12.3: <blockquote>The static type of a literal double is
   /// double.</blockquote>
-  @override
   void visitDoubleLiteral(covariant DoubleLiteralImpl node) {
-    recordStaticType(node, _typeProvider.doubleType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.doubleType);
   }
 
-  @override
   void visitExtensionOverride(ExtensionOverride node) {
     assert(false,
         'Resolver should call extensionResolver.resolveOverride directly');
@@ -160,10 +134,8 @@
   /// x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>}) &rarr; dynamic</i>. In any case
   /// where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is considered to have been
   /// specified as dynamic.</blockquote>
-  @override
   void visitFunctionExpression(FunctionExpression node) {}
 
-  @override
   void visitFunctionReference(covariant FunctionReferenceImpl node) {
     // TODO(paulberry): implement
     node.staticType = _dynamicType;
@@ -176,11 +148,11 @@
   /// The Dart Language Specification, 12.11.2: <blockquote>The static type of a constant object
   /// expression of either the form <i>const T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the
   /// form <i>const T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>. </blockquote>
-  @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
     _inferInstanceCreationExpression(node);
-    recordStaticType(node, node.constructorName.type2.typeOrThrow);
+    _inferenceHelper.recordStaticType(
+        node, node.constructorName.type2.typeOrThrow);
   }
 
   /// <blockquote>
@@ -198,7 +170,6 @@
   /// type of $e$ is the same as the static type of an integer literal with the
   /// same contexttype
   /// </blockquote>
-  @override
   void visitIntegerLiteral(IntegerLiteral node) {
     // Check the parent context for negated integer literals.
     var context = InferenceContext.getContext(
@@ -206,9 +177,9 @@
     if (context == null ||
         _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
         !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
-      recordStaticType(node, _typeProvider.intType);
+      _inferenceHelper.recordStaticType(node, _typeProvider.intType);
     } else {
-      recordStaticType(node, _typeProvider.doubleType);
+      _inferenceHelper.recordStaticType(node, _typeProvider.doubleType);
     }
   }
 
@@ -216,58 +187,49 @@
   /// denote a type available in the current lexical scope.
   ///
   /// The static type of an is-expression is `bool`.</blockquote>
-  @override
   void visitIsExpression(covariant IsExpressionImpl node) {
-    recordStaticType(node, _typeProvider.boolType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
   }
 
-  @override
   void visitMethodInvocation(MethodInvocation node) {
     throw StateError('Should not be invoked');
   }
 
-  @override
   void visitNamedExpression(covariant NamedExpressionImpl node) {
     Expression expression = node.expression;
-    recordStaticType(node, expression.typeOrThrow);
+    _inferenceHelper.recordStaticType(node, expression.typeOrThrow);
   }
 
   /// The Dart Language Specification, 12.2: <blockquote>The static type of `null` is bottom.
   /// </blockquote>
-  @override
   void visitNullLiteral(covariant NullLiteralImpl node) {
-    recordStaticType(node, _typeProvider.nullType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.nullType);
   }
 
-  @override
   void visitParenthesizedExpression(
       covariant ParenthesizedExpressionImpl node) {
     Expression expression = node.expression;
-    recordStaticType(node, expression.typeOrThrow);
+    _inferenceHelper.recordStaticType(node, expression.typeOrThrow);
   }
 
   /// The Dart Language Specification, 12.9: <blockquote>The static type of a rethrow expression is
   /// bottom.</blockquote>
-  @override
   void visitRethrowExpression(covariant RethrowExpressionImpl node) {
-    recordStaticType(node, _typeProvider.bottomType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.bottomType);
   }
 
   /// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
   /// `String`.</blockquote>
-  @override
   void visitSimpleStringLiteral(covariant SimpleStringLiteralImpl node) {
-    recordStaticType(node, _typeProvider.stringType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
   }
 
   /// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
   /// `String`.</blockquote>
-  @override
   void visitStringInterpolation(covariant StringInterpolationImpl node) {
-    recordStaticType(node, _typeProvider.stringType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.stringType);
   }
 
-  @override
   void visitSuperExpression(covariant SuperExpressionImpl node) {
     var thisType = _resolver.thisType;
     _resolver.flowAnalysis.flow?.thisOrSuper(node, thisType ?? _dynamicType);
@@ -275,37 +237,34 @@
         node.thisOrAncestorOfType<ExtensionDeclaration>() != null) {
       // TODO(brianwilkerson) Report this error if it hasn't already been
       // reported.
-      recordStaticType(node, _dynamicType);
+      _inferenceHelper.recordStaticType(node, _dynamicType);
     } else {
-      recordStaticType(node, thisType);
+      _inferenceHelper.recordStaticType(node, thisType);
     }
   }
 
-  @override
   void visitSymbolLiteral(covariant SymbolLiteralImpl node) {
-    recordStaticType(node, _typeProvider.symbolType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.symbolType);
   }
 
   /// The Dart Language Specification, 12.10: <blockquote>The static type of `this` is the
   /// interface of the immediately enclosing class.</blockquote>
-  @override
   void visitThisExpression(covariant ThisExpressionImpl node) {
     var thisType = _resolver.thisType;
     _resolver.flowAnalysis.flow?.thisOrSuper(node, thisType ?? _dynamicType);
     if (thisType == null) {
       // TODO(brianwilkerson) Report this error if it hasn't already been
       // reported.
-      recordStaticType(node, _dynamicType);
+      _inferenceHelper.recordStaticType(node, _dynamicType);
     } else {
-      recordStaticType(node, thisType);
+      _inferenceHelper.recordStaticType(node, thisType);
     }
   }
 
   /// The Dart Language Specification, 12.8: <blockquote>The static type of a throw expression is
   /// bottom.</blockquote>
-  @override
   void visitThrowExpression(covariant ThrowExpressionImpl node) {
-    recordStaticType(node, _typeProvider.bottomType);
+    _inferenceHelper.recordStaticType(node, _typeProvider.bottomType);
   }
 
   /// Set the static type of [node] to be the least upper bound of the static
@@ -327,7 +286,7 @@
 
     staticType = _resolver.toLegacyTypeIfOptOut(staticType);
 
-    recordStaticType(node, staticType);
+    _inferenceHelper.recordStaticType(node, staticType);
   }
 
   /// Return the type represented by the given type [annotation].
@@ -378,7 +337,9 @@
       // Fix up the parameter elements based on inferred method.
       arguments.correspondingStaticParameters =
           ResolverVisitor.resolveArgumentsToParameters(
-              arguments, inferred.parameters, null);
+        argumentList: arguments,
+        parameters: inferred.parameters,
+      );
       typeName.type = inferred.returnType;
       // Update the static element as well. This is used in some cases, such as
       // computing constant values. It is stored in two places.
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index 59758e4..c3c0036 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/generated/java_core.dart';
-
 /// Returns `true` if a and b contain equal elements in the same order.
 bool listsEqual(List a, List b) {
   // TODO(rnystrom): package:collection also implements this, and analyzer
@@ -34,11 +32,6 @@
     return (array & (1 << index)) > 0;
   }
 
-  /// Return the value of the element at the given index.
-  @deprecated
-  static bool getEnum<E extends Enum<E>>(int array, Enum<E> index) =>
-      get(array, index.ordinal);
-
   /// Set the value of the element of the given [array] at the given [index] to
   /// the given [value].
   static int set(int array, int index, bool value) {
@@ -50,11 +43,6 @@
     }
   }
 
-  /// Set the value of the element at the given index to the given value.
-  @deprecated
-  static int setEnum<E extends Enum<E>>(int array, Enum<E> index, bool value) =>
-      set(array, index.ordinal, value);
-
   /// Throw an exception if the index is not within the bounds allowed for an
   /// integer-encoded array of boolean values.
   static void _checkIndex(int index) {
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 8b32896..542e9ec 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -375,8 +375,6 @@
     );
 
     computeConstants(
-      typeProvider,
-      typeSystem,
       declaredVariables,
       dependencies,
       libraryElement.featureSet,
@@ -483,8 +481,6 @@
     var dependenciesFinder = ConstantExpressionsDependenciesFinder();
     node.accept(dependenciesFinder);
     computeConstants(
-      typeProvider,
-      typeSystem,
       declaredVariables,
       dependenciesFinder.dependencies.toList(),
       libraryElement.featureSet,
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index 692f0c7..b08cc00 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -653,6 +653,12 @@
   }
 
   @override
+  void visitSuperFormalParameter(SuperFormalParameter node) {
+    _runSubscriptions(node, registry._forSuperFormalParameter);
+    super.visitSuperFormalParameter(node);
+  }
+
+  @override
   void visitSwitchCase(SwitchCase node) {
     _runSubscriptions(node, registry._forSwitchCase);
     super.visitSwitchCase(node);
@@ -897,6 +903,7 @@
   final List<_Subscription<SuperConstructorInvocation>>
       _forSuperConstructorInvocation = [];
   final List<_Subscription<SuperExpression>> _forSuperExpression = [];
+  final List<_Subscription<SuperFormalParameter>> _forSuperFormalParameter = [];
   final List<_Subscription<SwitchCase>> _forSwitchCase = [];
   final List<_Subscription<SwitchDefault>> _forSwitchDefault = [];
   final List<_Subscription<SwitchStatement>> _forSwitchStatement = [];
@@ -1386,6 +1393,11 @@
     _forSuperExpression.add(_Subscription(linter, visitor, _getTimer(linter)));
   }
 
+  void addSuperFormalParameter(LintRule linter, AstVisitor visitor) {
+    _forSuperFormalParameter
+        .add(_Subscription(linter, visitor, _getTimer(linter)));
+  }
+
   void addSwitchCase(LintRule linter, AstVisitor visitor) {
     _forSwitchCase.add(_Subscription(linter, visitor, _getTimer(linter)));
   }
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index 49a7400..80ba07c 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -467,20 +467,20 @@
     _currentVTable!.addField(field, _tail);
   }
 
-  static void _setFloat64AtTail(ByteData _buf, int tail, double x) {
-    _buf.setFloat64(_buf.lengthInBytes - tail, x, Endian.little);
+  static void _setFloat64AtTail(ByteData buf, int tail, double x) {
+    buf.setFloat64(buf.lengthInBytes - tail, x, Endian.little);
   }
 
-  static void _setInt32AtTail(ByteData _buf, int tail, int x) {
-    _buf.setInt32(_buf.lengthInBytes - tail, x, Endian.little);
+  static void _setInt32AtTail(ByteData buf, int tail, int x) {
+    buf.setInt32(buf.lengthInBytes - tail, x, Endian.little);
   }
 
-  static void _setUint32AtTail(ByteData _buf, int tail, int x) {
-    _buf.setUint32(_buf.lengthInBytes - tail, x, Endian.little);
+  static void _setUint32AtTail(ByteData buf, int tail, int x) {
+    buf.setUint32(buf.lengthInBytes - tail, x, Endian.little);
   }
 
-  static void _setUint8AtTail(ByteData _buf, int tail, int x) {
-    _buf.setUint8(_buf.lengthInBytes - tail, x);
+  static void _setUint8AtTail(ByteData buf, int tail, int x) {
+    buf.setUint8(buf.lengthInBytes - tail, x);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index e85a569..fcbf6a9 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -241,24 +241,24 @@
     implements idl.AnalysisDriverExceptionContext {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_exception = exception;
     if (local_exception != '') {
-      _result["exception"] = local_exception;
+      result["exception"] = local_exception;
     }
     var local_files = files;
     if (local_files.isNotEmpty) {
-      _result["files"] = local_files.map((_value) => _value.toJson()).toList();
+      result["files"] = local_files.map((value) => value.toJson()).toList();
     }
     var local_path = path;
     if (local_path != '') {
-      _result["path"] = local_path;
+      result["path"] = local_path;
     }
     var local_stackTrace = stackTrace;
     if (local_stackTrace != '') {
-      _result["stackTrace"] = local_stackTrace;
+      result["stackTrace"] = local_stackTrace;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -367,16 +367,16 @@
     implements idl.AnalysisDriverExceptionFile {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_content = content;
     if (local_content != '') {
-      _result["content"] = local_content;
+      result["content"] = local_content;
     }
     var local_path = path;
     if (local_path != '') {
-      _result["path"] = local_path;
+      result["path"] = local_path;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -512,17 +512,16 @@
     implements idl.AnalysisDriverResolvedUnit {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_errors = errors;
     if (local_errors.isNotEmpty) {
-      _result["errors"] =
-          local_errors.map((_value) => _value.toJson()).toList();
+      result["errors"] = local_errors.map((value) => value.toJson()).toList();
     }
     var local_index = index;
     if (local_index != null) {
-      _result["index"] = local_index.toJson();
+      result["index"] = local_index.toJson();
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -634,16 +633,16 @@
     implements idl.AnalysisDriverSubtype {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_members = members;
     if (local_members.isNotEmpty) {
-      _result["members"] = local_members;
+      result["members"] = local_members;
     }
     var local_name = name;
     if (local_name != 0) {
-      _result["name"] = local_name;
+      result["name"] = local_name;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -859,33 +858,33 @@
     implements idl.AnalysisDriverUnitError {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_contextMessages = contextMessages;
     if (local_contextMessages.isNotEmpty) {
-      _result["contextMessages"] =
-          local_contextMessages.map((_value) => _value.toJson()).toList();
+      result["contextMessages"] =
+          local_contextMessages.map((value) => value.toJson()).toList();
     }
     var local_correction = correction;
     if (local_correction != '') {
-      _result["correction"] = local_correction;
+      result["correction"] = local_correction;
     }
     var local_length = length;
     if (local_length != 0) {
-      _result["length"] = local_length;
+      result["length"] = local_length;
     }
     var local_message = message;
     if (local_message != '') {
-      _result["message"] = local_message;
+      result["message"] = local_message;
     }
     var local_offset = offset;
     if (local_offset != 0) {
-      _result["offset"] = local_offset;
+      result["offset"] = local_offset;
     }
     var local_uniqueName = uniqueName;
     if (local_uniqueName != '') {
-      _result["uniqueName"] = local_uniqueName;
+      result["uniqueName"] = local_uniqueName;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -1711,96 +1710,95 @@
     implements idl.AnalysisDriverUnitIndex {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_elementKinds = elementKinds;
     if (local_elementKinds.isNotEmpty) {
-      _result["elementKinds"] = local_elementKinds
-          .map((_value) => _value.toString().split('.')[1])
+      result["elementKinds"] = local_elementKinds
+          .map((value) => value.toString().split('.')[1])
           .toList();
     }
     var local_elementNameClassMemberIds = elementNameClassMemberIds;
     if (local_elementNameClassMemberIds.isNotEmpty) {
-      _result["elementNameClassMemberIds"] = local_elementNameClassMemberIds;
+      result["elementNameClassMemberIds"] = local_elementNameClassMemberIds;
     }
     var local_elementNameParameterIds = elementNameParameterIds;
     if (local_elementNameParameterIds.isNotEmpty) {
-      _result["elementNameParameterIds"] = local_elementNameParameterIds;
+      result["elementNameParameterIds"] = local_elementNameParameterIds;
     }
     var local_elementNameUnitMemberIds = elementNameUnitMemberIds;
     if (local_elementNameUnitMemberIds.isNotEmpty) {
-      _result["elementNameUnitMemberIds"] = local_elementNameUnitMemberIds;
+      result["elementNameUnitMemberIds"] = local_elementNameUnitMemberIds;
     }
     var local_elementUnits = elementUnits;
     if (local_elementUnits.isNotEmpty) {
-      _result["elementUnits"] = local_elementUnits;
+      result["elementUnits"] = local_elementUnits;
     }
     var local_nullStringId = nullStringId;
     if (local_nullStringId != 0) {
-      _result["nullStringId"] = local_nullStringId;
+      result["nullStringId"] = local_nullStringId;
     }
     var local_strings = strings;
     if (local_strings.isNotEmpty) {
-      _result["strings"] = local_strings;
+      result["strings"] = local_strings;
     }
     var local_subtypes = subtypes;
     if (local_subtypes.isNotEmpty) {
-      _result["subtypes"] =
-          local_subtypes.map((_value) => _value.toJson()).toList();
+      result["subtypes"] =
+          local_subtypes.map((value) => value.toJson()).toList();
     }
     var local_supertypes = supertypes;
     if (local_supertypes.isNotEmpty) {
-      _result["supertypes"] = local_supertypes;
+      result["supertypes"] = local_supertypes;
     }
     var local_unitLibraryUris = unitLibraryUris;
     if (local_unitLibraryUris.isNotEmpty) {
-      _result["unitLibraryUris"] = local_unitLibraryUris;
+      result["unitLibraryUris"] = local_unitLibraryUris;
     }
     var local_unitUnitUris = unitUnitUris;
     if (local_unitUnitUris.isNotEmpty) {
-      _result["unitUnitUris"] = local_unitUnitUris;
+      result["unitUnitUris"] = local_unitUnitUris;
     }
     var local_usedElementIsQualifiedFlags = usedElementIsQualifiedFlags;
     if (local_usedElementIsQualifiedFlags.isNotEmpty) {
-      _result["usedElementIsQualifiedFlags"] =
-          local_usedElementIsQualifiedFlags;
+      result["usedElementIsQualifiedFlags"] = local_usedElementIsQualifiedFlags;
     }
     var local_usedElementKinds = usedElementKinds;
     if (local_usedElementKinds.isNotEmpty) {
-      _result["usedElementKinds"] = local_usedElementKinds
-          .map((_value) => _value.toString().split('.')[1])
+      result["usedElementKinds"] = local_usedElementKinds
+          .map((value) => value.toString().split('.')[1])
           .toList();
     }
     var local_usedElementLengths = usedElementLengths;
     if (local_usedElementLengths.isNotEmpty) {
-      _result["usedElementLengths"] = local_usedElementLengths;
+      result["usedElementLengths"] = local_usedElementLengths;
     }
     var local_usedElementOffsets = usedElementOffsets;
     if (local_usedElementOffsets.isNotEmpty) {
-      _result["usedElementOffsets"] = local_usedElementOffsets;
+      result["usedElementOffsets"] = local_usedElementOffsets;
     }
     var local_usedElements = usedElements;
     if (local_usedElements.isNotEmpty) {
-      _result["usedElements"] = local_usedElements;
+      result["usedElements"] = local_usedElements;
     }
     var local_usedNameIsQualifiedFlags = usedNameIsQualifiedFlags;
     if (local_usedNameIsQualifiedFlags.isNotEmpty) {
-      _result["usedNameIsQualifiedFlags"] = local_usedNameIsQualifiedFlags;
+      result["usedNameIsQualifiedFlags"] = local_usedNameIsQualifiedFlags;
     }
     var local_usedNameKinds = usedNameKinds;
     if (local_usedNameKinds.isNotEmpty) {
-      _result["usedNameKinds"] = local_usedNameKinds
-          .map((_value) => _value.toString().split('.')[1])
+      result["usedNameKinds"] = local_usedNameKinds
+          .map((value) => value.toString().split('.')[1])
           .toList();
     }
     var local_usedNameOffsets = usedNameOffsets;
     if (local_usedNameOffsets.isNotEmpty) {
-      _result["usedNameOffsets"] = local_usedNameOffsets;
+      result["usedNameOffsets"] = local_usedNameOffsets;
     }
     var local_usedNames = usedNames;
     if (local_usedNames.isNotEmpty) {
-      _result["usedNames"] = local_usedNames;
+      result["usedNames"] = local_usedNames;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -2499,110 +2497,110 @@
 abstract class _AvailableDeclarationMixin implements idl.AvailableDeclaration {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_children = children;
     if (local_children.isNotEmpty) {
-      _result["children"] =
-          local_children.map((_value) => _value.toJson()).toList();
+      result["children"] =
+          local_children.map((value) => value.toJson()).toList();
     }
     var local_codeLength = codeLength;
     if (local_codeLength != 0) {
-      _result["codeLength"] = local_codeLength;
+      result["codeLength"] = local_codeLength;
     }
     var local_codeOffset = codeOffset;
     if (local_codeOffset != 0) {
-      _result["codeOffset"] = local_codeOffset;
+      result["codeOffset"] = local_codeOffset;
     }
     var local_defaultArgumentListString = defaultArgumentListString;
     if (local_defaultArgumentListString != '') {
-      _result["defaultArgumentListString"] = local_defaultArgumentListString;
+      result["defaultArgumentListString"] = local_defaultArgumentListString;
     }
     var local_defaultArgumentListTextRanges = defaultArgumentListTextRanges;
     if (local_defaultArgumentListTextRanges.isNotEmpty) {
-      _result["defaultArgumentListTextRanges"] =
+      result["defaultArgumentListTextRanges"] =
           local_defaultArgumentListTextRanges;
     }
     var local_docComplete = docComplete;
     if (local_docComplete != '') {
-      _result["docComplete"] = local_docComplete;
+      result["docComplete"] = local_docComplete;
     }
     var local_docSummary = docSummary;
     if (local_docSummary != '') {
-      _result["docSummary"] = local_docSummary;
+      result["docSummary"] = local_docSummary;
     }
     var local_fieldMask = fieldMask;
     if (local_fieldMask != 0) {
-      _result["fieldMask"] = local_fieldMask;
+      result["fieldMask"] = local_fieldMask;
     }
     var local_isAbstract = isAbstract;
     if (local_isAbstract != false) {
-      _result["isAbstract"] = local_isAbstract;
+      result["isAbstract"] = local_isAbstract;
     }
     var local_isConst = isConst;
     if (local_isConst != false) {
-      _result["isConst"] = local_isConst;
+      result["isConst"] = local_isConst;
     }
     var local_isDeprecated = isDeprecated;
     if (local_isDeprecated != false) {
-      _result["isDeprecated"] = local_isDeprecated;
+      result["isDeprecated"] = local_isDeprecated;
     }
     var local_isFinal = isFinal;
     if (local_isFinal != false) {
-      _result["isFinal"] = local_isFinal;
+      result["isFinal"] = local_isFinal;
     }
     var local_isStatic = isStatic;
     if (local_isStatic != false) {
-      _result["isStatic"] = local_isStatic;
+      result["isStatic"] = local_isStatic;
     }
     var local_kind = kind;
     if (local_kind != idl.AvailableDeclarationKind.CLASS) {
-      _result["kind"] = local_kind.toString().split('.')[1];
+      result["kind"] = local_kind.toString().split('.')[1];
     }
     var local_locationOffset = locationOffset;
     if (local_locationOffset != 0) {
-      _result["locationOffset"] = local_locationOffset;
+      result["locationOffset"] = local_locationOffset;
     }
     var local_locationStartColumn = locationStartColumn;
     if (local_locationStartColumn != 0) {
-      _result["locationStartColumn"] = local_locationStartColumn;
+      result["locationStartColumn"] = local_locationStartColumn;
     }
     var local_locationStartLine = locationStartLine;
     if (local_locationStartLine != 0) {
-      _result["locationStartLine"] = local_locationStartLine;
+      result["locationStartLine"] = local_locationStartLine;
     }
     var local_name = name;
     if (local_name != '') {
-      _result["name"] = local_name;
+      result["name"] = local_name;
     }
     var local_parameterNames = parameterNames;
     if (local_parameterNames.isNotEmpty) {
-      _result["parameterNames"] = local_parameterNames;
+      result["parameterNames"] = local_parameterNames;
     }
     var local_parameters = parameters;
     if (local_parameters != '') {
-      _result["parameters"] = local_parameters;
+      result["parameters"] = local_parameters;
     }
     var local_parameterTypes = parameterTypes;
     if (local_parameterTypes.isNotEmpty) {
-      _result["parameterTypes"] = local_parameterTypes;
+      result["parameterTypes"] = local_parameterTypes;
     }
     var local_relevanceTags = relevanceTags;
     if (local_relevanceTags.isNotEmpty) {
-      _result["relevanceTags"] = local_relevanceTags;
+      result["relevanceTags"] = local_relevanceTags;
     }
     var local_requiredParameterCount = requiredParameterCount;
     if (local_requiredParameterCount != 0) {
-      _result["requiredParameterCount"] = local_requiredParameterCount;
+      result["requiredParameterCount"] = local_requiredParameterCount;
     }
     var local_returnType = returnType;
     if (local_returnType != '') {
-      _result["returnType"] = local_returnType;
+      result["returnType"] = local_returnType;
     }
     var local_typeParameters = typeParameters;
     if (local_typeParameters != '') {
-      _result["typeParameters"] = local_typeParameters;
+      result["typeParameters"] = local_typeParameters;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -2900,38 +2898,37 @@
 abstract class _AvailableFileMixin implements idl.AvailableFile {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_declarations = declarations;
     if (local_declarations.isNotEmpty) {
-      _result["declarations"] =
-          local_declarations.map((_value) => _value.toJson()).toList();
+      result["declarations"] =
+          local_declarations.map((value) => value.toJson()).toList();
     }
     var local_directiveInfo = directiveInfo;
     if (local_directiveInfo != null) {
-      _result["directiveInfo"] = local_directiveInfo.toJson();
+      result["directiveInfo"] = local_directiveInfo.toJson();
     }
     var local_exports = exports;
     if (local_exports.isNotEmpty) {
-      _result["exports"] =
-          local_exports.map((_value) => _value.toJson()).toList();
+      result["exports"] = local_exports.map((value) => value.toJson()).toList();
     }
     var local_isLibrary = isLibrary;
     if (local_isLibrary != false) {
-      _result["isLibrary"] = local_isLibrary;
+      result["isLibrary"] = local_isLibrary;
     }
     var local_isLibraryDeprecated = isLibraryDeprecated;
     if (local_isLibraryDeprecated != false) {
-      _result["isLibraryDeprecated"] = local_isLibraryDeprecated;
+      result["isLibraryDeprecated"] = local_isLibraryDeprecated;
     }
     var local_lineStarts = lineStarts;
     if (local_lineStarts.isNotEmpty) {
-      _result["lineStarts"] = local_lineStarts;
+      result["lineStarts"] = local_lineStarts;
     }
     var local_parts = parts;
     if (local_parts.isNotEmpty) {
-      _result["parts"] = local_parts;
+      result["parts"] = local_parts;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3057,17 +3054,17 @@
 abstract class _AvailableFileExportMixin implements idl.AvailableFileExport {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_combinators = combinators;
     if (local_combinators.isNotEmpty) {
-      _result["combinators"] =
-          local_combinators.map((_value) => _value.toJson()).toList();
+      result["combinators"] =
+          local_combinators.map((value) => value.toJson()).toList();
     }
     var local_uri = uri;
     if (local_uri != '') {
-      _result["uri"] = local_uri;
+      result["uri"] = local_uri;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3194,16 +3191,16 @@
     implements idl.AvailableFileExportCombinator {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_hides = hides;
     if (local_hides.isNotEmpty) {
-      _result["hides"] = local_hides;
+      result["hides"] = local_hides;
     }
     var local_shows = shows;
     if (local_shows.isNotEmpty) {
-      _result["shows"] = local_shows;
+      result["shows"] = local_shows;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3340,17 +3337,16 @@
 abstract class _CiderUnitErrorsMixin implements idl.CiderUnitErrors {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_errors = errors;
     if (local_errors.isNotEmpty) {
-      _result["errors"] =
-          local_errors.map((_value) => _value.toJson()).toList();
+      result["errors"] = local_errors.map((value) => value.toJson()).toList();
     }
     var local_signature = signature;
     if (local_signature.isNotEmpty) {
-      _result["signature"] = local_signature;
+      result["signature"] = local_signature;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3524,28 +3520,28 @@
 abstract class _DiagnosticMessageMixin implements idl.DiagnosticMessage {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_filePath = filePath;
     if (local_filePath != '') {
-      _result["filePath"] = local_filePath;
+      result["filePath"] = local_filePath;
     }
     var local_length = length;
     if (local_length != 0) {
-      _result["length"] = local_length;
+      result["length"] = local_length;
     }
     var local_message = message;
     if (local_message != '') {
-      _result["message"] = local_message;
+      result["message"] = local_message;
     }
     var local_offset = offset;
     if (local_offset != 0) {
-      _result["offset"] = local_offset;
+      result["offset"] = local_offset;
     }
     var local_url = url;
     if (local_url != '') {
-      _result["url"] = local_url;
+      result["url"] = local_url;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3672,16 +3668,16 @@
 abstract class _DirectiveInfoMixin implements idl.DirectiveInfo {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_templateNames = templateNames;
     if (local_templateNames.isNotEmpty) {
-      _result["templateNames"] = local_templateNames;
+      result["templateNames"] = local_templateNames;
     }
     var local_templateValues = templateValues;
     if (local_templateValues.isNotEmpty) {
-      _result["templateValues"] = local_templateValues;
+      result["templateValues"] = local_templateValues;
     }
-    return _result;
+    return result;
   }
 
   @override
@@ -3762,12 +3758,12 @@
 abstract class _PackageBundleMixin implements idl.PackageBundle {
   @override
   Map<String, Object> toJson() {
-    Map<String, Object> _result = <String, Object>{};
+    Map<String, Object> result = <String, Object>{};
     var local_fake = fake;
     if (local_fake != 0) {
-      _result["fake"] = local_fake;
+      result["fake"] = local_fake;
     }
-    return _result;
+    return result;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index c7c08cf..114c5ec 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -95,6 +95,8 @@
         return _readGenericFunctionType();
       case Tag.IfElement:
         return _readIfElement();
+      case Tag.ImplicitCallReference:
+        return _readImplicitCallReference();
       case Tag.IndexExpression:
         return _readIndexExpression();
       case Tag.IntegerLiteralNegative1:
@@ -647,6 +649,22 @@
     );
   }
 
+  ImplicitCallReference _readImplicitCallReference() {
+    var expression = readNode() as Expression;
+    var typeArguments = _readOptionalNode() as TypeArgumentList?;
+    var typeArgumentTypes = _reader.readOptionalTypeList()!;
+    var staticElement = _reader.readElement() as MethodElement;
+
+    var node = astFactory.implicitCallReference(
+      expression: expression,
+      staticElement: staticElement,
+      typeArguments: typeArguments,
+      typeArgumentTypes: typeArgumentTypes,
+    );
+    _readExpressionResolution(node);
+    return node;
+  }
+
   IndexExpression _readIndexExpression() {
     var flags = _readByte();
     var target = _readOptionalNode() as Expression?;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index a8033ec..38aa374 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -45,6 +45,7 @@
   static const int GenericFunctionType = 21;
   static const int HideCombinator = 48;
   static const int IfElement = 63;
+  static const int ImplicitCallReference = 104;
   static const int IndexExpression = 98;
   static const int InstanceCreationExpression = 25;
   static const int IntegerLiteralNegative = 73;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 446308d..e03af22 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -359,6 +359,18 @@
   }
 
   @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    _writeByte(Tag.ImplicitCallReference);
+    _writeNode(node.expression);
+    _writeOptionalNode(node.typeArguments);
+    _sink.writeOptionalTypeList(node.typeArgumentTypes);
+
+    _sink.writeElement(node.staticElement);
+
+    _storeExpression(node);
+  }
+
+  @override
   void visitIndexExpression(IndexExpression node) {
     _writeByte(Tag.IndexExpression);
     _writeByte(
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index 411f10f..ead4620 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -50,9 +50,13 @@
     flowAnalysisHelper: _flowAnalysis,
   );
 
-  AstResolver(this._linker, this._unitElement, this._nameScope, AstNode node,
-      {this.enclosingClassElement, this.enclosingExecutableElement})
-      : _featureSet = node.thisOrAncestorOfType<CompilationUnit>()!.featureSet;
+  AstResolver(
+    this._linker,
+    this._unitElement,
+    this._nameScope, {
+    this.enclosingClassElement,
+    this.enclosingExecutableElement,
+  }) : _featureSet = _unitElement.library.featureSet;
 
   void resolveAnnotation(AnnotationImpl node) {
     node.accept(_resolutionVisitor);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 14aa0a2..53915eb 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -272,25 +272,10 @@
 
   @override
   void _read(element, reader) {
-    var typeProvider = element.library.typeProvider;
-
     element.metadata = reader._readAnnotationList(
       unitElement: element.enclosingElement,
     );
-
-    var indexField = element.getField('index') as FieldElementImpl;
-    indexField.type = typeProvider.intType;
-
-    var toStringMethod = element.getMethod('toString') as MethodElementImpl;
-    toStringMethod.returnType = typeProvider.stringType;
-
-    for (var constant in element.constants) {
-      constant as FieldElementImpl;
-      constant.metadata = reader._readAnnotationList(
-        unitElement: element.enclosingElement,
-      );
-    }
-
+    _readTypeParameters(reader, element.typeParameters);
     applyConstantOffsets?.perform();
   }
 }
@@ -568,7 +553,7 @@
 
   List<ConstructorElementImpl> _readConstructors(
     CompilationUnitElementImpl unitElement,
-    ClassElementImpl classElement,
+    AbstractClassElementImpl classElement,
     Reference classReference,
   ) {
     var containerRef = classReference.getChild('@constructor');
@@ -608,55 +593,21 @@
       offset: resolutionOffset,
     );
     element.setLinkedData(reference, linkedData);
+    EnumElementFlags.read(_reader, element);
 
+    element.typeParameters = _readTypeParameters();
+
+    var accessors = <PropertyAccessorElement>[];
     var fields = <FieldElement>[];
-    var getters = <PropertyAccessorElement>[];
 
-    // Build the 'index' field.
-    {
-      var field = FieldElementImpl('index', -1)
-        ..enclosingElement = element
-        ..isSynthetic = true
-        ..isFinal = true;
-      fields.add(field);
-      getters.add(
-        PropertyAccessorElementImpl_ImplicitGetter(field,
-            reference: reference.getChild('@getter').getChild('index'))
-          ..enclosingElement = element,
-      );
-    }
-
-    // Build the 'values' field.
-    {
-      var field = ConstFieldElementImpl_EnumValues(element);
-      fields.add(field);
-      getters.add(
-        PropertyAccessorElementImpl_ImplicitGetter(field,
-            reference: reference.getChild('@getter').getChild('values'))
-          ..enclosingElement = element,
-      );
-    }
-
-    // Build fields for all enum constants.
-    var containerRef = reference.getChild('@constant');
-    var constantCount = _reader.readUInt30();
-    for (var i = 0; i < constantCount; i++) {
-      var constantName = _reader.readStringReference();
-      var field = ConstFieldElementImpl_EnumValue(element, constantName, i);
-      var constantRef = containerRef.getChild(constantName);
-      field.reference = constantRef;
-      constantRef.element = field;
-      fields.add(field);
-      getters.add(
-        PropertyAccessorElementImpl_ImplicitGetter(field,
-            reference: reference.getChild('@getter').getChild(constantName))
-          ..enclosingElement = element,
-      );
-    }
-
+    _readFields(unitElement, element, reference, accessors, fields);
+    _readPropertyAccessors(
+        unitElement, element, reference, accessors, fields, '@field');
     element.fields = fields;
-    element.accessors = getters;
-    element.createToStringMethodElement();
+    element.accessors = accessors;
+
+    element.constructors = _readConstructors(unitElement, element, reference);
+    element.methods = _readMethods(unitElement, element, reference);
 
     return element;
   }
@@ -891,6 +842,7 @@
       offset: resolutionOffset,
     );
     element.setLinkedData(reference, linkedData);
+    MixinElementFlags.read(_reader, element);
 
     element.typeParameters = _readTypeParameters();
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 946fd6e6..489d45d 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -172,13 +172,23 @@
     element as EnumElementImpl;
     _sink.writeUInt30(_resolutionSink.offset);
     _sink._writeStringReference(element.name);
+    EnumElementFlags.write(_sink, element);
     _resolutionSink._writeAnnotationList(element.metadata);
 
-    var constants =
-        element.fields.whereType<ConstFieldElementImpl_EnumValue>().toList();
-    _writeList<FieldElement>(constants, (field) {
-      _sink._writeStringReference(field.name);
-      _resolutionSink._writeAnnotationList(field.metadata);
+    _writeTypeParameters(element.typeParameters, () {
+      _writeList(
+        element.fields.where((e) {
+          return !e.isSynthetic ||
+              e is FieldElementImpl && e.isSyntheticEnumField;
+        }).toList(),
+        _writeFieldElement,
+      );
+      _writeList(
+        element.accessors.where((e) => !e.isSynthetic).toList(),
+        _writePropertyAccessorElement,
+      );
+      _writeList(element.constructors, _writeConstructorElement);
+      _writeList(element.methods, _writeMethodElement);
     });
   }
 
@@ -296,6 +306,7 @@
     _sink.writeUInt30(_resolutionSink.offset);
 
     _sink._writeStringReference(element.name);
+    MixinElementFlags.write(_sink, element);
     _resolutionSink._writeAnnotationList(element.metadata);
 
     _writeTypeParameters(element.typeParameters, () {
diff --git a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
index 48f2df7..0449c8c 100644
--- a/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/constructor_initializer_resolver.dart
@@ -46,7 +46,7 @@
       element,
     );
 
-    var astResolver = AstResolver(_linker, unitElement, initializerScope, node,
+    var astResolver = AstResolver(_linker, unitElement, initializerScope,
         enclosingClassElement: classElement,
         enclosingExecutableElement: element);
 
diff --git a/pkg/analyzer/lib/src/summary2/data_reader.dart b/pkg/analyzer/lib/src/summary2/data_reader.dart
index e72e947..9c1988d 100644
--- a/pkg/analyzer/lib/src/summary2/data_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/data_reader.dart
@@ -242,7 +242,7 @@
     }
   }
 
-  static String _decodeWtf8(Uint8List _bytes, int start, int end) {
+  static String _decodeWtf8(Uint8List bytes, int start, int end) {
     // WTF-8 decoder that trusts its input, meaning that the correctness of
     // the code depends on the bytes from start to end being valid and
     // complete WTF-8. Instead of masking off the control bits from every
@@ -252,28 +252,28 @@
     int i = start;
     int j = 0;
     while (i < end) {
-      int byte = _bytes[i++];
+      int byte = bytes[i++];
       if (byte < 0x80) {
         // ASCII.
         charCodes[j++] = byte;
       } else if (byte < 0xE0) {
         // Two-byte sequence (11-bit unicode value).
-        int byte2 = _bytes[i++];
+        int byte2 = bytes[i++];
         int value = (byte << 6) ^ byte2 ^ 0x3080;
         assert(value >= 0x80 && value < 0x800);
         charCodes[j++] = value;
       } else if (byte < 0xF0) {
         // Three-byte sequence (16-bit unicode value).
-        int byte2 = _bytes[i++];
-        int byte3 = _bytes[i++];
+        int byte2 = bytes[i++];
+        int byte3 = bytes[i++];
         int value = (byte << 12) ^ (byte2 << 6) ^ byte3 ^ 0xE2080;
         assert(value >= 0x800 && value < 0x10000);
         charCodes[j++] = value;
       } else {
         // Four-byte sequence (non-BMP unicode value).
-        int byte2 = _bytes[i++];
-        int byte3 = _bytes[i++];
-        int byte4 = _bytes[i++];
+        int byte2 = bytes[i++];
+        int byte3 = bytes[i++];
+        int byte4 = bytes[i++];
         int value =
             (byte << 18) ^ (byte2 << 12) ^ (byte3 << 6) ^ byte4 ^ 0x3C82080;
         assert(value >= 0x10000 && value < 0x110000);
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index d565a18..ec3ff9a 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -34,6 +34,11 @@
         _breakSelfCycles(node.typeParameters);
         _breakRawTypeCycles(element, node.typeParameters);
         _computeBounds(element, node.typeParameters);
+      } else if (node is EnumDeclaration) {
+        var element = node.declaredElement!;
+        _breakSelfCycles(node.typeParameters);
+        _breakRawTypeCycles(element, node.typeParameters);
+        _computeBounds(element, node.typeParameters);
       } else if (node is FunctionTypeAlias) {
         var element = node.declaredElement!;
         _breakSelfCycles(node.typeParameters);
@@ -56,6 +61,8 @@
         _build(node.typeParameters);
       } else if (node is ClassTypeAlias) {
         _build(node.typeParameters);
+      } else if (node is EnumDeclaration) {
+        _build(node.typeParameters);
       } else if (node is FunctionTypeAlias) {
         _build(node.typeParameters);
       } else if (node is GenericTypeAlias) {
@@ -246,7 +253,6 @@
           void recurseParameters(List<TypeParameterElement> parameters) {
             for (var parameter in parameters) {
               var parameterNode = _linker.getLinkingNode(parameter);
-              // TODO(scheglov) How to we skip already linked?
               if (parameterNode is TypeParameter) {
                 var bound = parameterNode.bound;
                 if (bound != null) {
diff --git a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
index 9675fd4..632a6c4 100644
--- a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
@@ -16,61 +16,31 @@
   final LibraryElementImpl _libraryElement;
   final TypeSystemImpl _typeSystem;
 
-  late CompilationUnitElementImpl _unitElement;
-  ClassElement? _classElement;
-  late ExecutableElement _executableElement;
-  late Scope _scope;
-
   DefaultValueResolver(this._linker, this._libraryElement)
       : _typeSystem = _libraryElement.typeSystem;
 
   void resolve() {
-    for (var unit in _libraryElement.units) {
-      _unitElement = unit as CompilationUnitElementImpl;
-
-      for (var classElement in unit.classes) {
-        _class(classElement);
-      }
-
-      for (var extensionElement in unit.extensions) {
-        _extension(extensionElement);
-      }
-
-      for (var classElement in unit.mixins) {
-        _class(classElement);
-      }
-
-      for (var element in unit.functions) {
-        _function(element);
-      }
+    for (var unitElement in _libraryElement.units.impl) {
+      _UnitContext(unitElement)
+        ..forEach(unitElement.classes, _class)
+        ..forEach(unitElement.extensions, _extension)
+        ..forEach(unitElement.functions, _executable)
+        ..forEach(unitElement.mixins, _class);
     }
   }
 
-  void _class(ClassElement classElement) {
-    _classElement = classElement;
-
-    for (var element in classElement.constructors) {
-      _constructor(element as ConstructorElementImpl);
-    }
-
-    for (var element in classElement.methods) {
-      _setScopeFromElement(element);
-      _method(element as MethodElementImpl);
-    }
-
-    _classElement = null;
+  void _class(_UnitContext context, ClassElement element) {
+    _ClassContext(context, element)
+      ..forEach(element.constructors, _constructor)
+      ..forEach(element.methods, _executable);
   }
 
-  void _constructor(ConstructorElementImpl element) {
+  void _constructor(_ClassContext context, ConstructorElement element) {
     if (element.isSynthetic) return;
-
-    _executableElement = element;
-    _setScopeFromElement(element);
-
-    _parameters(element.parameters);
+    _executable(context, element);
   }
 
-  DefaultFormalParameter? _defaultParameter(ParameterElementImpl element) {
+  DefaultFormalParameter? _defaultParameter(ParameterElement element) {
     var node = _linker.getLinkingNode(element);
     if (node is DefaultFormalParameter && node.defaultValue != null) {
       return node;
@@ -79,32 +49,21 @@
     }
   }
 
-  void _extension(ExtensionElement extensionElement) {
-    for (var element in extensionElement.methods) {
-      _setScopeFromElement(element);
-      _method(element as MethodElementImpl);
-    }
+  void _executable(_Context context, ExecutableElement element) {
+    _ExecutableContext(
+      enclosingContext: context,
+      executableElement: element,
+      scope: _scopeFromElement(element),
+    ).forEach(element.parameters, _parameter);
   }
 
-  void _function(FunctionElement element) {
-    _executableElement = element;
-    _setScopeFromElement(element);
-
-    _parameters(element.parameters);
+  void _extension(_UnitContext context, ExtensionElement element) {
+    context.forEach(element.methods, _executable);
   }
 
-  void _method(MethodElementImpl element) {
-    _executableElement = element;
-    _setScopeFromElement(element);
-
-    _parameters(element.parameters);
-  }
-
-  void _parameter(ParameterElementImpl parameter) {
+  void _parameter(_ExecutableContext context, ParameterElement parameter) {
     // If a function typed parameter, process nested parameters.
-    for (var localParameter in parameter.parameters) {
-      _parameter(localParameter as ParameterElementImpl);
-    }
+    context.forEach(parameter.parameters, _parameter);
 
     var node = _defaultParameter(parameter);
     if (node == null) return;
@@ -112,21 +71,82 @@
     var contextType = _typeSystem.eliminateTypeVariables(parameter.type);
 
     var astResolver = AstResolver(
-        _linker, _unitElement, _scope, node.defaultValue!,
-        enclosingClassElement: _classElement,
-        enclosingExecutableElement: _executableElement);
+      _linker,
+      context.unitElement,
+      context.scope,
+      enclosingClassElement: context.classElement,
+      enclosingExecutableElement: context.executableElement,
+    );
     astResolver.resolveExpression(() => node.defaultValue!,
         contextType: contextType);
   }
 
-  void _parameters(List<ParameterElement> parameters) {
-    for (var parameter in parameters) {
-      _parameter(parameter as ParameterElementImpl);
-    }
-  }
-
-  void _setScopeFromElement(Element element) {
+  Scope _scopeFromElement(Element element) {
     var node = _linker.getLinkingNode(element)!;
-    _scope = LinkingNodeContext.get(node).scope;
+    return LinkingNodeContext.get(node).scope;
+  }
+}
+
+class _ClassContext extends _Context {
+  final _UnitContext unitContext;
+
+  @override
+  final ClassElement classElement;
+
+  _ClassContext(this.unitContext, this.classElement);
+
+  @override
+  CompilationUnitElementImpl get unitElement {
+    return unitContext.unitElement;
+  }
+}
+
+abstract class _Context {
+  ClassElement? get classElement => null;
+
+  CompilationUnitElementImpl get unitElement;
+}
+
+class _ExecutableContext extends _Context {
+  final _Context enclosingContext;
+  final ExecutableElement executableElement;
+  final Scope scope;
+
+  _ExecutableContext({
+    required this.enclosingContext,
+    required this.executableElement,
+    required this.scope,
+  });
+
+  @override
+  ClassElement? get classElement => enclosingContext.classElement;
+
+  @override
+  CompilationUnitElementImpl get unitElement {
+    return enclosingContext.unitElement;
+  }
+}
+
+class _UnitContext extends _Context {
+  @override
+  final CompilationUnitElementImpl unitElement;
+
+  _UnitContext(this.unitElement);
+}
+
+extension on List<CompilationUnitElement> {
+  List<CompilationUnitElementImpl> get impl {
+    return cast();
+  }
+}
+
+extension _ContextExtension<C extends _Context> on C {
+  void forEach<T>(
+    List<T> elements,
+    void Function(C context, T element) f,
+  ) {
+    for (var element in elements) {
+      f(this, element);
+    }
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index f0d5965..667c275 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -3,12 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
 import 'package:analyzer/src/summary2/library_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -180,7 +184,7 @@
     node.declaredElement = element;
     _linker.elementNodes[element] = node;
 
-    var reference = _enclosingContext.addConstructor(name, element);
+    var reference = _enclosingContext.addConstructor(element);
     _buildExecutableElementChildren(
       reference: reference,
       element: element,
@@ -209,6 +213,180 @@
 
     var reference = _enclosingContext.addEnum(name, element);
     _libraryBuilder.localScope.declare(name, reference);
+
+    var holder = _EnclosingContext(
+      reference,
+      element,
+      hasConstConstructor: true,
+    );
+
+    var needsImplicitConstructor =
+        !node.members.any((e) => e is ConstructorDeclaration);
+
+    // Build fields for all enum constants.
+    var constants = node.constants;
+    var valuesElements = <Expression>[];
+    for (var i = 0; i < constants.length; ++i) {
+      var constant = constants[i];
+      var name = constant.name.name;
+      var field = ConstFieldElementImpl(name, constant.name.offset)
+        ..hasImplicitType = true
+        ..isConst = true
+        ..isEnumConstant = true
+        ..isStatic = true
+        ..type = DynamicTypeImpl.instance;
+      _setCodeRange(field, constant);
+      _setDocumentation(field, constant);
+      field.metadata = _buildAnnotationsWithUnit(
+        _unitElement,
+        constant.metadata,
+      );
+
+      var constructorSelector = constant.arguments?.constructorSelector;
+      var constructorName = constructorSelector?.name.name ?? '';
+
+      var initializer = astFactory.instanceCreationExpression(
+        null,
+        astFactory.constructorName(
+          astFactory.namedType(
+            name: astFactory.simpleIdentifier(
+              StringToken(TokenType.STRING, element.name, -1),
+            ),
+            typeArguments: constant.arguments?.typeArguments,
+          ),
+          Tokens.period(),
+          astFactory.simpleIdentifier(
+            StringToken(TokenType.STRING, constructorName, -1),
+          ),
+        ),
+        astFactory.argumentList(
+          Tokens.openParenthesis(),
+          [
+            ...?constant.arguments?.argumentList.arguments,
+          ],
+          Tokens.closeParenthesis(),
+        ),
+      );
+
+      var variableDeclaration = astFactory.variableDeclaration(
+        astFactory.simpleIdentifier(
+          StringToken(TokenType.STRING, name, -1),
+        ),
+        Tokens.eq(),
+        initializer,
+      );
+      astFactory.variableDeclarationList2(
+        variables: [variableDeclaration],
+      );
+      _linker.elementNodes[field] = variableDeclaration;
+
+      field.constantInitializer = initializer;
+      holder.addNonSyntheticField(field);
+      valuesElements.add(
+        astFactory.simpleIdentifier(
+          StringToken(TokenType.STRING, name, -1),
+        ),
+      );
+    }
+
+    // Build the 'values' field.
+    ConstFieldElementImpl valuesField;
+    NamedTypeImpl valuesTypeNode;
+    {
+      valuesField = ConstFieldElementImpl('values', -1)
+        ..isConst = true
+        ..isStatic = true
+        ..isSynthetic = true;
+      var initializer = astFactory.listLiteral(
+        null,
+        null,
+        Tokens.openSquareBracket(),
+        valuesElements,
+        Tokens.closeSquareBracket(),
+      );
+      valuesField.constantInitializer = initializer;
+
+      var variableDeclaration = astFactory.variableDeclaration(
+        astFactory.simpleIdentifier(
+          StringToken(TokenType.STRING, 'values', -1),
+        ),
+        Tokens.eq(),
+        initializer,
+      );
+      valuesTypeNode = astFactory.namedType(
+        name: astFactory.simpleIdentifier(
+          StringToken(TokenType.STRING, 'List', -1),
+        ),
+        typeArguments: astFactory.typeArgumentList(
+          Tokens.lt(),
+          [
+            astFactory.namedType(
+              name: astFactory.simpleIdentifier(
+                StringToken(TokenType.STRING, element.name, -1),
+              )..staticElement = element,
+            )
+          ],
+          Tokens.gt(),
+        ),
+      );
+      astFactory.variableDeclarationList2(
+        keyword: Tokens.const_(),
+        variables: [variableDeclaration],
+        type: valuesTypeNode,
+      );
+      _linker.elementNodes[valuesField] = variableDeclaration;
+
+      holder.addNonSyntheticField(valuesField);
+    }
+
+    // TODO(scheglov) implement
+    // node.extendsClause?.accept(this);
+    // node.withClause?.accept(this);
+    // node.implementsClause?.accept(this);
+
+    // Build the 'index' field.
+    var indexField = ConstFieldElementImpl('index', -1)
+      ..isFinal = true
+      ..isSynthetic = true;
+    holder.addNonSyntheticField(indexField);
+
+    _withEnclosing(holder, () {
+      node.typeParameters?.accept(this);
+      _visitPropertyFirst<FieldDeclaration>(node.members);
+    });
+
+    if (needsImplicitConstructor) {
+      holder.addConstructor(
+        ConstructorElementImpl('', -1)
+          ..isConst = true
+          ..isSynthetic = true,
+      );
+    }
+
+    MethodElementImpl? syntheticToStringMethod;
+    if (holder.getMethod('toString').element == null) {
+      syntheticToStringMethod = MethodElementImpl('toString', -1)
+        ..isSynthetic = true;
+      holder.addMethod(name, syntheticToStringMethod);
+    }
+
+    _libraryBuilder.implicitEnumNodes.add(
+      ImplicitEnumNodes(
+        element: element,
+        indexField: indexField,
+        valuesTypeNode: valuesTypeNode,
+        valuesField: valuesField,
+        syntheticToStringMethod: syntheticToStringMethod,
+      ),
+    );
+
+    element.accessors = holder.propertyAccessors;
+    element.constructors = holder.constructors;
+    element.fields = holder.properties.whereType<FieldElementImpl>().toList();
+    element.methods = holder.methods;
+    element.typeParameters = holder.typeParameters;
+
+    // TODO(scheglov) resolve field formals
   }
 
   @override
@@ -258,8 +436,12 @@
       }
     });
 
+    // TODO(scheglov) don't create a duplicate
     {
-      var holder = _buildClassMembers(element, node.members);
+      var holder = _EnclosingContext(reference, element);
+      _withEnclosing(holder, () {
+        _visitPropertyFirst<FieldDeclaration>(node.members);
+      });
       element.accessors = holder.propertyAccessors;
       element.fields = holder.properties.whereType<FieldElement>().toList();
       element.methods = holder.methods;
@@ -272,8 +454,6 @@
   void visitFieldDeclaration(
     covariant FieldDeclarationImpl node,
   ) {
-    var enclosingRef = _enclosingContext.reference;
-
     var metadata = _buildAnnotations(node.metadata);
     for (var variable in node.fields.variables) {
       var nameNode = variable.name as SimpleIdentifierImpl;
@@ -305,21 +485,10 @@
         element.type = DynamicTypeImpl.instance;
       }
 
-      element.createImplicitAccessors(enclosingRef, name);
+      _enclosingContext.addNonSyntheticField(element);
 
       _linker.elementNodes[element] = variable;
-      _enclosingContext.addField(name, element);
       nameNode.staticElement = element;
-
-      var getter = element.getter;
-      if (getter is PropertyAccessorElementImpl) {
-        _enclosingContext.addGetter(name, getter);
-      }
-
-      var setter = element.setter;
-      if (setter is PropertyAccessorElementImpl) {
-        _enclosingContext.addSetter(name, setter);
-      }
     }
     _buildType(node.fields.type);
   }
@@ -937,29 +1106,23 @@
     return _buildAnnotationsWithUnit(_unitElement, nodeList);
   }
 
-  _EnclosingContext _buildClassMembers(
-      ElementImpl element, NodeList<ClassMember> members) {
-    var hasConstConstructor = members.any((e) {
+  void _buildClassOrMixin(ClassOrMixinDeclaration node) {
+    var element = node.declaredElement as ClassElementImpl;
+    var hasConstConstructor = node.members.any((e) {
       return e is ConstructorDeclaration && e.constKeyword != null;
     });
+    // TODO(scheglov) don't create a duplicate
     var holder = _EnclosingContext(element.reference!, element,
         hasConstConstructor: hasConstConstructor);
     _withEnclosing(holder, () {
-      _visitPropertyFirst<FieldDeclaration>(members);
+      _visitPropertyFirst<FieldDeclaration>(node.members);
     });
-    return holder;
-  }
-
-  void _buildClassOrMixin(ClassOrMixinDeclaration node) {
-    var element = node.declaredElement as ClassElementImpl;
-    var holder = _buildClassMembers(element, node.members);
     element.accessors = holder.propertyAccessors;
     element.fields = holder.properties.whereType<FieldElement>().toList();
     element.methods = holder.methods;
 
     if (holder.constructors.isEmpty) {
       holder.addConstructor(
-        '',
         ConstructorElementImpl('', -1)..isSynthetic = true,
       );
     }
@@ -1124,73 +1287,6 @@
     }
   }
 
-  static void buildEnumChildren(
-    Linker linker,
-    LibraryElementImpl libraryElement,
-  ) {
-    for (var unitElement in libraryElement.units) {
-      for (var element in unitElement.enums) {
-        var node = linker.elementNodes[element] as EnumDeclaration;
-        element as EnumElementImpl;
-        var reference = element.reference!;
-
-        var fields = <FieldElementImpl>[];
-        var getters = <PropertyAccessorElementImpl>[];
-
-        // Build the 'index' field.
-        {
-          var field = FieldElementImpl('index', -1)
-            ..enclosingElement = element
-            ..isSynthetic = true
-            ..isFinal = true
-            ..type = libraryElement.typeProvider.intType;
-          fields.add(field);
-          getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
-              reference: reference.getChild('@getter').getChild('index'))
-            ..enclosingElement = element);
-        }
-
-        // Build the 'values' field.
-        {
-          var field = ConstFieldElementImpl_EnumValues(element);
-          fields.add(field);
-          getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
-              reference: reference.getChild('@getter').getChild('values'))
-            ..enclosingElement = element);
-        }
-
-        // Build fields for all enum constants.
-        var containerRef = reference.getChild('@constant');
-        var constants = node.constants;
-        for (var i = 0; i < constants.length; ++i) {
-          var constant = constants[i];
-          var name = constant.name.name;
-          var reference = containerRef.getChild(name);
-          var field = ConstFieldElementImpl_EnumValue(element, name, i);
-          // TODO(scheglov) test it
-          field.nameOffset = constant.name.offset;
-          _setCodeRange(field, constant);
-          _setDocumentation(field, constant);
-          field.reference = reference;
-          field.metadata = _buildAnnotationsWithUnit(
-            unitElement as CompilationUnitElementImpl,
-            constant.metadata,
-          );
-          field.createImplicitAccessors(containerRef.parent!, name);
-          fields.add(field);
-          getters.add(field.getter as PropertyAccessorElementImpl);
-        }
-
-        element.fields = fields;
-        element.accessors = getters;
-
-        element.createToStringMethodElement();
-        (element.getMethod('toString') as MethodElementImpl).returnType =
-            libraryElement.typeProvider.stringType;
-      }
-    }
-  }
-
   static List<ElementAnnotation> _buildAnnotationsWithUnit(
     CompilationUnitElementImpl unitElement,
     List<Annotation> nodeList,
@@ -1281,9 +1377,9 @@
     return _bindReference('@class', name, element);
   }
 
-  Reference addConstructor(String name, ConstructorElementImpl element) {
+  Reference addConstructor(ConstructorElementImpl element) {
     constructors.add(element);
-    return _bindReference('@constructor', name, element);
+    return _bindReference('@constructor', element.name, element);
   }
 
   Reference addEnum(String name, EnumElementImpl element) {
@@ -1321,6 +1417,23 @@
     return _bindReference('@mixin', name, element);
   }
 
+  void addNonSyntheticField(FieldElementImpl element) {
+    var name = element.name;
+    element.createImplicitAccessors(reference, name);
+
+    addField(name, element);
+
+    var getter = element.getter;
+    if (getter is PropertyAccessorElementImpl) {
+      addGetter(name, getter);
+    }
+
+    var setter = element.setter;
+    if (setter is PropertyAccessorElementImpl) {
+      addSetter(name, setter);
+    }
+  }
+
   Reference? addParameter(String? name, ParameterElementImpl element) {
     parameters.add(element);
     if (name == null) {
@@ -1351,6 +1464,10 @@
     this.element.encloseElement(element);
   }
 
+  Reference getMethod(String name) {
+    return reference.getChild('@method').getChild(name);
+  }
+
   Reference _bindReference(
     String containerName,
     String name,
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index 806aab7..ff4cdbc 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -51,6 +51,21 @@
   }
 }
 
+class EnumElementFlags {
+  static const int _isSimplyBounded = 1 << 0;
+
+  static void read(SummaryDataReader reader, EnumElementImpl element) {
+    var byte = reader.readByte();
+    element.isSimplyBounded = (byte & _isSimplyBounded) != 0;
+  }
+
+  static void write(BufferedSink sink, EnumElementImpl element) {
+    var result = 0;
+    result |= element.isSimplyBounded ? _isSimplyBounded : 0;
+    sink.writeByte(result);
+  }
+}
+
 class FieldElementFlags {
   static const int _hasImplicitType = 1 << 0;
   static const int _hasInitializer = 1 << 1;
@@ -58,10 +73,12 @@
   static const int _isAbstract = 1 << 3;
   static const int _isConst = 1 << 4;
   static const int _isCovariant = 1 << 5;
-  static const int _isExternal = 1 << 6;
-  static const int _isFinal = 1 << 7;
-  static const int _isLate = 1 << 8;
-  static const int _isStatic = 1 << 9;
+  static const int _isEnumConstant = 1 << 6;
+  static const int _isExternal = 1 << 7;
+  static const int _isFinal = 1 << 8;
+  static const int _isLate = 1 << 9;
+  static const int _isStatic = 1 << 10;
+  static const int _isSynthetic = 1 << 11;
 
   static void read(SummaryDataReader reader, FieldElementImpl element) {
     var byte = reader.readUInt30();
@@ -71,10 +88,12 @@
     element.isAbstract = (byte & _isAbstract) != 0;
     element.isConst = (byte & _isConst) != 0;
     element.isCovariant = (byte & _isCovariant) != 0;
+    element.isEnumConstant = (byte & _isEnumConstant) != 0;
     element.isExternal = (byte & _isExternal) != 0;
     element.isFinal = (byte & _isFinal) != 0;
     element.isLate = (byte & _isLate) != 0;
     element.isStatic = (byte & _isStatic) != 0;
+    element.isSynthetic = (byte & _isSynthetic) != 0;
   }
 
   static void write(BufferedSink sink, FieldElementImpl element) {
@@ -85,10 +104,12 @@
     result |= element.isAbstract ? _isAbstract : 0;
     result |= element.isConst ? _isConst : 0;
     result |= element.isCovariant ? _isCovariant : 0;
+    result |= element.isEnumConstant ? _isEnumConstant : 0;
     result |= element.isExternal ? _isExternal : 0;
     result |= element.isFinal ? _isFinal : 0;
     result |= element.isLate ? _isLate : 0;
     result |= element.isStatic ? _isStatic : 0;
+    result |= element.isSynthetic ? _isSynthetic : 0;
     sink.writeUInt30(result);
   }
 }
@@ -160,6 +181,7 @@
   static const int _isExternal = 1 << 3;
   static const int _isGenerator = 1 << 4;
   static const int _isStatic = 1 << 5;
+  static const int _isSynthetic = 1 << 6;
 
   static void read(SummaryDataReader reader, MethodElementImpl element) {
     var byte = reader.readByte();
@@ -169,6 +191,7 @@
     element.isExternal = (byte & _isExternal) != 0;
     element.isGenerator = (byte & _isGenerator) != 0;
     element.isStatic = (byte & _isStatic) != 0;
+    element.isSynthetic = (byte & _isSynthetic) != 0;
   }
 
   static void write(BufferedSink sink, MethodElementImpl element) {
@@ -179,6 +202,22 @@
     result |= element.isExternal ? _isExternal : 0;
     result |= element.isGenerator ? _isGenerator : 0;
     result |= element.isStatic ? _isStatic : 0;
+    result |= element.isSynthetic ? _isSynthetic : 0;
+    sink.writeByte(result);
+  }
+}
+
+class MixinElementFlags {
+  static const int _isSimplyBounded = 1 << 0;
+
+  static void read(SummaryDataReader reader, MixinElementImpl element) {
+    var byte = reader.readByte();
+    element.isSimplyBounded = (byte & _isSimplyBounded) != 0;
+  }
+
+  static void write(BufferedSink sink, MixinElementImpl element) {
+    var result = 0;
+    result |= element.isSimplyBounded ? _isSimplyBounded : 0;
     sink.writeByte(result);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index c592b1f..1d68050 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -254,6 +254,7 @@
         element.nameOffset = info.nameOffset;
         element.nameEnd = info.nameEnd;
         element.documentationComment = info.documentationComment;
+
         _applyToFormalParameters(
           element.parameters_unresolved,
           info.parameters,
@@ -274,30 +275,28 @@
 
   void _applyToEnumDeclaration(
     ClassElement element,
-    _InfoEnumDeclaration info,
+    _InfoClassDeclaration info,
   ) {
     element as EnumElementImpl;
     element.setCodeRange(info.codeOffset, info.codeLength);
     element.nameOffset = info.nameOffset;
     element.documentationComment = info.documentationComment;
 
-    forCorrespondingPairs<FieldElement, _InfoEnumConstantDeclaration>(
-      element.constants_unresolved,
-      info.constants,
-      (element, info) {
-        element as FieldElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.nameOffset = info.nameOffset;
-        element.documentationComment = info.documentationComment;
-      },
+    _applyToTypeParameters(
+      element.typeParameters_unresolved,
+      info.typeParameters,
     );
+    _applyToConstructors(element.constructors, info.constructors);
+    _applyToFields(element.fields, info.fields);
+    _applyToAccessors(element.accessors, info.accessors);
+    _applyToMethods(element.methods, info.methods);
 
     var linkedData = element.linkedData as EnumElementLinkedData;
     linkedData.applyConstantOffsets = ApplyConstantOffsets(
       info.constantOffsets,
       (applier) {
         applier.applyToMetadata(element);
-        applier.applyToEnumConstants(element.constants);
+        applier.applyToTypeParameters(element.typeParameters);
       },
     );
   }
@@ -766,60 +765,6 @@
   });
 }
 
-class _InfoEnumConstantDeclaration {
-  final int codeOffset;
-  final int codeLength;
-  final int nameOffset;
-  final String? documentationComment;
-
-  factory _InfoEnumConstantDeclaration(SummaryDataReader reader) {
-    return _InfoEnumConstantDeclaration._(
-      codeOffset: reader.readUInt30(),
-      codeLength: reader.readUInt30(),
-      nameOffset: reader.readUInt30(),
-      documentationComment: reader.readStringUtf8().nullIfEmpty,
-    );
-  }
-
-  _InfoEnumConstantDeclaration._({
-    required this.codeOffset,
-    required this.codeLength,
-    required this.nameOffset,
-    required this.documentationComment,
-  });
-}
-
-class _InfoEnumDeclaration {
-  final int codeOffset;
-  final int codeLength;
-  final int nameOffset;
-  final String? documentationComment;
-  final List<_InfoEnumConstantDeclaration> constants;
-  final Uint32List constantOffsets;
-
-  factory _InfoEnumDeclaration(SummaryDataReader reader) {
-    return _InfoEnumDeclaration._(
-      codeOffset: reader.readUInt30(),
-      codeLength: reader.readUInt30(),
-      nameOffset: reader.readUInt30(),
-      documentationComment: reader.readStringUtf8().nullIfEmpty,
-      constants: reader.readTypedList(
-        () => _InfoEnumConstantDeclaration(reader),
-      ),
-      constantOffsets: reader.readUInt30List(),
-    );
-  }
-
-  _InfoEnumDeclaration._({
-    required this.codeOffset,
-    required this.codeLength,
-    required this.nameOffset,
-    required this.documentationComment,
-    required this.constants,
-    required this.constantOffsets,
-  });
-}
-
 class _InfoExport {
   final int nameOffset;
   final List<_InfoCombinator> combinators;
@@ -1163,15 +1108,15 @@
       sink.writeUInt30(node.length);
       sink.writeUInt30(node.name.offset);
       _writeDocumentationComment(node);
-      sink.writeList2<EnumConstantDeclaration>(node.constants, (node) {
-        sink.writeUInt30(node.offset);
-        sink.writeUInt30(node.length);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-      });
+      _writeTypeParameters(node.typeParameters);
+      _writeConstructors(node.members);
+      _writeEnumFields(node.constants, node.members);
+      _writeGettersSetters(node.members);
+      _writeMethods(node.members);
       _writeOffsets(
         metadata: node.metadata,
         enumConstants: node.constants,
+        typeParameters: node.typeParameters,
       );
     });
 
@@ -1332,27 +1277,58 @@
     sink.writeStringUtf8(commentText ?? '');
   }
 
+  void _writeEnumFields(
+    List<EnumConstantDeclaration> constants,
+    List<ClassMember> members,
+  ) {
+    var fields = members
+        .whereType<FieldDeclaration>()
+        .expand((declaration) => declaration.fields.variables)
+        .toList();
+
+    sink.writeUInt30(constants.length + fields.length);
+
+    // Write constants in the same format as fields.
+    for (var node in constants) {
+      var codeOffset = node.offset;
+      sink.writeUInt30(codeOffset);
+      sink.writeUInt30(node.end - codeOffset);
+      sink.writeUInt30(node.name.offset);
+      _writeDocumentationComment(node);
+      _writeOffsets(
+        metadata: node.metadata,
+        enumConstantArguments: node.arguments,
+      );
+    }
+
+    for (var field in fields) {
+      _writeField(field);
+    }
+  }
+
+  void _writeField(VariableDeclaration node) {
+    var codeOffset = _codeOffsetForVariable(node);
+    sink.writeUInt30(codeOffset);
+    sink.writeUInt30(node.end - codeOffset);
+    sink.writeUInt30(node.name.offset);
+    _writeDocumentationComment(node);
+
+    // TODO(scheglov) Replace with some kind of double-iterating list.
+    var declaration = node.parent!.parent as FieldDeclaration;
+
+    _writeOffsets(
+      metadata: declaration.metadata,
+      constantInitializer: node.initializer,
+    );
+  }
+
   void _writeFields(List<ClassMember> members) {
     sink.writeList<VariableDeclaration>(
       members
           .whereType<FieldDeclaration>()
           .expand((declaration) => declaration.fields.variables)
           .toList(),
-      (node) {
-        var codeOffset = _codeOffsetForVariable(node);
-        sink.writeUInt30(codeOffset);
-        sink.writeUInt30(node.end - codeOffset);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-
-        // TODO(scheglov) Replace with some kind of double-iterating list.
-        var declaration = node.parent!.parent as FieldDeclaration;
-
-        _writeOffsets(
-          metadata: declaration.metadata,
-          constantInitializer: node.initializer,
-        );
-      },
+      _writeField,
     );
   }
 
@@ -1370,6 +1346,9 @@
       } else if (notDefault is FunctionTypedFormalParameter) {
         _writeTypeParameters(notDefault.typeParameters);
         _writeFormalParameters(notDefault.parameters);
+      } else if (notDefault is SuperFormalParameter) {
+        _writeTypeParameters(notDefault.typeParameters);
+        _writeFormalParameters(notDefault.parameters);
       } else {
         _writeTypeParameters(null);
         _writeFormalParameters(null);
@@ -1452,6 +1431,7 @@
     NodeList<ConstructorInitializer>? constructorInitializers,
     NodeList<EnumConstantDeclaration>? enumConstants,
     TypeAnnotation? aliasedType,
+    EnumConstantArguments? enumConstantArguments,
   }) {
     var collector = _OffsetsCollector();
 
@@ -1503,6 +1483,8 @@
       addTypeParameters(aliasedType.typeParameters);
       addFormalParameters(aliasedType.parameters);
     }
+    enumConstantArguments?.typeArguments?.accept(collector);
+    enumConstantArguments?.argumentList.arguments.accept(collector);
     sink.writeUint30List(collector.offsets);
   }
 
@@ -1590,7 +1572,7 @@
   final List<_InfoPart> parts;
   final List<_InfoClassDeclaration> classDeclarations;
   final List<_InfoClassTypeAlias> classTypeAliases;
-  final List<_InfoEnumDeclaration> enums;
+  final List<_InfoClassDeclaration> enums;
   final List<_InfoClassDeclaration> extensions;
   final List<_InfoMethodDeclaration> accessors;
   final List<_InfoFunctionDeclaration> functions;
@@ -1623,7 +1605,7 @@
         () => _InfoClassTypeAlias(reader),
       ),
       enums: reader.readTypedList(
-        () => _InfoEnumDeclaration(reader),
+        () => _InfoClassDeclaration(reader),
       ),
       extensions: reader.readTypedList(
         () => _InfoClassDeclaration(reader, nameOffsetDelta: 1),
@@ -1678,11 +1660,10 @@
   _OffsetsApplier(this._iterator);
 
   void applyToConstantInitializer(Element element) {
-    if (element is ConstVariableElement) {
-      var initializer = element.constantInitializer;
-      if (initializer != null) {
-        initializer.accept(this);
-      }
+    if (element is ConstFieldElementImpl && element.isEnumConstant) {
+      _applyToEnumConstantInitializer(element);
+    } else if (element is ConstVariableElement) {
+      element.constantInitializer?.accept(this);
     }
   }
 
@@ -1755,6 +1736,16 @@
       element.nameOffset = identifier.offset;
     }
   }
+
+  void _applyToEnumConstantInitializer(ConstFieldElementImpl element) {
+    var initializer = element.constantInitializer;
+    if (initializer is InstanceCreationExpression) {
+      initializer.constructorName.type2.typeArguments?.accept(this);
+      for (var argument in initializer.argumentList.arguments) {
+        argument.accept(this);
+      }
+    }
+  }
 }
 
 abstract class _OffsetsAstVisitor extends RecursiveAstVisitor<void> {
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index f389647..aa57e1e 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -20,6 +20,22 @@
 import 'package:analyzer/src/summary2/scope.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
 
+class ImplicitEnumNodes {
+  final EnumElementImpl element;
+  final FieldElementImpl indexField;
+  final ast.NamedTypeImpl valuesTypeNode;
+  final ConstFieldElementImpl valuesField;
+  final MethodElementImpl? syntheticToStringMethod;
+
+  ImplicitEnumNodes({
+    required this.element,
+    required this.indexField,
+    required this.valuesTypeNode,
+    required this.valuesField,
+    required this.syntheticToStringMethod,
+  });
+}
+
 class LibraryBuilder {
   final Linker linker;
   final Uri uri;
@@ -27,6 +43,8 @@
   final LibraryElementImpl element;
   final List<LinkingUnit> units;
 
+  final List<ImplicitEnumNodes> implicitEnumNodes = [];
+
   /// Local declarations.
   final Scope localScope = Scope.top();
 
@@ -114,7 +132,19 @@
   }
 
   void buildEnumChildren() {
-    ElementBuilder.buildEnumChildren(linker, element);
+    var typeProvider = element.typeProvider;
+    for (var enum_ in implicitEnumNodes) {
+      enum_.indexField.type = typeProvider.intType;
+      var valuesType = typeProvider.listType(
+        element.typeSystem.instantiateToBounds2(
+          classElement: enum_.element,
+          nullabilitySuffix: typeProvider.objectType.nullabilitySuffix,
+        ),
+      );
+      enum_.valuesTypeNode.type = valuesType;
+      enum_.valuesField.type = valuesType;
+      enum_.syntheticToStringMethod?.returnType = typeProvider.stringType;
+    }
   }
 
   void buildInitialExportScope() {
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index cf733cc..4526d92 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -88,8 +88,8 @@
   void _buildOutlines() {
     _computeLibraryScopes();
     _createTypeSystem();
-    _buildEnumChildren();
     _resolveTypes();
+    _buildEnumChildren();
     SuperConstructorResolver(this).perform();
     _performTopLevelInference();
     _resolveConstructors();
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index b91377d..21183bd 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -13,7 +13,7 @@
 
 class LinkedElementFactory {
   final AnalysisContextImpl analysisContext;
-  final AnalysisSessionImpl analysisSession;
+  AnalysisSessionImpl analysisSession;
   final Reference rootReference;
   final Map<String, LibraryReader> _libraryReaders = {};
   final Map<String, List<Reference>> _exportsOfLibrary = {};
@@ -165,13 +165,6 @@
     return _libraryReaders[uriStr] != null;
   }
 
-  /// We are about to discard this factory, mark all libraries invalid.
-  void invalidateAllLibraries() {
-    for (var libraryReference in rootReference.children) {
-      _invalidateLibrary(libraryReference);
-    }
-  }
-
   LibraryElementImpl? libraryOfUri(String uriStr) {
     var reference = rootReference.getChild(uriStr);
     return elementOfReference(reference) as LibraryElementImpl?;
@@ -204,8 +197,7 @@
     for (var uriStr in uriStrSet) {
       _exportsOfLibrary.remove(uriStr);
       _libraryReaders.remove(uriStr);
-      var libraryReference = rootReference.removeChild(uriStr);
-      _invalidateLibrary(libraryReference);
+      rootReference.removeChild(uriStr);
     }
 
     analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
@@ -230,6 +222,16 @@
     }
   }
 
+  void replaceAnalysisSession(AnalysisSessionImpl newSession) {
+    analysisSession = newSession;
+    for (var libraryReference in rootReference.children) {
+      var libraryElement = libraryReference.element;
+      if (libraryElement is LibraryElementImpl) {
+        libraryElement.session = newSession;
+      }
+    }
+  }
+
   /// Set exports of the library with [uriStr], after building exports during
   /// linking, or after reading a linked bundle.
   void setExportsOfLibrary(String uriStr, List<Reference> exports) {
@@ -255,11 +257,4 @@
 
     libraryElement.createLoadLibraryFunction();
   }
-
-  void _invalidateLibrary(Reference? libraryReference) {
-    var libraryElement = libraryReference?.element;
-    if (libraryElement is LibraryElementImpl) {
-      libraryElement.isValid = false;
-    }
-  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index 286730c..63659bb7 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -28,7 +28,7 @@
   void visitAnnotation(covariant AnnotationImpl node) {
     var annotationElement = node.elementAnnotation;
     if (annotationElement is ElementAnnotationImpl) {
-      var astResolver = AstResolver(_linker, _unitElement, _scope, node);
+      var astResolver = AstResolver(_linker, _unitElement, _scope);
       astResolver.resolveAnnotation(node);
       annotationElement.element = node.element;
     }
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 4208e83..dd5b4cc 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -114,7 +114,27 @@
   }
 
   @override
-  void visitEnumDeclaration(EnumDeclaration node) {}
+  void visitEnumDeclaration(EnumDeclaration node) {
+    var outerScope = scope;
+
+    var element = node.declaredElement as EnumElementImpl;
+
+    scope = TypeParameterScope(scope, element.typeParameters);
+
+    node.typeParameters?.accept(this);
+    // TODO(scheglov) implement
+    // node.extendsClause?.accept(this);
+    // node.implementsClause?.accept(this);
+    // node.withClause?.accept(this);
+
+    scope = ClassScope(scope, element);
+    LinkingNodeContext(node, scope);
+
+    node.members.accept(this);
+    nodesToBuildType.addDeclaration(node);
+
+    scope = outerScope;
+  }
 
   @override
   void visitExpressionFunctionBody(ExpressionFunctionBody node) {}
diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
index cc9870c..0fe77da 100644
--- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart
+++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
@@ -21,6 +21,10 @@
         var node = walker.getNode(element);
         nodes.add(node);
       }
+      for (var element in unit.enums) {
+        var node = walker.getNode(element);
+        nodes.add(node);
+      }
       for (var element in unit.mixins) {
         var node = walker.getNode(element);
         nodes.add(node);
@@ -43,6 +47,9 @@
     } else if (node2 is ClassTypeAlias) {
       var element = node2.declaredElement as ClassElementImpl;
       element.isSimplyBounded = node.isSimplyBounded;
+    } else if (node2 is EnumDeclaration) {
+      var element = node2.declaredElement as EnumElementImpl;
+      element.isSimplyBounded = node.isSimplyBounded;
     } else if (node2 is GenericTypeAlias) {
       var element = node2.declaredElement as TypeAliasElementImpl;
       element.isSimplyBounded = node.isSimplyBounded;
@@ -95,6 +102,14 @@
           parameters ?? const <TypeParameter>[],
           const <TypeAnnotation>[],
         );
+      } else if (node is EnumDeclaration) {
+        var parameters = node.typeParameters?.typeParameters;
+        graphNode = SimplyBoundedNode(
+          this,
+          node,
+          parameters ?? const <TypeParameter>[],
+          const <TypeAnnotation>[],
+        );
       } else if (node is FunctionTypeAlias) {
         var parameters = node.typeParameters?.typeParameters;
         graphNode = SimplyBoundedNode(
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 714e348..004c65b 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -43,6 +43,7 @@
       for (var unit in _library.units) {
         _unitElement = unit as CompilationUnitElementImpl;
         unit.classes.forEach(_resolveClassFields);
+        unit.enums.forEach(_resolveClassFields);
         unit.extensions.forEach(_resolveExtensionFields);
         unit.mixins.forEach(_resolveClassFields);
 
@@ -74,9 +75,9 @@
 
   void _resolveVariable(PropertyInducingElement element) {
     element as PropertyInducingElementImpl;
-    if (element.isSynthetic) return;
 
-    var variable = linker.getLinkingNode(element) as VariableDeclaration;
+    var variable = linker.getLinkingNode(element);
+    if (variable is! VariableDeclaration) return;
     if (variable.initializer == null) return;
 
     var declarationList = variable.parent as VariableDeclarationList;
@@ -93,8 +94,7 @@
 
     if (declarationList.isConst ||
         declarationList.isFinal && _enclosingClassHasConstConstructor) {
-      var astResolver =
-          AstResolver(linker, _unitElement, _scope, variable.initializer!);
+      var astResolver = AstResolver(linker, _unitElement, _scope);
       astResolver.resolveExpression(() => variable.initializer!,
           contextType: contextType);
     }
@@ -290,7 +290,7 @@
 
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
-    var element = node.staticElement;
+    var element = node.staticElement?.declaration;
     if (element is PropertyAccessorElement && element.isGetter) {
       _set.add(element.variable);
     }
@@ -351,6 +351,7 @@
         _unitElement = unit as CompilationUnitElementImpl;
         unit.classes.forEach(_addClassConstructorFieldFormals);
         unit.classes.forEach(_addClassElementFields);
+        unit.enums.forEach(_addClassElementFields);
         unit.extensions.forEach(_addExtensionElementFields);
         unit.mixins.forEach(_addClassElementFields);
 
@@ -390,6 +391,7 @@
   }
 
   void _addVariableNode(PropertyInducingElement element) {
+    element as PropertyInducingElementImpl;
     if (element.isSynthetic) return;
 
     var node = _linker.getLinkingNode(element) as VariableDeclaration;
@@ -402,10 +404,10 @@
       var inferenceNode =
           _VariableInferenceNode(_walker, _unitElement, _scope, element, node);
       _walker._nodes[element] = inferenceNode;
-      (element as PropertyInducingElementImpl).typeInference =
+      element.typeInference =
           _PropertyInducingElementTypeInference(inferenceNode);
     } else {
-      (element as PropertyInducingElementImpl).type = DynamicTypeImpl.instance;
+      element.type = DynamicTypeImpl.instance;
     }
   }
 }
@@ -437,7 +439,7 @@
   final CompilationUnitElementImpl _unitElement;
   final TypeSystemImpl _typeSystem;
   final Scope _scope;
-  final PropertyInducingElement _element;
+  final PropertyInducingElementImpl _element;
   final VariableDeclaration _node;
 
   @override
@@ -456,13 +458,9 @@
     return _node.name.name;
   }
 
-  PropertyInducingElementImpl get _elementImpl {
-    return _node.declaredElement as PropertyInducingElementImpl;
-  }
-
   @override
   List<_InferenceNode> computeDependencies() {
-    if (_elementImpl.hasTypeInferred) {
+    if (_element.hasTypeInferred) {
       return const <_InferenceNode>[];
     }
 
@@ -480,7 +478,7 @@
 
   @override
   void evaluate() {
-    if (_elementImpl.hasTypeInferred) {
+    if (_element.hasTypeInferred) {
       return;
     }
 
@@ -488,23 +486,23 @@
 
     var initializerType = _node.initializer!.typeOrThrow;
     initializerType = _refineType(initializerType);
-    _elementImpl.type = initializerType;
-    _elementImpl.hasTypeInferred = true;
+    _element.type = initializerType;
+    _element.hasTypeInferred = true;
 
     isEvaluated = true;
   }
 
   @override
   void markCircular(List<_InferenceNode> cycle) {
-    _elementImpl.type = DynamicTypeImpl.instance;
-    _elementImpl.hasTypeInferred = true;
+    _element.type = DynamicTypeImpl.instance;
+    _element.hasTypeInferred = true;
 
     var cycleNames = <String>{};
     for (var inferenceNode in cycle) {
       cycleNames.add(inferenceNode.displayName);
     }
 
-    _elementImpl.typeInferenceError = TopLevelInferenceError(
+    _element.typeInferenceError = TopLevelInferenceError(
       kind: TopLevelInferenceErrorKind.dependencyCycle,
       arguments: cycleNames.toList(),
     );
@@ -531,8 +529,7 @@
     var enclosingElement = _element.enclosingElement;
     var enclosingClassElement =
         enclosingElement is ClassElement ? enclosingElement : null;
-    var astResolver = AstResolver(
-        _walker._linker, _unitElement, _scope, _node.initializer!,
+    var astResolver = AstResolver(_walker._linker, _unitElement, _scope,
         enclosingClassElement: enclosingClassElement);
     astResolver.resolveExpression(() => _node.initializer!,
         buildElements: forDependencies);
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index 53b27e3..795d229 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -167,6 +167,8 @@
       _classDeclaration(node);
     } else if (node is ClassTypeAlias) {
       _classTypeAlias(node);
+    } else if (node is EnumDeclaration) {
+      _enumDeclaration(node);
     } else if (node is ExtensionDeclaration) {
       _extensionDeclaration(node);
     } else if (node is FieldFormalParameter) {
@@ -220,6 +222,10 @@
     }
   }
 
+  void _enumDeclaration(EnumDeclaration node) {
+    // TODO(scheglov) implement
+  }
+
   void _extensionDeclaration(ExtensionDeclaration node) {
     var element = node.declaredElement as ExtensionElementImpl;
     element.extendedType = node.extendedType.typeOrThrow;
diff --git a/pkg/analyzer/lib/src/summary2/variance_builder.dart b/pkg/analyzer/lib/src/summary2/variance_builder.dart
index c9017ca..fad5a0e 100644
--- a/pkg/analyzer/lib/src/summary2/variance_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/variance_builder.dart
@@ -39,6 +39,8 @@
             _typeParameters(node.typeParameters);
           } else if (node is ClassDeclaration) {
             _typeParameters(node.typeParameters);
+          } else if (node is EnumDeclaration) {
+            _typeParameters(node.typeParameters);
           } else if (node is FunctionTypeAlias) {
             _functionTypeAlias(node);
           } else if (node is GenericTypeAlias) {
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 8a894ec..7159665 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -172,31 +172,31 @@
       }
     }
 
+    void findInClasses(List<ClassElement> classes) {
+      for (var class_ in classes) {
+        findInExecutables(class_.accessors);
+        findInExecutables(class_.constructors);
+        findInExecutables(class_.methods);
+      }
+    }
+
     findInExecutables(unitElement.accessors);
     findInExecutables(unitElement.functions);
 
-    for (var alias in unitElement.typeAliases) {
-      var aliasedElement = alias.aliasedElement;
-      if (aliasedElement is GenericFunctionTypeElement) {
-        findIn(aliasedElement.parameters);
-      }
-    }
+    findInClasses(unitElement.classes);
+    findInClasses(unitElement.enums);
+    findInClasses(unitElement.mixins);
 
     for (var extension_ in unitElement.extensions) {
       findInExecutables(extension_.accessors);
       findInExecutables(extension_.methods);
     }
 
-    for (var mixin in unitElement.mixins) {
-      findInExecutables(mixin.accessors);
-      findInExecutables(mixin.constructors);
-      findInExecutables(mixin.methods);
-    }
-
-    for (var class_ in unitElement.classes) {
-      findInExecutables(class_.accessors);
-      findInExecutables(class_.constructors);
-      findInExecutables(class_.methods);
+    for (var alias in unitElement.typeAliases) {
+      var aliasedElement = alias.aliasedElement;
+      if (aliasedElement is GenericFunctionTypeElement) {
+        findIn(aliasedElement.parameters);
+      }
     }
 
     unit.accept(
@@ -285,6 +285,10 @@
       findInClass(class_);
     }
 
+    for (var enum_ in unitElement.enums) {
+      findInClass(enum_);
+    }
+
     for (var extension_ in unitElement.extensions) {
       findIn(extension_.typeParameters);
     }
@@ -351,21 +355,34 @@
 
   ConstructorElement constructor(String name, {String? of}) {
     assert(name != '');
+
     ConstructorElement? result;
-    for (var class_ in unitElement.classes) {
-      if (of == null || class_.name == of) {
-        for (var constructor in class_.constructors) {
-          if (constructor.name == name) {
-            if (result != null) {
-              throw StateError('Not unique: $name');
-            }
-            result = constructor;
+
+    void findIn(List<ConstructorElement> constructors) {
+      for (var constructor in constructors) {
+        if (constructor.name == name) {
+          if (result != null) {
+            throw StateError('Not unique: $name');
           }
+          result = constructor;
         }
       }
     }
+
+    for (var class_ in unitElement.classes) {
+      if (of == null || class_.name == of) {
+        findIn(class_.constructors);
+      }
+    }
+
+    for (var enum_ in unitElement.enums) {
+      if (of == null || enum_.name == of) {
+        findIn(enum_.constructors);
+      }
+    }
+
     if (result != null) {
-      return result;
+      return result!;
     }
     throw StateError('Not found: $name');
   }
@@ -498,13 +515,6 @@
       }
     }
 
-    for (var extension_ in unitElement.extensions) {
-      if (of != null && extension_.name != of) {
-        continue;
-      }
-      findIn(extension_.methods);
-    }
-
     for (var class_ in unitElement.classes) {
       if (of != null && class_.name != of) {
         continue;
@@ -512,6 +522,20 @@
       findIn(class_.methods);
     }
 
+    for (var enum_ in unitElement.enums) {
+      if (of != null && enum_.name != of) {
+        continue;
+      }
+      findIn(enum_.methods);
+    }
+
+    for (var extension_ in unitElement.extensions) {
+      if (of != null && extension_.name != of) {
+        continue;
+      }
+      findIn(extension_.methods);
+    }
+
     for (var mixin in unitElement.mixins) {
       if (of != null && mixin.name != of) {
         continue;
@@ -638,6 +662,15 @@
 }
 
 extension ExecutableElementExtensions on ExecutableElement {
+  ParameterElement parameter(String name) {
+    for (var parameter in parameters) {
+      if (parameter.name == name) {
+        return parameter;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
+
   SuperFormalParameterElement superFormalParameter(String name) {
     for (var parameter in parameters) {
       if (parameter is SuperFormalParameterElement && parameter.name == name) {
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index 84ee9ef..9c4b72b 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -6,6 +6,33 @@
 
 /// Helper for creating mock packages.
 class MockPackages {
+  /// Create a fake 'ffi' package that can be used by tests.
+  static void addFfiPackageFiles(Folder rootFolder) {
+    var libFolder = rootFolder.getChildAssumingFolder('lib');
+    libFolder.getChildAssumingFile('ffi.dart').writeAsStringSync(r'''
+import 'dart:ffi';
+
+const Allocator calloc = _CallocAllocator();
+
+abstract class Allocator {
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment});
+
+  void free(Pointer pointer);
+}
+
+class Utf8 extends Opaque {}
+
+class _CallocAllocator implements Allocator {
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment})
+      => throw '';
+
+  @override
+  void free(Pointer pointer) => throw '';
+}
+''');
+  }
+
   /// Create a fake 'js' package that can be used by tests.
   static void addJsPackageFiles(Folder rootFolder) {
     var libFolder = rootFolder.getChildAssumingFolder('lib');
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 44a6369..84784c3 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -66,6 +66,9 @@
 }
 
 abstract class Timer {
+  factory Timer(Duration duration, void Function() callback) {
+    throw 0;
+  }
   static void run(void callback()) {}
 }
 ''',
@@ -659,6 +662,8 @@
 
 class Handle extends NativeType {}
 
+abstract class Opaque extends NativeType {}
+
 class Void extends NativeType {}
 
 class Int8 extends NativeType {
@@ -833,6 +838,9 @@
   const AbiSpecificIntegerMapping(this.mapping);
 }
 
+abstract class Finalizable {
+  factory Finalizable._() => throw UnsupportedError("");
+}
 ''',
   )
 ]);
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index b079038..d791d4c 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -3203,9 +3203,10 @@
     documentation: |-
       #### Description
 
-      The analyzer produces this diagnostic when there's more than one field
-      formal parameter for the same field in a constructor's parameter list. It
-      isn't useful to assign a value that will immediately be overwritten.
+      The analyzer produces this diagnostic when there's more than one
+      initializing formal parameter for the same field in a constructor's
+      parameter list. It isn't useful to assign a value that will immediately be
+      overwritten.
 
       #### Example
 
@@ -3222,7 +3223,7 @@
 
       #### Common fixes
 
-      Remove one of the field formal parameters:
+      Remove one of the initializing formal parameters:
 
       ```dart
       class C {
@@ -3971,13 +3972,16 @@
       If there are multiple cascaded accesses, you'll need to duplicate the
       extension override for each one.
   EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER:
-    problemMessage: External fields cannot have initializers.
+    sharedName: EXTERNAL_WITH_INITIALIZER
+    problemMessage: External fields can't have initializers.
     correctionMessage: "Try removing the field initializer or the 'external' keyword from the field declaration."
   EXTERNAL_FIELD_INITIALIZER:
-    problemMessage: External fields cannot have initializers.
+    sharedName: EXTERNAL_WITH_INITIALIZER
+    problemMessage: External fields can't have initializers.
     correctionMessage: "Try removing the initializer or the 'external' keyword."
   EXTERNAL_VARIABLE_INITIALIZER:
-    problemMessage: External variables cannot have initializers.
+    sharedName: EXTERNAL_WITH_INITIALIZER
+    problemMessage: External variables can't have initializers.
     correctionMessage: "Try removing the initializer or the 'external' keyword."
   EXTRA_POSITIONAL_ARGUMENTS:
     problemMessage: "Too many positional arguments: {0} expected, but {1} found."
@@ -4166,7 +4170,8 @@
       #### Example
 
       The following code produces this diagnostic because the field `f` is
-      initialized both by a field formal parameter and in the initializer list:
+      initialized both by an initializing formal parameter and in the
+      initializer list:
 
       ```dart
       class C {
@@ -4218,14 +4223,14 @@
     documentation: |-
       #### Description
 
-      The analyzer produces this diagnostic when a factory constructor has a
-      field formal parameter. Factory constructors can't assign values to fields
-      because no instance is created; hence, there is no field to assign.
+      The analyzer produces this diagnostic when a factory constructor has an
+      initializing formal parameter. Factory constructors can't assign values to
+      fields because no instance is created; hence, there is no field to assign.
 
       #### Example
 
       The following code produces this diagnostic because the factory constructor
-      uses a field formal parameter:
+      uses an initializing formal parameter:
 
       ```dart
       class C {
@@ -4237,7 +4242,7 @@
 
       #### Common fixes
 
-      Replace the field formal parameter with a normal parameter:
+      Replace the initializing formal parameter with a normal parameter:
 
       ```dart
       class C {
@@ -4328,8 +4333,8 @@
       #### Examples
 
       The following code produces this diagnostic because the constructor
-      `C.zero`, which redirects to the constructor `C`, has a field formal
-      parameter that initializes the field `f`:
+      `C.zero`, which redirects to the constructor `C`, has an initializing
+      formal parameter that initializes the field `f`:
 
       ```dart
       class C {
@@ -4357,8 +4362,8 @@
 
       #### Common fixes
 
-      If the initialization is done by a field formal parameter, then use a
-      normal parameter:
+      If the initialization is done by an initializing formal parameter, then
+      use a normal parameter:
 
       ```dart
       class C {
@@ -4393,14 +4398,16 @@
     documentation: |-
       #### Description
 
-      The analyzer produces this diagnostic when the type of a field formal
-      parameter isn't assignable to the type of the field being initialized.
+      The analyzer produces this diagnostic when the type of an initializing
+      formal parameter isn't assignable to the type of the field being
+      initialized.
 
       #### Example
 
-      The following code produces this diagnostic because the field formal
-      parameter has the type `String`, but the type of the field is `int`. The
-      parameter must have a type that is a subtype of the field's type.
+      The following code produces this diagnostic because the initializing
+      formal parameter has the type `String`, but the type of the field is
+      `int`. The parameter must have a type that is a subtype of the field's
+      type.
 
       ```dart
       class C {
@@ -4436,8 +4443,8 @@
       ```
 
       If the types of both the field and the parameter are correct, then use an
-      initializer rather than a field formal parameter to convert the parameter
-      value into a value of the correct type:
+      initializer rather than an initializing formal parameter to convert the
+      parameter value into a value of the correct type:
 
       ```dart
       class C {
@@ -4527,7 +4534,7 @@
 
       For instance fields, you can add an initializer as shown in the previous
       example, or you can initialize the field in every constructor. You can
-      initialize the field by using a field formal parameter:
+      initialize the field by using an initializing formal parameter:
 
       ```dart
       class C {
@@ -4576,8 +4583,8 @@
 
       #### Common fixes
 
-      If the value should be passed in to the constructor directly, then use a
-      field formal parameter to initialize the field `value`:
+      If the value should be passed in to the constructor directly, then use an
+      initializing formal parameter to initialize the field `value`:
 
       ```dart
       class C {
@@ -5185,6 +5192,12 @@
         int get defaultX => 0;
       }
       ```
+  IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT:
+    problemMessage: The named parameter '{0}' is required in the implicitly invoked unnamed constructor of '{1}'.
+    correctionMessage: Try declaring corresponding named super-parameter, or explicitly invoking a different constructor.
+  IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS:
+    problemMessage: The implicitly invoked unnamed constructor of '{0}' expects {1} positional arguments, but {2} found.
+    correctionMessage: Try declaring positional super-parameters, or explicitly invoking a different constructor.
   IMPORT_INTERNAL_LIBRARY:
     problemMessage: "The library '{0}' is internal and can't be imported."
     hasPublishedDocs: true
@@ -5371,14 +5384,14 @@
     documentation: |-
       #### Description
 
-      The analyzer produces this diagnostic when a static field is initialized in
-      a constructor using either a field formal parameter or an assignment in the
-      initializer list.
+      The analyzer produces this diagnostic when a static field is initialized
+      in a constructor using either an initializing formal parameter or an
+      assignment in the initializer list.
 
       #### Example
 
-      The following code produces this diagnostic because the static field `a` is
-      being initialized by the field formal parameter `this.a`:
+      The following code produces this diagnostic because the static field `a`
+      is being initialized by the initializing formal parameter `this.a`:
 
       ```dart
       class C {
@@ -5431,10 +5444,10 @@
     documentation: |-
       #### Description
 
-      The analyzer produces this diagnostic when a field formal parameter is
-      found in a constructor in a class that doesn't declare the field being
-      initialized. Constructors can't initialize fields that aren't declared and
-      fields that are inherited from superclasses.
+      The analyzer produces this diagnostic when an initializing formal
+      parameter is found in a constructor in a class that doesn't declare the
+      field being initialized. Constructors can't initialize fields that aren't
+      declared and fields that are inherited from superclasses.
 
       #### Example
 
@@ -6067,7 +6080,7 @@
       0: the type of the list literal
       1: the expected type
   INVALID_CAST_LITERAL_MAP:
-    problemMessage: "The map literal type '{0}' isn't of expected type '{1}'. The maps's type can be changed with an explicit generic type arguments or by changing the key and value types."
+    problemMessage: "The map literal type '{0}' isn't of expected type '{1}'. The map's type can be changed with an explicit generic type arguments or by changing the key and value types."
     comment: |-
       Parameters:
       0: the type of the map literal
@@ -6098,11 +6111,6 @@
       for more informative errors.
 
       See TODOs in ConstantVisitor
-  INVALID_CONSTRUCTOR_NAME:
-    problemMessage: Invalid constructor name.
-    comment: |-
-      7.6 Constructors: It is a compile-time error if the name of a constructor
-      is not a constructor name.
   INVALID_EXTENSION_ARGUMENT_COUNT:
     problemMessage: "Extension overrides must have exactly one argument: the value of 'this' in the extension method."
     correctionMessage: Try specifying exactly one argument.
@@ -6526,6 +6534,12 @@
 
       class C {}
       ```
+  INVALID_SUPER_FORMAL_PARAMETER_LOCATION:
+    problemMessage: "Super-formal parameters can only be used in non-redirecting generative constructors."
+    comment: |-
+      Parameters:
+      0: the super modifier
+    correctionMessage: Try removing the 'super' modifier, or changing the constructor to be non-redirecting and generative.
   INVALID_TYPE_ARGUMENT_IN_CONST_LIST:
     sharedName: INVALID_TYPE_ARGUMENT_IN_CONST_LITERAL
     problemMessage: "Constant list literals can't include a type parameter as a type argument, such as '{0}'."
@@ -7290,17 +7304,26 @@
       var m = <String, int>{'a' : 2};
       ```
   MISSING_CONST_IN_LIST_LITERAL:
-    problemMessage: "List literals must be prefixed with 'const' when used as a constant expression."
-    correctionMessage: "Try adding the keyword 'const' before the literal."
-    comment: "12.1 Constants: A constant expression is ... a constant list literal."
+    problemMessage: Seeing this message constitutes a bug. Please report it.
+    comment: |-
+      12.1 Constants: A constant expression is ... a constant list literal.
+      
+      Note: This diagnostic is never displayed to the user, so it doesn't need
+      to be documented.
   MISSING_CONST_IN_MAP_LITERAL:
-    problemMessage: "Map literals must be prefixed with 'const' when used as a constant expression."
-    correctionMessage: "Try adding the keyword 'const' before the literal."
-    comment: "12.1 Constants: A constant expression is ... a constant map literal."
+    problemMessage: Seeing this message constitutes a bug. Please report it.
+    comment: |-
+      12.1 Constants: A constant expression is ... a constant map literal.
+
+      Note: This diagnostic is never displayed to the user, so it doesn't need
+      to be documented.
   MISSING_CONST_IN_SET_LITERAL:
-    problemMessage: "Set literals must be prefixed with 'const' when used as a constant expression."
-    correctionMessage: "Try adding the keyword 'const' before the literal."
-    comment: "12.1 Constants: A constant expression is ... a constant set literal."
+    problemMessage: Seeing this message constitutes a bug. Please report it.
+    comment: |-
+      12.1 Constants: A constant expression is ... a constant set literal.
+
+      Note: This diagnostic is never displayed to the user, so it doesn't need
+      to be documented.
   MISSING_DART_LIBRARY:
     problemMessage: "Required library '{0}' is missing."
     correctionMessage: Re-install the Dart or Flutter SDK.
@@ -7369,6 +7392,12 @@
       void f(int x) {}
       void g({required int x}) {}
       ```
+  MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION:
+    sharedName: MISSING_DEFAULT_VALUE_FOR_PARAMETER
+    problemMessage: "With null safety, use the 'required' keyword, not the '@required' annotation."
+    correctionMessage: "Try removing the '@'."
+    hasPublishedDocs: true
+    comment: No parameters.
   MISSING_REQUIRED_ARGUMENT:
     problemMessage: "The named parameter '{0}' is required, but there's no corresponding argument."
     correctionMessage: Try adding the required argument.
@@ -7689,17 +7718,6 @@
 
       class B extends A {}
       ```
-  MIXIN_DECLARES_CONSTRUCTOR:
-    problemMessage: "Mixins can't declare constructors."
-    comment: |-
-      The <i>mixinMember</i> production allows the same instance or static
-      members that a class would allow, but no constructors (for now).
-  MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES:
-    problemMessage: "Type parameters couldn't be inferred for the mixin '{0}' because the base class implements the mixin's supertype constraint '{1}' in multiple conflicting ways"
-  MIXIN_INFERENCE_NO_MATCHING_CLASS:
-    problemMessage: "Type parameters couldn't be inferred for the mixin '{0}' because the base class doesn't implement the mixin's supertype constraint '{1}'"
-  MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION:
-    problemMessage: "Type parameters couldn't be inferred for the mixin '{0}' because no type parameter substitution could be found matching the mixin's supertype constraints"
   MIXIN_INHERITS_FROM_NOT_OBJECT:
     problemMessage: "The class '{0}' can't be used as a mixin because it extends a class other than 'Object'."
     hasPublishedDocs: true
@@ -9860,6 +9878,10 @@
       ```dart
       part of 'test.dart';
       ```
+  POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT:
+    problemMessage: Positional super-formal parameters can't be used when the super-constructor invocation has a positional argument.
+    comment: No parameters.
+    correctionMessage: Try removing the 'super' modifier, or changing the super-constructor to use named parameters.
   PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER:
     problemMessage: "The name '{0}' is already used as an import prefix and can't be used to name a top-level element."
     correctionMessage: Try renaming either the top-level element or the prefix.
@@ -11092,6 +11114,21 @@
 
       int f(C c) => c.b;
       ```
+  SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED:
+    problemMessage: The type '{0}' of this parameter is not a subtype of the type '{1}' of the associated super-constructor parameter.
+    comment: |-
+      Parameters:
+      0: the type of super-parameter
+      1: the type of associated super-constructor parameter
+    correctionMessage: Try removing the explicit type annotation from the parameter.
+  SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED:
+    problemMessage: No associated named super-constructor parameter.
+    comment: No parameters.
+    correctionMessage: Try changing the name to the name of an existing named super-constructor parameter, or creating such named parameter.
+  SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL:
+    problemMessage: No associated positional super-constructor parameter.
+    comment: No parameters.
+    correctionMessage: Try using named parameters instead, or adding more positional parameters to the super-constructor.
   IMPLEMENTS_DEFERRED_CLASS:
     sharedName: SUBTYPE_OF_DEFERRED_CLASS
     problemMessage: "Classes and mixins can't implement deferred classes."
@@ -13794,34 +13831,286 @@
     correctionMessage: Try changing the value to 'Int8', 'Int16', 'Int32', 'Int64', 'Uint8', 'Uint16', 'UInt32', or 'Uint64'.
     comment: No parameters.
   ANNOTATION_ON_POINTER_FIELD:
-    problemMessage: "Fields in a struct class whose type is 'Pointer' should not have any annotations."
+    problemMessage: "Fields in a struct class whose type is 'Pointer' shouldn't have any annotations."
     correctionMessage: Try removing the annotation.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field that's declared in a
+      subclass of `Struct` and has the type `Pointer` also has an annotation
+      associated with it.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `p`, which
+      has the type `Pointer` and is declared in a subclass of `Struct`, has the
+      annotation `@Double()`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        [!@Double()!]
+        external Pointer<Int8> p;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove the annotations from the field:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        external Pointer<Int8> p;
+      }
+      ```
   ARGUMENT_MUST_BE_A_CONSTANT:
     problemMessage: "Argument '{0}' must be a constant."
     correctionMessage: Try replacing the value with a literal or const.
     comment: |-
       Parameters:
       0: the name of the argument
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when an invocation of either
+      `Pointer.asFunction` or `DynamicLibrary.lookupFunction` has an `isLeaf`
+      argument whose value isn't a constant expression.
+
+      The analyzer also produces this diagnostic when the value of the
+      `exceptionalReturn` argument of `Pointer.fromFunction`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the value of the
+      `isLeaf` argument is a parameter, and hence isn't a constant:
+
+      ```dart
+      import 'dart:ffi';
+
+      int Function(int) fromPointer(
+          Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
+        return p.asFunction(isLeaf: [!isLeaf!]);
+      }
+      ```
+
+      #### Common fixes
+
+      If there's a suitable constant that can be used, then replace the argument
+      with a constant:
+
+      ```dart
+      import 'dart:ffi';
+
+      const isLeaf = false;
+
+      int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+        return p.asFunction(isLeaf: isLeaf);
+      }
+      ```
+
+      If there isn't a suitable constant, then replace the argument with a
+      boolean literal:
+
+      ```dart
+      import 'dart:ffi';
+
+      int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+        return p.asFunction(isLeaf: true);
+      }
+      ```
   CREATION_OF_STRUCT_OR_UNION:
     problemMessage: "Subclasses of 'Struct' and 'Union' are backed by native memory, and can't be instantiated by a generative constructor."
     correctionMessage: "Try allocating it via allocation, or load from a 'Pointer'."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a subclass of either `Struct`
+      or `Union` is instantiated using a generative constructor.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C` is being
+      instantiated using a generative constructor:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        external int a;
+      }
+
+      void f() {
+        [!C!]();
+      }
+      ```
+
+      #### Common fixes
+
+      If you need to allocate the structure described by the class, then use the
+      `ffi` package to do so:
+
+      ```dart
+      import 'dart:ffi';
+      import 'package:ffi/ffi.dart';
+
+      class C extends Struct {
+        @Int32()
+        external int a;
+      }
+
+      void f() {
+        final pointer = calloc.allocate<C>(4);
+        final c = pointer.ref;
+        print(c);
+        calloc.free(pointer);
+      }
+      ```
   EMPTY_STRUCT:
-    problemMessage: "The class '{0}' can’t be empty because it's a subclass of '{1}'."
+    problemMessage: "The class '{0}' can't be empty because it's a subclass of '{1}'."
     correctionMessage: "Try adding a field to '{0}' or use a different superclass."
     comment: |-
       Parameters:
       0: the name of the subclass
       1: the name of the superclass
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a subclass of `Struct` or
+      `Union` doesn't have any fields. Having an empty `Struct` or `Union`
+      isn't supported.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C`, which
+      extends `Struct`, doesn't declare any fields:
+
+      ```dart
+      import 'dart:ffi';
+
+      class [!C!] extends Struct {}
+      ```
+
+      #### Common fixes
+
+      If the class is intended to be a struct, then declare one or more fields:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        external int x;
+      }
+      ```
+
+      If the class is intended to be used as a type argument to `Pointer`, then
+      make it a subclass of `Opaque`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Opaque {}
+      ```
+
+      If the class isn't intended to be a struct, then remove or change the
+      extends clause:
+
+      ```dart
+      class C {}
+      ```
   EXTRA_ANNOTATION_ON_STRUCT_FIELD:
     problemMessage: Fields in a struct class must have exactly one annotation indicating the native type.
     correctionMessage: Try removing the extra annotation.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` has more than one annotation describing the native type of the
+      field.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `x` has two
+      annotations describing the native type of the field:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        [!@Int16()!]
+        external int x;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove all but one of the annotations:
+
+      ```dart
+      import 'dart:ffi';
+      class C extends Struct {
+        @Int32()
+        external int x;
+      }
+      ```
   EXTRA_SIZE_ANNOTATION_CARRAY:
     problemMessage: "'Array's must have exactly one 'Array' annotation."
     correctionMessage: Try removing the extra annotation.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` has more than one annotation describing the size of the native
+      array.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `a0` has two
+      annotations that specify the size of the native array:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(4)
+        [!@Array(8)!]
+        external Array<Uint8> a0;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove all but one of the annotations:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8)
+        external Array<Uint8> a0;
+      }
+      ```
   FFI_NATIVE_MUST_BE_EXTERNAL:
     problemMessage: FfiNative functions must be declared external.
     correctionMessage: Add the `external` keyword to the function.
@@ -13848,60 +14137,576 @@
     problemMessage: "Constructors in subclasses of 'Struct' and 'Union' can't have field initializers."
     correctionMessage: Try removing the field initializer and marking the field as external.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a constructor in a subclass of
+      either `Struct` or `Union` has one or more field initializers.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C` has a
+      constructor with an initializer for the field `f`:
+
+      ```dart
+      // @dart = 2.9
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        int f;
+
+        C() : [!f = 0!];
+      }
+      ```
+
+      #### Common fixes
+
+      Remove the field initializer:
+
+      ```dart
+      // @dart = 2.9
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        int f;
+
+        C();
+      }
+      ```
   FIELD_IN_STRUCT_WITH_INITIALIZER:
     problemMessage: "Fields in subclasses of 'Struct' and 'Union' can't have initializers."
     correctionMessage: Try removing the initializer and marking the field as external.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` has an initializer.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `p` has an
+      initializer:
+
+      ```dart
+      // @dart = 2.9
+      import 'dart:ffi';
+
+      class C extends Struct {
+        Pointer [!p!] = nullptr;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove the initializer:
+
+      ```dart
+      // @dart = 2.9
+      import 'dart:ffi';
+
+      class C extends Struct {
+        Pointer p;
+      }
+      ```
   FIELD_MUST_BE_EXTERNAL_IN_STRUCT:
     problemMessage: "Fields of 'Struct' and 'Union' subclasses must be marked external."
     correctionMessage: "Try adding the 'external' modifier."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of either
+      `Struct` or `Union` isn't marked as being `external`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `a` isn't
+      marked as being `external`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int16()
+        int [!a!];
+      }
+      ```
+
+      #### Common fixes
+
+      Add the required `external` modifier:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int16()
+        external int a;
+      }
+      ```
   GENERIC_STRUCT_SUBCLASS:
-    problemMessage: "The class '{0}' can't extend 'Struct' or 'Union' because it is generic."
+    problemMessage: "The class '{0}' can't extend 'Struct' or 'Union' because '{0}' is generic."
     correctionMessage: "Try removing the type parameters from '{0}'."
     comment: |-
       Parameters:
       0: the name of the struct class
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a subclass of either `Struct`
+      or `Union` has a type parameter.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `S` defines
+      the type parameter `T`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class [!S!]<T> extends Struct {
+        external Pointer notEmpty;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove the type parameters from the class:
+
+      ```dart
+      import 'dart:ffi';
+
+      class S extends Struct {
+        external Pointer notEmpty;
+      }
+      ```
   INVALID_EXCEPTION_VALUE:
-    problemMessage: "The method 'Pointer.fromFunction' must not have an exceptional return value (the second argument) when the return type of the function is either 'void', 'Handle' or 'Pointer'."
+    problemMessage: "The method 'Pointer.fromFunction' can't have an exceptional return value (the second argument) when the return type of the function is either 'void', 'Handle' or 'Pointer'."
     correctionMessage: Try removing the exceptional return value.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when an invocation of the method
+      `Pointer.fromFunction` has a second argument (the exceptional return
+      value) and the type to be returned from the invocation is either `void`,
+      `Handle` or `Pointer`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because a second argument is
+      provided when the return type of `f` is `void`:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = Void Function(Int8);
+
+      void f(int i) {}
+
+      void g() {
+        Pointer.fromFunction<T>(f, [!42!]);
+      }
+      ```
+
+      #### Common fixes
+
+      Remove the exception value:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = Void Function(Int8);
+
+      void f(int i) {}
+
+      void g() {
+        Pointer.fromFunction<T>(f);
+      }
+      ```
   INVALID_FIELD_TYPE_IN_STRUCT:
     problemMessage: "Fields in struct classes can't have the type '{0}'. They can only be declared as 'int', 'double', 'Array', 'Pointer', or subtype of 'Struct' or 'Union'."
     correctionMessage: "Try using 'int', 'double', 'Array', 'Pointer', or subtype of 'Struct' or 'Union'."
     comment: |-
       Parameters:
       0: the type of the field
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` has a type other than `int`, `double`, `Array`, `Pointer`, or
+      subtype of `Struct` or `Union`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `str` has
+      the type `String`, which isn't one of the allowed types for fields in a
+      subclass of `Struct`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        external [!String!] s;
+
+        @Int32()
+        external int i;
+      }
+      ```
+
+      #### Common fixes
+
+      Use one of the allowed types for the field:
+
+      ```dart
+      import 'dart:ffi';
+      import 'package:ffi/ffi.dart';
+
+      class C extends Struct {
+        external Pointer<Utf8> s;
+
+        @Int32()
+        external int i;
+      }
+      ```
   LEAF_CALL_MUST_NOT_RETURN_HANDLE:
-    problemMessage: FFI leaf call must not return a Handle.
+    problemMessage: "FFI leaf call can't return a 'Handle'."
     correctionMessage: Try changing the return type to primitive or struct.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the value of the `isLeaf`
+      argument in an invocation of either `Pointer.asFunction` or
+      `DynamicLibrary.lookupFunction` is `true` and the function that would be
+      returned would have a return type of `Handle`.
+
+      The analyzer also produces this diagnostic when the value of the `isLeaf`
+      argument in an `FfiNative` annotation is `true` and the type argument on
+      the annotation is a function type whose return type is `Handle`.
+
+      In all of these cases, leaf calls are only supported for the types `bool`,
+      `int`, `float`, `double`, and, as a return type `void`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the function `p`
+      returns a `Handle`, but the `isLeaf` argument is `true`:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Handle Function()>> p) {
+        [!p.asFunction<Object Function()>(isLeaf: true)!];
+      }
+      ```
+
+      #### Common fixes
+
+      If the function returns a handle, then remove the `isLeaf` argument:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Handle Function()>> p) {
+        p.asFunction<Object Function()>();
+      }
+      ```
+
+      If the function returns one of the supported types, then correct the type
+      information:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Int32 Function()>> p) {
+        p.asFunction<int Function()>(isLeaf: true);
+      }
+      ```
   LEAF_CALL_MUST_NOT_TAKE_HANDLE:
-    problemMessage: FFI leaf call must not take arguments of type Handle.
+    problemMessage: "FFI leaf call can't take arguments of type 'Handle'."
     correctionMessage: Try changing the argument type to primitive or struct.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the value of the `isLeaf`
+      argument in an invocation of either `Pointer.asFunction` or
+      `DynamicLibrary.lookupFunction` is `true` and the function that would be
+      returned would have a parameter of type `Handle`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the function `p` has a
+      parameter of type `Handle`, but the `isLeaf` argument is `true`:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+        [!p.asFunction<void Function(Object)>(isLeaf: true)!];
+      }
+      ```
+
+      #### Common fixes
+
+      If the function has at least one parameter of type `Handle`, then remove
+      the `isLeaf` argument:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+        p.asFunction<void Function(Object)>();
+      }
+      ```
+
+      If none of the function's parameters are `Handle`s, then correct the type
+      information:
+
+      ```dart
+      import 'dart:ffi';
+
+      void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
+        p.asFunction<void Function(int)>(isLeaf: true);
+      }
+      ```
   MISMATCHED_ANNOTATION_ON_STRUCT_FIELD:
-    problemMessage: The annotation does not match the declared type of the field.
+    problemMessage: "The annotation doesn't match the declared type of the field."
     correctionMessage: Try using a different annotation or changing the declared type to match.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the annotation on a field in a
+      subclass of `Struct` or `Union` doesn't match the Dart type of the field.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the annotation
+      `Double` doesn't match the Dart type `int`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        [!@Double()!]
+        external int x;
+      }
+      ```
+
+      #### Common fixes
+
+      If the type of the field is correct, then change the annotation to match:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        external int x;
+      }
+      ```
+
+      If the annotation is correct, then change the type of the field to match:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Double()
+        external double x;
+      }
+      ```
   MISSING_ANNOTATION_ON_STRUCT_FIELD:
     problemMessage: "Fields in a struct class must either have the type 'Pointer' or an annotation indicating the native type."
     correctionMessage: Try adding an annotation.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` or `Union` whose type requires an annotation doesn't have one.
+      The Dart types `int`, `double`, and `Array` are used to represent multiple
+      C types, and the annotation specifies which of the compatible C types the
+      field represents.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `x` doesn't
+      have an annotation indicating the underlying width of the integer value:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        external [!int!] x;
+      }
+      ```
+
+      #### Common fixes
+
+      Add an appropriate annotation to the field:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int64()
+        external int x;
+      }
+      ```
   MISSING_EXCEPTION_VALUE:
-    problemMessage: "The method 'Pointer.fromFunction' must have an exceptional return value (the second argument) when the return type of the function is neither 'void', 'Handle' or 'Pointer'."
+    problemMessage: "The method 'Pointer.fromFunction' must have an exceptional return value (the second argument) when the return type of the function is neither 'void', 'Handle', nor 'Pointer'."
     correctionMessage: Try adding an exceptional return value.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when an invocation of the method
+      `Pointer.fromFunction` doesn't have a second argument (the exceptional
+      return value) when the type to be returned from the invocation is neither
+      `void`, `Handle`, nor `Pointer`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the type returned by
+      `f` is expected to be an 8-bit integer but the call to `fromFunction`
+      doesn't include an exceptional return argument:
+
+      ```dart
+      import 'dart:ffi';
+
+      int f(int i) => i * 2;
+
+      void g() {
+        Pointer.[!fromFunction!]<Int8 Function(Int8)>(f);
+      }
+      ```
+
+      #### Common fixes
+
+      Add an exceptional return type:
+
+      ```dart
+      import 'dart:ffi';
+
+      int f(int i) => i * 2;
+
+      void g() {
+        Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
+      }
+      ```
   MISSING_FIELD_TYPE_IN_STRUCT:
     problemMessage: "Fields in struct classes must have an explicitly declared type of 'int', 'double' or 'Pointer'."
     correctionMessage: "Try using 'int', 'double' or 'Pointer'."
     comment: |-
       Parameters:
       0: the type of the field
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of
+      `Struct` or `Union` doesn't have a type annotation. Every field must have
+      an explicit type, and the type must either be `int`, `double`, `Pointer`,
+      or a subclass of either `Struct` or `Union`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `str`
+      doesn't have a type annotation:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        external var [!str!];
+
+        @Int32()
+        external int i;
+      }
+      ```
+
+      #### Common fixes
+
+      Explicitly specify the type of the field:
+
+      ```dart
+      import 'dart:ffi';
+      import 'package:ffi/ffi.dart';
+
+      class C extends Struct {
+        external Pointer<Utf8> str;
+
+        @Int32()
+        external int i;
+      }
+      ```
   MISSING_SIZE_ANNOTATION_CARRAY:
-    problemMessage: "'Array's must have exactly one 'Array' annotation."
-    correctionMessage: "Try adding a 'Array' annotation."
+    problemMessage: "Fields of type 'Array' must have exactly one 'Array' annotation."
+    correctionMessage: "Try adding an 'Array' annotation, or removing all but one of the annotations."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a field in a subclass of either
+      `Struct` or `Union` has a type of `Array` but doesn't have a single
+      `Array` annotation indicating the dimensions of the array.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `a0` doesn't
+      have an `Array` annotation:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        external [!Array<Uint8>!] a0;
+      }
+      ```
+
+      #### Common fixes
+
+      Ensure that there's exactly one `Array` annotation on the field:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8)
+        external Array<Uint8> a0;
+      }
+      ```
   MUST_BE_A_NATIVE_FUNCTION_TYPE:
     problemMessage: "The type '{0}' given to '{1}' must be a valid 'dart:ffi' native function type."
     correctionMessage: "Try changing the type to only use members for 'dart:ffi'."
@@ -13909,6 +14714,48 @@
       Parameters:
       0: the type that should be a valid dart:ffi native type.
       1: the name of the function whose invocation depends on this relationship
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when an invocation of either
+      `Pointer.fromFunction` or `DynamicLibrary.lookupFunction` has a type
+      argument(whether explicit or inferred) that isn't a native function type.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the type `T` can be
+      any subclass of `Function` but the type argument for `fromFunction` is
+      required to be a native function type:
+
+      ```dart
+      import 'dart:ffi';
+
+      int f(int i) => i * 2;
+
+      class C<T extends Function> {
+        void g() {
+          Pointer.fromFunction<[!T!]>(f, 0);
+        }
+      }
+      ```
+
+      #### Common fixes
+
+      Use a native function type as the type argument to the invocation:
+
+      ```dart
+      import 'dart:ffi';
+
+      int f(int i) => i * 2;
+
+      class C<T extends Function> {
+        void g() {
+          Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
+        }
+      }
+      ```
   MUST_BE_A_SUBTYPE:
     problemMessage: "The type '{0}' must be a subtype of '{1}' for '{2}'."
     correctionMessage: Try changing one or both of the type arguments.
@@ -13917,47 +14764,455 @@
       0: the type that should be a subtype
       1: the supertype that the subtype is compared to
       2: the name of the function whose invocation depends on this relationship
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic in two cases:
+      - In an invocation of `Pointer.fromFunction` where the type argument
+        (whether explicit or inferred) isn't a supertype of the type of the
+        function passed as the first argument to the method.
+      - In an invocation of `DynamicLibrary.lookupFunction` where the first type
+        argument isn't a supertype of the second type argument.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the type of the
+      function `f` (`String Function(int)`) isn't a subtype of the type
+      argument `T` (`Int8 Function(Int8)`):
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = Int8 Function(Int8);
+
+      double f(double i) => i;
+
+      void g() {
+        Pointer.fromFunction<T>([!f!], 5.0);
+      }
+      ```
+
+      #### Common fixes
+
+      If the function is correct, then change the type argument to match:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = Float Function(Float);
+
+      double f(double i) => i;
+
+      void g() {
+        Pointer.fromFunction<T>(f, 5.0);
+      }
+      ```
+
+      If the type argument is correct, then change the function to match:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = Int8 Function(Int8);
+
+      int f(int i) => i;
+
+      void g() {
+        Pointer.fromFunction<T>(f, 5);
+      }
+      ```
   NON_CONSTANT_TYPE_ARGUMENT:
-    problemMessage: "The type arguments to '{0}' must be compile time constants but type parameters are not constants."
+    problemMessage: "The type arguments to '{0}' must be known at compile time, so they can't be type parameters."
     correctionMessage: Try changing the type argument to be a constant type.
     comment: |-
       Parameters:
       0: the name of the function, method, or constructor having type arguments
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the type arguments to a method
+      are required to be known at compile time, but a type parameter, whose
+      value can't be known at compile time, is used as a type argument.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the type argument to
+      `Pointer.asFunction` must be known at compile time, but the type parameter
+      `R`, which isn't known at compile time, is being used as the type
+      argument:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef T = int Function(int);
+
+      class C<R extends T> {
+        void m(Pointer<NativeFunction<T>> p) {
+          p.asFunction<[!R!]>();
+        }
+      }
+      ```
+
+      #### Common fixes
+
+      Remove any uses of type parameters:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C {
+        void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
+          p.asFunction<int Function(int)>();
+        }
+      }
+      ```
   NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER:
-    problemMessage: "The type argument for the pointer '{0}' must be a valid 'NativeFunction' in order to use 'asFunction'."
+    problemMessage: "Can't invoke 'asFunction' because the function signature '{0}' for the pointer isn't a valid C function signature."
     correctionMessage: "Try changing the function argument in 'NativeFunction' to only use NativeTypes."
     comment: |-
       Parameters:
       0: the type that should be a valid dart:ffi native type.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the method `asFunction` is
+      invoked on a pointer to a native function, but the signature of the native
+      function isn't a valid C function signature.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because function signature
+      associated with the pointer `p` (`FNative`) isn't a valid C function
+      signature:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef FNative = int Function(int);
+      typedef F = int Function(int);
+
+      class C {
+        void f(Pointer<NativeFunction<FNative>> p) {
+          p.asFunction<[!F!]>();
+        }
+      }
+      ```
+
+      #### Common fixes
+
+      Make the `NativeFunction` signature a valid C signature:
+
+      ```dart
+      import 'dart:ffi';
+
+      typedef FNative = Int8 Function(Int8);
+      typedef F = int Function(int);
+
+      class C {
+        void f(Pointer<NativeFunction<FNative>> p) {
+          p.asFunction<F>();
+        }
+      }
+      ```
   NON_POSITIVE_ARRAY_DIMENSION:
     problemMessage: Array dimensions must be positive numbers.
     correctionMessage: Try changing the input to a positive number.
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a dimension given in an `Array`
+      annotation is less than or equal to zero (`0`).
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because an array dimension of
+      `-1` was provided:
+
+      ```dart
+      import 'dart:ffi';
+
+      class MyStruct extends Struct {
+        @Array([!-8!])
+        external Array<Uint8> a0;
+      }
+      ```
+
+      #### Common fixes
+
+      Change the dimension to be a positive integer:
+
+      ```dart
+      import 'dart:ffi';
+
+      class MyStruct extends Struct {
+        @Array(8)
+        external Array<Uint8> a0;
+      }
+      ```
   NON_SIZED_TYPE_ARGUMENT:
-    problemMessage: "Type arguments to '{0}' can't have the type '{1}'. They can only be declared as native integer, 'Float', 'Double', 'Pointer', or subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
+    problemMessage: "The type '{1}' isn't a valid type argument for '{0}'. The type argument must be a native integer, 'Float', 'Double', 'Pointer', or subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
     correctionMessage: "Try using a native integer, 'Float', 'Double', 'Pointer', or subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
     comment: |-
       Parameters:
       0: the type of the field
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the type argument for the class
+      `Array` isn't one of the valid types: either a native integer, `Float`,
+      `Double`, `Pointer`, or subtype of `Struct`, `Union`, or
+      `AbiSpecificInteger`.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the type argument to
+      `Array` is `Void`, and `Void` isn't one of the valid types:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8)
+        external Array<[!Void!]> a0;
+      }
+      ```
+
+      #### Common fixes
+
+      Change the type argument to one of the valid types:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8)
+        external Array<Uint8> a0;
+      }
+      ```
   PACKED_ANNOTATION:
     problemMessage: "Structs must have at most one 'Packed' annotation."
     correctionMessage: "Try removing extra 'Packed' annotations."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a subclass of `Struct` has more
+      than one `Packed` annotation.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C`, which
+      is a subclass of `Struct`, has two `Packed` annotations:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(1)
+      [!@Packed(1)!]
+      class C extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+      ```
+
+      #### Common fixes
+
+      Remove all but one of the annotations:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(1)
+      class C extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+      ```
   PACKED_ANNOTATION_ALIGNMENT:
     problemMessage: Only packing to 1, 2, 4, 8, and 16 bytes is supported.
     correctionMessage: "Try changing the 'Packed' annotation alignment to 1, 2, 4, 8, or 16."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the argument to the `Packed`
+      annotation isn't one of the allowed values: 1, 2, 4, 8, or 16.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the argument to the
+      `Packed` annotation (`3`) isn't one of the allowed values:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed([!3!])
+      class C extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+      ```
+
+      #### Common fixes
+
+      Change the alignment to be one of the allowed values:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(4)
+      class C extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+      ```
   PACKED_NESTING_NON_PACKED:
-    problemMessage: "Nesting the non-packed or less tightly packed struct '{0}' in a packed struct '{1}' is not supported."
+    problemMessage: "Nesting the non-packed or less tightly packed struct '{0}' in a packed struct '{1}' isn't supported."
     correctionMessage: Try packing the nested struct or packing the nested struct more tightly.
     comment: |-
       Parameters:
       0: the name of the outer struct
       1: the name of the struct being nested
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a subclass of `Struct` that is
+      annotated as being `Packed` declares a field whose type is also a subclass
+      of `Struct` and the field's type is either not packed or is packed less
+      tightly.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `Outer`,
+      which is a subclass of `Struct` and is packed on 1-byte boundaries,
+      declared a field whose type (`Inner`) is packed on 8-byte boundaries:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(8)
+      class Inner extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+
+      @Packed(1)
+      class Outer extends Struct {
+        external Pointer<Uint8> notEmpty;
+
+        external [!Inner!] nestedLooselyPacked;
+      }
+      ```
+
+      #### Common fixes
+
+      If the inner struct should be packed more tightly, then change the
+      argument to the inner struct's `Packed` annotation:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(1)
+      class Inner extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+
+      @Packed(1)
+      class Outer extends Struct {
+        external Pointer<Uint8> notEmpty;
+
+        external Inner nestedLooselyPacked;
+      }
+      ```
+
+      If the outer struct should be packed less tightly, then change the
+      argument to the outer struct's `Packed` annotation:
+
+      ```dart
+      import 'dart:ffi';
+
+      @Packed(8)
+      class Inner extends Struct {
+        external Pointer<Uint8> notEmpty;
+      }
+
+      @Packed(8)
+      class Outer extends Struct {
+        external Pointer<Uint8> notEmpty;
+
+        external Inner nestedLooselyPacked;
+      }
+      ```
+
+      If the inner struct doesn't have an annotation and should be packed, then
+      add an annotation.
+
+      If the inner struct doesn't have an annotation and the outer struct
+      shouldn't be packed, then remove its annotation.
   SIZE_ANNOTATION_DIMENSIONS:
     problemMessage: "'Array's must have an 'Array' annotation that matches the dimensions."
     correctionMessage: "Try adjusting the arguments in the 'Array' annotation."
     comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when the number of dimensions
+      specified in an `Array` annotation doesn't match the number of nested
+      arrays specified by the type of a field.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the field `a0` has a
+      type with three nested arrays, but only two dimensions are given in the
+      `Array` annotation:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        [!@Array(8, 8)!]
+        external Array<Array<Array<Uint8>>> a0;
+      }
+      ```
+
+      #### Common fixes
+
+      If the type of the field is correct, then fix the annotation to have the
+      required number of dimensions:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8, 8, 4)
+        external Array<Array<Array<Uint8>>> a0;
+      }
+      ```
+
+      If the type of the field is wrong, then fix the type of the field:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Array(8, 8)
+        external Array<Array<Uint8>> a0;
+      }
+      ```
   SUBTYPE_OF_FFI_CLASS_IN_EXTENDS:
     sharedName: SUBTYPE_OF_FFI_CLASS
     problemMessage: "The class '{0}' can't extend '{1}'."
@@ -13966,10 +15221,51 @@
       Parameters:
       0: the name of the subclass
       1: the name of the class being extended, implemented, or mixed in
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a class extends any FFI class
+      other than `Struct` or `Union`, or implements or mixes in any FFI class.
+      `Struct` and `Union` are the only FFI classes that can be subtyped, and
+      then only by extending them.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C` extends
+      `Double`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends [!Double!] {}
+      ```
+
+      #### Common fixes
+
+      If the class should extend either `Struct` or `Union`, then change the
+      declaration of the class:
+
+      ```dart
+      import 'dart:ffi';
+
+      class C extends Struct {
+        @Int32()
+        external int i;
+      }
+      ```
+
+      If the class shouldn't extend either `Struct` or `Union`, then remove any
+      references to FFI classes:
+
+      ```dart
+      class C {}
+      ```
   SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS:
     sharedName: SUBTYPE_OF_FFI_CLASS
     problemMessage: "The class '{0}' can't implement '{1}'."
-    correctionMessage: "Try extending 'Struct' or 'Union'."
+    correctionMessage: "Try implementing 'Allocator' or 'Finalizable'."
     comment: |-
       Parameters:
       0: the name of the subclass
@@ -13990,6 +15286,51 @@
       Parameters:
       0: the name of the subclass
       1: the name of the class being extended, implemented, or mixed in
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a class extends, implements, or
+      mixes in a class that extends either `Struct` or `Union`. Classes can only
+      extend either `Struct` or `Union` directly.
+
+      For more information about FFI, see [C interop using dart:ffi][].
+
+      #### Example
+
+      The following code produces this diagnostic because the class `C` extends
+      `S`, and `S` extends `Struct`:
+
+      ```dart
+      import 'dart:ffi';
+
+      class S extends Struct {
+        external Pointer f;
+      }
+
+      class C extends [!S!] {
+        external Pointer g;
+      }
+      ```
+
+      #### Common fixes
+
+      If you're trying to define a struct or union that shares some fields
+      declared by a different struct or union, then extend `Struct` or `Union`
+      directly and copy the shared fields:
+
+      ```dart
+      import 'dart:ffi';
+
+      class S extends Struct {
+        external Pointer f;
+      }
+
+      class C extends Struct {
+        external Pointer f;
+
+        external Pointer g;
+      }
+      ```
   SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS:
     sharedName: SUBTYPE_OF_STRUCT_CLASS
     problemMessage: "The class '{0}' can't implement '{1}' because '{1}' is a subtype of 'Struct', 'Union', or 'AbiSpecificInteger'."
@@ -16487,7 +17828,7 @@
   TEXT_DIRECTION_CODE_POINT_IN_COMMENT:
     problemMessage: The Unicode code point 'U+{0}' changes the appearance of text from how it's interpreted by the compiler.
     correctionMessage: Try removing the code point or using the Unicode escape sequence '\u{0}'.
-    hasPublishedDocs: false
+    hasPublishedDocs: true
     comment: |-
       Parameters:
       0: the unicode sequence of the code point.
@@ -16527,7 +17868,7 @@
   TEXT_DIRECTION_CODE_POINT_IN_LITERAL:
     problemMessage: The Unicode code point 'U+{0}' changes the appearance of text from how it's interpreted by the compiler.
     correctionMessage: Try removing the code point or using the Unicode escape sequence '\u{0}'.
-    hasPublishedDocs: false
+    hasPublishedDocs: true
     comment: |-
       Parameters:
       0: the unicode sequence of the code point.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index e706822..5994057 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 3.1.0-dev
+version: 3.2.0
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
 
@@ -7,7 +7,7 @@
   sdk: '>=2.14.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^32.0.0
+  _fe_analyzer_shared: ^34.0.0
   cli_util: ^0.3.0
   collection: ^1.15.0
   convert: ^3.0.0
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index 873dc18..ffb9e0d 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -511,7 +511,7 @@
       String path, Function(List<WatchEvent> changesReceived) test) {
     var folder = provider.getResource(path) as Folder;
     var changesReceived = <WatchEvent>[];
-    folder.changes.listen(changesReceived.add);
+    folder.watch().changes.listen(changesReceived.add);
     return test(changesReceived);
   }
 }
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
index c08137e..08584bd 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
@@ -146,7 +146,7 @@
       var file =
           PhysicalResourceProvider.INSTANCE.getResource(filePath) as File;
       var changesReceived = <WatchEvent>[];
-      var subscription = file.changes.listen(changesReceived.add);
+      var subscription = file.watch().changes.listen(changesReceived.add);
       // Delay running the rest of the test to allow file.changes propagate.
       return _delayed(() => test(changesReceived)).whenComplete(() {
         subscription.cancel();
@@ -164,7 +164,7 @@
       var folder =
           PhysicalResourceProvider.INSTANCE.getResource(filePath) as Folder;
       var changesReceived = <WatchEvent>[];
-      var subscription = folder.changes.listen(changesReceived.add);
+      var subscription = folder.watch().changes.listen(changesReceived.add);
       // Delay running the rest of the test to allow folder.changes to
       // take a snapshot of the current directory state.  Otherwise it
       // won't be able to reliably distinguish new files from modified
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 8de1d7f..e52a181 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -372,6 +372,26 @@
     await _assertValueBool(true, "'a' != 'b'");
   }
 
+  test_object_enum() async {
+    await resolveTestCode('''
+enum E { v1, v2 }
+const x1 = E.v1;
+const x2 = E.v2;
+''');
+
+    _assertTopVarConstValue('x1', r'''
+E
+  _name: String v1
+  index: int 0
+''');
+
+    _assertTopVarConstValue('x2', r'''
+E
+  _name: String v2
+  index: int 1
+''');
+  }
+
   test_parenthesizedExpression() async {
     await _assertValueString("a", "('a')");
   }
@@ -444,6 +464,10 @@
     await _assertValueInt(6, "'Dvorak'.length");
   }
 
+  void _assertTopVarConstValue(String name, String expected) {
+    assertDartObjectText(_topVarConstResult(name).value, expected);
+  }
+
   Future<void> _assertValueBool(bool expectedValue, String contents) async {
     var result = await _getExpressionValue(contents);
     DartObject value = result.value!;
@@ -491,4 +515,9 @@
 
     return evaluator.evaluate(expression);
   }
+
+  EvaluationResultImpl _topVarConstResult(String name) {
+    var element = findElement.topVar(name) as ConstTopLevelVariableElementImpl;
+    return element.evaluationResult!;
+  }
 }
diff --git a/pkg/analyzer/test/generated/java_core_test.dart b/pkg/analyzer/test/generated/java_core_test.dart
index 9d8ccfe..1dd1ff2 100644
--- a/pkg/analyzer/test/generated/java_core_test.dart
+++ b/pkg/analyzer/test/generated/java_core_test.dart
@@ -6,53 +6,17 @@
 import 'package:test/test.dart';
 
 main() {
-  group('Character', () {
-    group('isLetter', () {
-      test('digits', () {
-        expect(Character.isLetter('0'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetter('1'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetter('9'.codeUnitAt(0)), isFalse);
-      });
+  test('formatList', () {
+    expect(
+      format('Hello, {0} {1}!', 'John', 'Doe'),
+      'Hello, John Doe!',
+    );
+  });
 
-      test('letters', () {
-        expect(Character.isLetter('a'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetter('b'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetter('z'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetter('C'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetter('D'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetter('Y'.codeUnitAt(0)), isTrue);
-      });
-
-      test('other', () {
-        expect(Character.isLetter(' '.codeUnitAt(0)), isFalse);
-        expect(Character.isLetter('.'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetter('-'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetter('+'.codeUnitAt(0)), isFalse);
-      });
-    });
-
-    group('isLetterOrDigit', () {
-      test('digits', () {
-        expect(Character.isLetterOrDigit('0'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('1'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('9'.codeUnitAt(0)), isTrue);
-      });
-
-      test('letters', () {
-        expect(Character.isLetterOrDigit('a'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('b'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('z'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('C'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('D'.codeUnitAt(0)), isTrue);
-        expect(Character.isLetterOrDigit('Y'.codeUnitAt(0)), isTrue);
-      });
-
-      test('other', () {
-        expect(Character.isLetterOrDigit(' '.codeUnitAt(0)), isFalse);
-        expect(Character.isLetterOrDigit('.'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetterOrDigit('-'.codeUnitAt(0)), isFalse);
-        expect(Character.isLetterOrDigit('+'.codeUnitAt(0)), isFalse);
-      });
-    });
+  test('formatList', () {
+    expect(
+      formatList('Hello, {0} {1}!', ['John', 'Doe']),
+      'Hello, John Doe!',
+    );
   });
 }
diff --git a/pkg/analyzer/test/generated/java_io_test.dart b/pkg/analyzer/test/generated/java_io_test.dart
deleted file mode 100644
index 35bfdeb..0000000
--- a/pkg/analyzer/test/generated/java_io_test.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/generated/java_io.dart';
-import 'package:path/path.dart' as path;
-import 'package:test/test.dart';
-
-main() {
-  group('JavaFile', () {
-    group('toURI', () {
-      test('forAbsolute', () {
-        String tempPath = '/temp';
-        String absolutePath = path.context.join(tempPath, 'foo.dart');
-        // we use an absolute path
-        expect(path.context.isAbsolute(absolutePath), isTrue,
-            reason: '"$absolutePath" is not absolute');
-        // test that toURI() returns an absolute URI
-        // ignore: deprecated_member_use_from_same_package
-        Uri uri = JavaFile(absolutePath).toURI();
-        expect(uri.isAbsolute, isTrue);
-        expect(uri.scheme, 'file');
-      });
-      test('forRelative', () {
-        String tempPath = '/temp';
-        String absolutePath = path.context.join(tempPath, 'foo.dart');
-        expect(path.context.isAbsolute(absolutePath), isTrue,
-            reason: '"$absolutePath" is not absolute');
-        // prepare a relative path
-        // We should not check that "relPath" is actually relative -
-        // it may be not on Windows, if "temp" is on other disk.
-        String relPath = path.context.relative(absolutePath);
-        // test that toURI() returns an absolute URI
-        // ignore: deprecated_member_use_from_same_package
-        Uri uri = JavaFile(relPath).toURI();
-        expect(uri.isAbsolute, isTrue);
-        expect(uri.scheme, 'file');
-      });
-    });
-  });
-}
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 145865a..b1e3ed3 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -2,32 +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/analysis/features.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/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
-import 'package:analyzer/src/generated/resolver.dart' show ResolverVisitor;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/source/source_resource.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'elements_types_mixin.dart';
-import 'test_analysis_context.dart';
-import 'test_support.dart';
+import '../src/dart/resolution/context_collection_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -35,155 +15,118 @@
   });
 }
 
-/// Wrapper around the test package's `fail` function.
-///
-/// Unlike the test package's `fail` function, this function is not annotated
-/// with @alwaysThrows, so we can call it at the top of a test method without
-/// causing the rest of the method to be flagged as dead code.
-void _fail(String message) {
-  fail(message);
-}
-
 @reflectiveTest
-class StaticTypeAnalyzerTest with ResourceProviderMixin, ElementsTypesMixin {
-  /// The error listener to which errors will be reported.
-  late final GatheringErrorListener _listener;
-
-  /// The resolver visitor used to create the analyzer.
-  late final ResolverVisitor _visitor;
-
-  /// The library containing the code being resolved.
-  late final LibraryElementImpl _definingLibrary;
-
-  /// The compilation unit containing the code being resolved.
-  late CompilationUnitElementImpl _definingCompilationUnit;
-
-  /// The type provider used to access the types.
-  late final TypeProvider _typeProvider;
-
-  @override
-  TypeProvider get typeProvider => _definingLibrary.typeProvider;
-
-  /// The type system used to analyze the test cases.
-  TypeSystemImpl get _typeSystem => _definingLibrary.typeSystem;
-
-  void fail_visitFunctionExpressionInvocation() {
-    _fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  void fail_visitMethodInvocation() {
-    _fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  void fail_visitSimpleIdentifier() {
-    _fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  void setUp() {
-    _listener = GatheringErrorListener();
-    _createAnalyzer();
-  }
-
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522')
-  void test_flatten_derived() {
+class StaticTypeAnalyzerTest extends PubPackageResolutionTest {
+  test_flatten_derived() async {
+    await assertNoErrorsInCode('''
+abstract class Derived<T> extends Future<T> {
+  factory Derived() => throw 'foo';
+}
+late Derived<dynamic> derivedDynamic;
+late Derived<int> derivedInt;
+late Derived<Derived> derivedDerived;
+late Derived<Derived<int>> derivedDerivedInt;
+    ''');
+    var dynamicType = typeProvider.dynamicType;
+    var derivedDynamicType = findElement.topVar('derivedDynamic').type;
+    var derivedIntType = findElement.topVar('derivedInt').type;
+    var derivedDerivedType = findElement.topVar('derivedDerived').type;
+    var derivedDerivedIntType = findElement.topVar('derivedDerivedInt').type;
     // class Derived<T> extends Future<T> { ... }
-    ClassElementImpl derivedClass =
-        ElementFactory.classElement2('Derived', ['T']);
-    derivedClass.supertype =
-        futureType(typeParameterTypeStar(derivedClass.typeParameters[0]));
-    InterfaceType intType = _typeProvider.intType;
-    DartType dynamicType = _typeProvider.dynamicType;
-    InterfaceType derivedIntType =
-        interfaceTypeStar(derivedClass, typeArguments: [intType]);
     // flatten(Derived) = dynamic
-    InterfaceType derivedDynamicType =
-        interfaceTypeStar(derivedClass, typeArguments: [dynamicType]);
     expect(_flatten(derivedDynamicType), dynamicType);
     // flatten(Derived<int>) = int
     expect(_flatten(derivedIntType), intType);
     // flatten(Derived<Derived>) = Derived
-    expect(
-        _flatten(interfaceTypeStar(derivedClass,
-            typeArguments: [derivedDynamicType])),
-        derivedDynamicType);
+    expect(_flatten(derivedDerivedType), derivedDynamicType);
     // flatten(Derived<Derived<int>>) = Derived<int>
-    expect(
-        _flatten(
-            interfaceTypeStar(derivedClass, typeArguments: [derivedIntType])),
-        derivedIntType);
+    expect(_flatten(derivedDerivedIntType), derivedIntType);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522')
-  void test_flatten_inhibit_recursion() {
-    // class A extends B
-    // class B extends A
-    ClassElementImpl classA = ElementFactory.classElement2('A', []);
-    ClassElementImpl classB = ElementFactory.classElement2('B', []);
-    classA.supertype = interfaceTypeStar(classB);
-    classB.supertype = interfaceTypeStar(classA);
+  test_flatten_inhibit_recursion() async {
+    await assertErrorsInCode('''
+class A extends B {}
+class B extends A {}
+late A a;
+late B b;
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
+    ]);
+    var aType = findElement.topVar('a').type;
+    var bType = findElement.topVar('b').type;
     // flatten(A) = A and flatten(B) = B, since neither class contains Future
     // in its class hierarchy.  Even though there is a loop in the class
     // hierarchy, flatten() should terminate.
-    expect(_flatten(interfaceTypeStar(classA)), interfaceTypeStar(classA));
-    expect(_flatten(interfaceTypeStar(classB)), interfaceTypeStar(classB));
+    expect(_flatten(aType), aType);
+    expect(_flatten(bType), bType);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522')
-  void test_flatten_related_derived_types() {
-    InterfaceType intType = _typeProvider.intType;
-    InterfaceType numType = _typeProvider.numType;
-    // class Derived<T> extends Future<T>
-    ClassElementImpl derivedClass =
-        ElementFactory.classElement2('Derived', ['T']);
-    derivedClass.supertype =
-        futureType(typeParameterTypeStar(derivedClass.typeParameters[0]));
-    // class A extends Derived<int> implements Derived<num> { ... }
-    ClassElementImpl classA = ElementFactory.classElement(
-        'A', interfaceTypeStar(derivedClass, typeArguments: [intType]));
-    classA.interfaces = <InterfaceType>[
-      interfaceTypeStar(derivedClass, typeArguments: [numType]),
-    ];
-    // class B extends Future<num> implements Future<int> { ... }
-    ClassElementImpl classB = ElementFactory.classElement(
-        'B', interfaceTypeStar(derivedClass, typeArguments: [numType]));
-    classB.interfaces = <InterfaceType>[
-      interfaceTypeStar(derivedClass, typeArguments: [intType])
-    ];
-    // flatten(A) = flatten(B) = int, since int is more specific than num.
+  test_flatten_related_derived_types() async {
+    await assertErrorsInCode('''
+abstract class Derived<T> extends Future<T> {
+  factory Derived() => throw 'foo';
+}
+abstract class A extends Derived<int> implements Derived<num> {
+  factory A() => throw 'foo';
+}
+abstract class B extends Future<num> implements Future<int> {
+  factory B() => throw 'foo';
+}
+late A a;
+late B b;
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 99, 1),
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 99, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 133, 12),
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 195, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 228, 11),
+    ]);
+    InterfaceType intType = typeProvider.intType;
+    InterfaceType numType = typeProvider.numType;
+    var aType = findElement.topVar('a').type;
+    var bType = findElement.topVar('b').type;
     // The code in flatten() that inhibits infinite recursion shouldn't be
     // fooled by the fact that Derived appears twice in the type hierarchy.
-    expect(_flatten(interfaceTypeStar(classA)), intType);
-    expect(_flatten(interfaceTypeStar(classB)), intType);
+    expect(_flatten(aType), intType);
+    expect(_flatten(bType), numType);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522')
-  void test_flatten_related_types() {
-    InterfaceType intType = _typeProvider.intType;
-    InterfaceType numType = _typeProvider.numType;
-    // class A extends Future<int> implements Future<num> { ... }
-    ClassElementImpl classA =
-        ElementFactory.classElement('A', _typeProvider.futureType(intType));
-    classA.interfaces = <InterfaceType>[_typeProvider.futureType(numType)];
-    // class B extends Future<num> implements Future<int> { ... }
-    ClassElementImpl classB =
-        ElementFactory.classElement('B', _typeProvider.futureType(numType));
-    classB.interfaces = <InterfaceType>[_typeProvider.futureType(intType)];
-    // flatten(A) = flatten(B) = int, since int is more specific than num.
-    expect(_flatten(interfaceTypeStar(classA)), intType);
-    expect(_flatten(interfaceTypeStar(classB)), intType);
+  test_flatten_related_types() async {
+    await assertErrorsInCode('''
+abstract class A extends Future<int> implements Future<num> {
+  factory A() => throw 'foo';
+}
+abstract class B extends Future<num> implements Future<int> {
+  factory B() => throw 'foo';
+}
+late A a;
+late B b;
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 15, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 48, 11),
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 109, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 142, 11),
+    ]);
+    InterfaceType intType = typeProvider.intType;
+    InterfaceType numType = typeProvider.numType;
+    var aType = findElement.topVar('a').type;
+    var bType = findElement.topVar('b').type;
+    expect(_flatten(aType), intType);
+    expect(_flatten(bType), numType);
   }
 
-  void test_flatten_simple() {
-    InterfaceType intType = _typeProvider.intType;
-    DartType dynamicType = _typeProvider.dynamicType;
-    InterfaceType futureDynamicType = _typeProvider.futureDynamicType;
-    InterfaceType futureIntType = _typeProvider.futureType(intType);
+  test_flatten_simple() async {
+    // No code needs to be analyzed but we still need to call
+    // assertNoErrorsInCode to get the typeProvider initialized.
+    await assertNoErrorsInCode('');
+    InterfaceType intType = typeProvider.intType;
+    DartType dynamicType = typeProvider.dynamicType;
+    InterfaceType futureDynamicType = typeProvider.futureDynamicType;
+    InterfaceType futureIntType = typeProvider.futureType(intType);
     InterfaceType futureFutureDynamicType =
-        _typeProvider.futureType(futureDynamicType);
-    InterfaceType futureFutureIntType = _typeProvider.futureType(futureIntType);
+        typeProvider.futureType(futureDynamicType);
+    InterfaceType futureFutureIntType = typeProvider.futureType(futureIntType);
     // flatten(int) = int
     expect(_flatten(intType), intType);
     // flatten(dynamic) = dynamic
@@ -198,391 +141,269 @@
     expect(_flatten(futureFutureIntType), futureIntType);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522')
-  void test_flatten_unrelated_types() {
-    InterfaceType intType = _typeProvider.intType;
-    InterfaceType stringType = _typeProvider.stringType;
-    // class A extends Future<int> implements Future<String> { ... }
-    ClassElementImpl classA =
-        ElementFactory.classElement('A', _typeProvider.futureType(intType));
-    classA.interfaces = <InterfaceType>[_typeProvider.futureType(stringType)];
-    // class B extends Future<String> implements Future<int> { ... }
-    ClassElementImpl classB =
-        ElementFactory.classElement('B', _typeProvider.futureType(stringType));
-    classB.interfaces = <InterfaceType>[_typeProvider.futureType(intType)];
+  test_flatten_unrelated_types() async {
+    await assertErrorsInCode('''
+abstract class A extends Future<int> implements Future<String> {
+  factory A() => throw 'foo';
+}
+abstract class B extends Future<String> implements Future<int> {
+  factory B() => throw 'foo';
+}
+late A a;
+late B b;
+''', [
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 15, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 15, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 15, 1),
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 15, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 48, 14),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 112, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 112, 1),
+      error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 112, 1),
+      error(CompileTimeErrorCode.INCONSISTENT_INHERITANCE, 112, 1),
+      error(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, 148, 11),
+    ]);
+    var aType = findElement.topVar('a').type;
+    var bType = findElement.topVar('b').type;
     // flatten(A) = A and flatten(B) = B, since neither string nor int is more
     // specific than the other.
-    expect(_flatten(interfaceTypeStar(classA)), interfaceTypeStar(classA));
-    expect(_flatten(interfaceTypeStar(classB)), interfaceTypeStar(classB));
+    expect(_flatten(aType), intType);
+    expect(_flatten(bType), stringType);
   }
 
-  void test_visitAdjacentStrings() {
-    // "a" "b"
-    Expression node = AstTestFactory.adjacentStrings(
-        [_resolvedString("a"), _resolvedString("b")]);
-    expect(_analyze(node), same(_typeProvider.stringType));
-    _listener.assertNoErrors();
+  test_visitAdjacentStrings() async {
+    await assertNoErrorsInCode('''
+test() => 'a' 'b';
+''');
+    expect(findNode.adjacentStrings("'a' 'b'").staticType,
+        same(typeProvider.stringType));
   }
 
-  void test_visitAsExpression() {
-    // class A { ... this as B ... }
-    // class B extends A {}
-    ClassElement superclass = ElementFactory.classElement2("A");
-    InterfaceType superclassType = interfaceTypeStar(superclass);
-    ClassElement subclass = ElementFactory.classElement("B", superclassType);
-    Expression node = AstTestFactory.asExpression(
-        AstTestFactory.thisExpression(), AstTestFactory.namedType(subclass));
-    expect(_analyze(node, superclassType), interfaceTypeStar(subclass));
-    _listener.assertNoErrors();
+  test_visitAsExpression() async {
+    await assertNoErrorsInCode('''
+class A {
+  test() => this as B;
+}
+class B extends A {}
+late B b;
+''');
+    var bType = findElement.topVar('b').type;
+    expect(findNode.as_('this as B').staticType, bType);
   }
 
-  void test_visitAwaitExpression_flattened() {
-    // await e, where e has type Future<Future<int>>
-    InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType = _typeProvider.futureType(intType);
-    InterfaceType futureFutureIntType = _typeProvider.futureType(futureIntType);
-    Expression node = AstTestFactory.awaitExpression(
-        _resolvedVariable(futureFutureIntType, 'e'));
-    expect(_analyze(node), same(futureIntType));
-    _listener.assertNoErrors();
+  test_visitAwaitExpression_flattened() async {
+    await assertNoErrorsInCode('''
+test(Future<Future<int>> e) async => await e;
+''');
+    InterfaceType futureIntType = typeProvider.futureType(typeProvider.intType);
+    expect(findNode.awaitExpression('await e').staticType, futureIntType);
   }
 
-  void test_visitAwaitExpression_simple() {
+  test_visitAwaitExpression_simple() async {
+    await assertNoErrorsInCode('''
+test(Future<int> e) async => await e;
+''');
     // await e, where e has type Future<int>
-    InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType = _typeProvider.futureType(intType);
-    Expression node =
-        AstTestFactory.awaitExpression(_resolvedVariable(futureIntType, 'e'));
-    expect(_analyze(node), same(intType));
-    _listener.assertNoErrors();
+    InterfaceType intType = typeProvider.intType;
+    expect(findNode.awaitExpression('await e').staticType, intType);
   }
 
-  void test_visitBooleanLiteral_false() {
-    // false
-    Expression node = AstTestFactory.booleanLiteral(false);
-    expect(_analyze(node), same(_typeProvider.boolType));
-    _listener.assertNoErrors();
+  test_visitBooleanLiteral_false() async {
+    await assertNoErrorsInCode('''
+test() => false;
+''');
+    expect(findNode.booleanLiteral('false').staticType,
+        same(typeProvider.boolType));
   }
 
-  void test_visitBooleanLiteral_true() {
-    // true
-    Expression node = AstTestFactory.booleanLiteral(true);
-    expect(_analyze(node), same(_typeProvider.boolType));
-    _listener.assertNoErrors();
+  test_visitBooleanLiteral_true() async {
+    await assertNoErrorsInCode('''
+test() => true;
+''');
+    expect(findNode.booleanLiteral('true').staticType,
+        same(typeProvider.boolType));
   }
 
-  void test_visitCascadeExpression() {
-    // a..length
-    Expression node = AstTestFactory.cascadeExpression(_resolvedString("a"), [
-      AstTestFactory.propertyAccess2(null, "length", TokenType.PERIOD_PERIOD)
-    ]);
-    expect(_analyze(node), same(_typeProvider.stringType));
-    _listener.assertNoErrors();
+  test_visitCascadeExpression() async {
+    await assertNoErrorsInCode('''
+test(String a) => a..length;
+''');
+    expect(findNode.cascade('a..length').staticType, typeProvider.stringType);
   }
 
-  void test_visitConditionalExpression_differentTypes() {
-    // true ? 1.0 : 0
-    Expression node = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(true),
-        _resolvedDouble(1.0),
-        _resolvedInteger(0));
-    expect(_analyze(node), _typeProvider.numType);
-    _listener.assertNoErrors();
+  test_visitConditionalExpression_differentTypes() async {
+    await assertNoErrorsInCode('''
+test(bool b) => b ? 1.0 : 0;
+''');
+    expect(findNode.conditionalExpression('b ? 1.0 : 0').staticType,
+        typeProvider.numType);
   }
 
-  void test_visitConditionalExpression_sameTypes() {
-    // true ? 1 : 0
-    Expression node = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(true),
-        _resolvedInteger(1),
-        _resolvedInteger(0));
-    expect(_analyze(node), same(_typeProvider.intType));
-    _listener.assertNoErrors();
+  test_visitConditionalExpression_sameTypes() async {
+    await assertNoErrorsInCode('''
+test(bool b) => b ? 1 : 0;
+''');
+    expect(findNode.conditionalExpression('b ? 1 : 0').staticType,
+        same(typeProvider.intType));
   }
 
-  void test_visitDoubleLiteral() {
-    // 4.33
-    Expression node = AstTestFactory.doubleLiteral(4.33);
-    expect(_analyze(node), same(_typeProvider.doubleType));
-    _listener.assertNoErrors();
+  test_visitDoubleLiteral() async {
+    await assertNoErrorsInCode('''
+test() => 4.33;
+''');
+    expect(findNode.doubleLiteral('4.33').staticType,
+        same(typeProvider.doubleType));
   }
 
-  void test_visitInstanceCreationExpression_named() {
-    // new C.m()
-    ClassElementImpl classElement = ElementFactory.classElement2("C");
-    _definingCompilationUnit.classes = [classElement];
-    String constructorName = "m";
-    ConstructorElementImpl constructor =
-        ElementFactory.constructorElement2(classElement, constructorName);
-    classElement.constructors = <ConstructorElement>[constructor];
-    InstanceCreationExpression node =
-        AstTestFactory.instanceCreationExpression2(
-            null, AstTestFactory.namedType(classElement), [
-      AstTestFactory.identifier3(constructorName)
-        ..scopeLookupResult = ScopeLookupResult(constructor, null)
-    ]);
-    expect(_analyze(node), interfaceTypeStar(classElement));
-    _listener.assertNoErrors();
+  test_visitInstanceCreationExpression_named() async {
+    await assertNoErrorsInCode('''
+class C {
+  C.m();
+}
+test() => new C.m();
+late C c;
+''');
+    var cType = findElement.topVar('c').type;
+    expect(findNode.instanceCreation('new C.m()').staticType, cType);
   }
 
-  void test_visitInstanceCreationExpression_typeParameters() {
-    // new C<I>()
-    ClassElementImpl elementC = ElementFactory.classElement2("C", ["E"]);
-    ClassElementImpl elementI = ElementFactory.classElement2("I");
-    ConstructorElementImpl constructor =
-        ElementFactory.constructorElement2(elementC, null);
-    elementC.constructors = <ConstructorElement>[constructor];
-    var typeName = AstTestFactory.namedType(
-        elementC, [AstTestFactory.namedType(elementI)]);
-    typeName.type = interfaceTypeStar(elementC,
-        typeArguments: [interfaceTypeStar(elementI)]);
-    InstanceCreationExpression node =
-        AstTestFactory.instanceCreationExpression2(null, typeName);
-    _definingCompilationUnit.classes = [elementC, elementI];
-    InterfaceType type = _analyze(node) as InterfaceType;
+  test_visitInstanceCreationExpression_typeParameters() async {
+    await assertNoErrorsInCode('''
+class C<E> {}
+class I {}
+test() => new C<I>();
+late I i;
+''');
+    var iType = findElement.topVar('i').type;
+    InterfaceType type =
+        findNode.instanceCreation('new C<I>()').staticType as InterfaceType;
     List<DartType> typeArgs = type.typeArguments;
     expect(typeArgs.length, 1);
-    expect(typeArgs[0], interfaceTypeStar(elementI));
-    _listener.assertNoErrors();
+    expect(typeArgs[0], iType);
   }
 
-  void test_visitInstanceCreationExpression_unnamed() {
-    // new C()
-    ClassElementImpl classElement = ElementFactory.classElement2("C");
-    _definingCompilationUnit.classes = [classElement];
-    ConstructorElementImpl constructor =
-        ElementFactory.constructorElement2(classElement, null);
-    classElement.constructors = <ConstructorElement>[constructor];
-    InstanceCreationExpression node =
-        AstTestFactory.instanceCreationExpression2(
-            null, AstTestFactory.namedType(classElement));
-    expect(_analyze(node), interfaceTypeStar(classElement));
-    _listener.assertNoErrors();
+  test_visitInstanceCreationExpression_unnamed() async {
+    await assertNoErrorsInCode('''
+class C {}
+test() => new C();
+late C c;
+''');
+    var cType = findElement.topVar('c').type;
+    expect(findNode.instanceCreation('new C()').staticType, cType);
   }
 
-  void test_visitIntegerLiteral() {
-    // 42
-    Expression node = _resolvedInteger(42);
-    AstTestFactory.argumentList([node]);
-    expect(_analyze(node), same(_typeProvider.intType));
-    _listener.assertNoErrors();
+  test_visitIntegerLiteral() async {
+    await assertNoErrorsInCode('''
+test() => 42;
+''');
+    var node = findNode.integerLiteral('42');
+    expect(node.staticType, same(typeProvider.intType));
   }
 
-  void test_visitIsExpression_negated() {
-    // a is! String
-    Expression node = AstTestFactory.isExpression(
-        _resolvedString("a"), true, AstTestFactory.namedType4("String"));
-    expect(_analyze(node), same(_typeProvider.boolType));
-    _listener.assertNoErrors();
+  test_visitIsExpression_negated() async {
+    await assertNoErrorsInCode('''
+test(Object a) => a is! String;
+''');
+    expect(findNode.isExpression('a is! String').staticType,
+        same(typeProvider.boolType));
   }
 
-  void test_visitIsExpression_notNegated() {
-    // a is String
-    Expression node = AstTestFactory.isExpression(
-        _resolvedString("a"), false, AstTestFactory.namedType4("String"));
-    expect(_analyze(node), same(_typeProvider.boolType));
-    _listener.assertNoErrors();
+  test_visitIsExpression_notNegated() async {
+    await assertNoErrorsInCode('''
+test(Object a) => a is String;
+''');
+    expect(findNode.isExpression('a is String').staticType,
+        same(typeProvider.boolType));
   }
 
-  @FailingTest(reason: 'This is an old unit test, port and remove')
-  void test_visitMethodInvocation_then() {
-    // then()
-    Expression node = AstTestFactory.methodInvocation(null, "then");
-    _analyze(node);
-    _listener.assertNoErrors();
+  test_visitMethodInvocation() async {
+    await assertNoErrorsInCode('''
+m() => 0;
+test() => m();
+''');
   }
 
-  void test_visitNamedExpression() {
-    // n: a
-    Expression node =
-        AstTestFactory.namedExpression2("n", _resolvedString("a"));
-    expect(_analyze(node), same(_typeProvider.stringType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitNullLiteral() {
-    // null
-    Expression node = AstTestFactory.nullLiteral();
-    expect(_analyze(node), same(_typeProvider.nullType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitParenthesizedExpression() {
-    // (0)
-    Expression node =
-        AstTestFactory.parenthesizedExpression(_resolvedInteger(0));
-    expect(_analyze(node), same(_typeProvider.intType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitSimpleStringLiteral() {
-    // "a"
-    Expression node = _resolvedString("a");
-    expect(_analyze(node), same(_typeProvider.stringType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitStringInterpolation() {
-    // "a${'b'}c"
-    Expression node = AstTestFactory.string([
-      AstTestFactory.interpolationString("a", "a"),
-      AstTestFactory.interpolationExpression(_resolvedString("b")),
-      AstTestFactory.interpolationString("c", "c")
-    ]);
-    expect(_analyze(node), same(_typeProvider.stringType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitSuperExpression() {
-    // super
-    InterfaceType superType =
-        interfaceTypeStar(ElementFactory.classElement2("A"));
-    InterfaceType thisType =
-        interfaceTypeStar(ElementFactory.classElement("B", superType));
-    Expression node = AstTestFactory.superExpression();
-    // Place the super expression inside a method declaration
-    // (`test() => super.foo;`) so that we don't provoke a
-    // SUPER_IN_INVALID_CONTEXT error
-    AstTestFactory.methodDeclaration4(
-        name: 'test',
-        body: AstTestFactory.expressionFunctionBody(
-            AstTestFactory.propertyAccess2(node, 'foo')));
-    expect(_analyze(node, thisType), same(thisType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitSymbolLiteral() {
-    expect(_analyze(AstTestFactory.symbolLiteral(["a"])),
-        same(_typeProvider.symbolType));
-  }
-
-  void test_visitThisExpression() {
-    // this
-    InterfaceType thisType = interfaceTypeStar(ElementFactory.classElement(
-        "B", interfaceTypeStar(ElementFactory.classElement2("A"))));
-    Expression node = AstTestFactory.thisExpression();
-    expect(_analyze(node, thisType), same(thisType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitThrowExpression_withValue() {
-    // throw 0
-    Expression node = AstTestFactory.throwExpression2(_resolvedInteger(0));
-    expect(_analyze(node), same(_typeProvider.bottomType));
-    _listener.assertNoErrors();
-  }
-
-  /// Return the type associated with the given [node] after the static type
-  /// analyzer has computed a type for it. If [thisType] is provided, it is the
-  /// type of 'this'.
-  DartType _analyze(Expression node, [InterfaceType? thisType]) {
-    if (thisType != null) {
-      _visitor.setThisInterfaceType(thisType);
-    }
-    node.accept(_visitor);
-    return node.typeOrThrow;
-  }
-
-  void _assertType(
-      InterfaceTypeImpl expectedType, InterfaceTypeImpl actualType) {
+  test_visitNamedExpression() async {
+    await assertNoErrorsInCode('''
+test(dynamic d, String a) => d(n: a);
+''');
     expect(
-      actualType.getDisplayString(withNullability: false),
-      expectedType.getDisplayString(withNullability: false),
-    );
-    expect(actualType.element, expectedType.element);
-    List<DartType> expectedArguments = expectedType.typeArguments;
-    int length = expectedArguments.length;
-    List<DartType> actualArguments = actualType.typeArguments;
-    expect(actualArguments, hasLength(length));
-    for (int i = 0; i < length; i++) {
-      _assertType2(expectedArguments[i], actualArguments[i]);
-    }
+        findNode.namedExpression('n: a').staticType, typeProvider.stringType);
   }
 
-  void _assertType2(DartType expectedType, DartType actualType) {
-    if (expectedType is InterfaceTypeImpl) {
-      _assertType(expectedType, actualType as InterfaceTypeImpl);
-    }
-    // TODO(brianwilkerson) Compare other kinds of types then make this a shared
-    // utility method.
+  test_visitNullLiteral() async {
+    await assertNoErrorsInCode('''
+test() => null;
+''');
+    expect(
+        findNode.nullLiteral('null').staticType, same(typeProvider.nullType));
   }
 
-  /// Create the analyzer used by the tests.
-  void _createAnalyzer() {
-    var context = TestAnalysisContext();
-    var inheritance = InheritanceManager3();
-    Source source = FileSource(getFile("/lib.dart"));
-    _definingCompilationUnit = CompilationUnitElementImpl();
-    _definingCompilationUnit.librarySource =
-        _definingCompilationUnit.source = source;
-    var featureSet = FeatureSet.latestLanguageVersion();
-
-    _definingLibrary = LibraryElementImpl(
-        context, _AnalysisSessionMock(), 'name', -1, 0, featureSet);
-    _definingLibrary.definingCompilationUnit = _definingCompilationUnit;
-
-    _definingLibrary.typeProvider = context.typeProviderLegacy;
-    _definingLibrary.typeSystem = context.typeSystemLegacy;
-    _typeProvider = context.typeProviderLegacy;
-
-    _visitor = ResolverVisitor(
-        inheritance, _definingLibrary, source, _typeProvider, _listener,
-        featureSet: featureSet,
-        flowAnalysisHelper:
-            FlowAnalysisHelper(context.typeSystemLegacy, false, featureSet));
+  test_visitParenthesizedExpression() async {
+    await assertNoErrorsInCode('''
+test() => (0);
+''');
+    expect(
+        findNode.parenthesized('(0)').staticType, same(typeProvider.intType));
   }
 
-  DartType _flatten(DartType type) => _typeSystem.flatten(type);
-
-  /// Return an integer literal that has been resolved to the correct type.
-  ///
-  /// @param value the value of the literal
-  /// @return an integer literal that has been resolved to the correct type
-  DoubleLiteral _resolvedDouble(double value) {
-    var literal = AstTestFactory.doubleLiteral(value);
-    literal.staticType = _typeProvider.doubleType;
-    return literal;
+  test_visitSimpleStringLiteral() async {
+    await assertNoErrorsInCode('''
+test() => 'a';
+''');
+    expect(findNode.stringLiteral("'a'").staticType,
+        same(typeProvider.stringType));
   }
 
-  /// Return an integer literal that has been resolved to the correct type.
-  ///
-  /// @param value the value of the literal
-  /// @return an integer literal that has been resolved to the correct type
-  IntegerLiteral _resolvedInteger(int value) {
-    var literal = AstTestFactory.integer(value);
-    literal.staticType = _typeProvider.intType;
-    return literal;
+  test_visitStringInterpolation() async {
+    await assertNoErrorsInCode(r'''
+test() => "a${'b'}c";
+''');
+    expect(findNode.stringInterpolation(r'''"a${'b'}c"''').staticType,
+        same(typeProvider.stringType));
   }
 
-  /// Return a string literal that has been resolved to the correct type.
-  ///
-  /// @param value the value of the literal
-  /// @return a string literal that has been resolved to the correct type
-  SimpleStringLiteral _resolvedString(String value) {
-    var string = AstTestFactory.string2(value);
-    string.staticType = _typeProvider.stringType;
-    return string;
-  }
-
-  /// Return a simple identifier that has been resolved to a variable element
-  /// with the given type.
-  ///
-  /// @param type the type of the variable being represented
-  /// @param variableName the name of the variable
-  /// @return a simple identifier that has been resolved to a variable element
-  ///           with the given type
-  SimpleIdentifier _resolvedVariable(InterfaceType type, String variableName) {
-    var identifier = AstTestFactory.identifier3(variableName);
-    VariableElementImpl element =
-        ElementFactory.localVariableElement(identifier);
-    element.type = type;
-    identifier.staticElement = element;
-    identifier.staticType = type;
-    return identifier;
-  }
+  test_visitSuperExpression() async {
+    await assertNoErrorsInCode('''
+class A {
+  int get foo => 0;
 }
+class B extends A {
+  test() => super.foo;
+}
+late B b;
+''');
+    var bType = findElement.topVar('b').type;
+    expect(findNode.super_('super').staticType, bType);
+  }
 
-class _AnalysisSessionMock implements AnalysisSession {
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+  test_visitSymbolLiteral() async {
+    await assertNoErrorsInCode('''
+test() => #a;
+''');
+    expect(
+        findNode.symbolLiteral('#a').staticType, same(typeProvider.symbolType));
+  }
+
+  test_visitThisExpression() async {
+    await assertNoErrorsInCode('''
+class A {}
+class B extends A {
+  test() => this;
+}
+late B b;
+''');
+    var bType = findElement.topVar('b').type;
+    expect(findNode.this_('this').staticType, bType);
+  }
+
+  test_visitThrowExpression_withValue() async {
+    await assertNoErrorsInCode('''
+test() => throw 0;
+''');
+    var node = findNode.throw_('throw 0');
+    expect(node.staticType, same(typeProvider.bottomType));
+  }
+
+  DartType _flatten(DartType type) => typeSystem.flatten(type);
 }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index e23271d..4cde594 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -3269,7 +3269,8 @@
 class D extends C {
   T f<T extends B>(T x) => null;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 46, 1)]),
     ]);
   }
 
@@ -3283,7 +3284,8 @@
 class D extends C {
   T f<T extends A>(T x) => null;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 101, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 46, 1)]),
     ]);
   }
 
@@ -3295,7 +3297,8 @@
 class D extends C {
   String f<S>(S x) => null;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 74, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 74, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 24, 1)]),
     ]);
   }
 
@@ -3307,7 +3310,8 @@
 class D extends C {
   S f<T, S>(T x) => null;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 59, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 59, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 14, 1)]),
     ]);
   }
 
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 2d48f18..065d67a 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -21,7 +21,6 @@
 import 'invalid_code_test.dart' as invalid_code;
 import 'issues_test.dart' as issues;
 import 'java_core_test.dart' as java_core_test;
-import 'java_io_test.dart' as java_io_test;
 import 'new_as_identifier_parser_test.dart' as new_as_identifier_parser;
 import 'nnbd_parser_test.dart' as nnbd_parser;
 import 'non_error_parser_test.dart' as non_error_parser;
@@ -63,7 +62,6 @@
     invalid_code.main();
     issues.main();
     java_core_test.main();
-    java_io_test.main();
     new_as_identifier_parser.main();
     nnbd_parser.main();
     non_error_parser.main();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index cd93433..dfaa5e0 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -1644,7 +1644,6 @@
     );
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/47951')
   void test_superFormalParameter() {
     var findNode = _parseStringToFindNode(r'''
 class A {
@@ -1666,7 +1665,6 @@
     );
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/47741')
   void test_superFormalParameter_functionTyped() {
     var findNode = _parseStringToFindNode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index b6c9542..4ed178b 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -57,7 +57,7 @@
       'aaa': [getFolder('/aaa/lib')],
       'bbb': [getFolder('/bbb/lib')],
     };
-    return AnalysisDriver.tmp1(
+    return AnalysisDriver(
       scheduler: scheduler,
       logger: logger,
       resourceProvider: resourceProvider,
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index 31462c1..efbf9533f 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -1507,14 +1507,14 @@
     _assertAnalyzedFiles(root, pathList);
   }
 
-  void _assertBasicWorkspace(Workspace _workspace, String posixRoot) {
-    var workspace = _workspace as BasicWorkspace;
+  void _assertBasicWorkspace(Workspace workspace, String posixRoot) {
+    workspace as BasicWorkspace;
     var root = convertPath(posixRoot);
     expect(workspace.root, root);
   }
 
-  void _assertBazelWorkspace(Workspace _workspace, String posixRoot) {
-    var workspace = _workspace as BazelWorkspace;
+  void _assertBazelWorkspace(Workspace workspace, String posixRoot) {
+    workspace as BazelWorkspace;
     var root = convertPath(posixRoot);
     expect(workspace.root, root);
   }
@@ -1526,8 +1526,8 @@
     }
   }
 
-  void _assertPubWorkspace(Workspace _workspace, String posixRoot) {
-    var workspace = _workspace as PubWorkspace;
+  void _assertPubWorkspace(Workspace workspace, String posixRoot) {
+    workspace as PubWorkspace;
     var root = convertPath(posixRoot);
     expect(workspace.root, root);
   }
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 d9bdc60..d56b63b 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -1840,15 +1840,7 @@
     expect(p.declaredElement, same(pElement));
 
     expect(p.identifier.staticElement, same(pElement));
-    assertType(p.identifier.staticType, 'String Function(int)');
-
-    {
-      var type = p.identifier.staticType as FunctionType;
-      expect(type.returnType, typeProvider.stringType);
-
-      expect(type.parameters, hasLength(1));
-      expect(type.parameters[0].type, typeProvider.intType);
-    }
+    assertTypeNull(p.identifier);
 
     _assertNamedTypeSimple(p.type!, typeProvider.stringType);
 
@@ -1886,7 +1878,7 @@
     expect(parameterNode.declaredElement, same(parameterElement));
 
     expect(parameterNode.identifier.staticElement, same(parameterElement));
-    expect(parameterNode.identifier.staticType, typeProvider.intType);
+    assertTypeNull(parameterNode.identifier);
   }
 
   test_formalParameter_simple_fieldFormal_typed() async {
@@ -1916,7 +1908,7 @@
     expect(parameterNode.declaredElement, same(parameterElement));
 
     expect(parameterNode.identifier.staticElement, same(parameterElement));
-    expect(parameterNode.identifier.staticType, typeProvider.intType);
+    assertTypeNull(parameterNode.identifier);
   }
 
   test_forwardingStub_class() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index cb4869d..807866c 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -116,7 +116,7 @@
 
   AnalysisDriver newDriver() {
     var sdk = FolderBasedDartSdk(resourceProvider, sdkRoot);
-    AnalysisDriver driver = AnalysisDriver.tmp1(
+    AnalysisDriver driver = AnalysisDriver(
       scheduler: scheduler,
       logger: logger,
       resourceProvider: resourceProvider,
@@ -819,12 +819,13 @@
       ],
     );
 
-    // All libraries are valid.
-    expect(a_element.isValid, true);
-    expect(b_element.isValid, true);
-    expect(c_element.isValid, true);
-    expect(d_element.isValid, true);
-    expect(e_element.isValid, true);
+    // All libraries have the current session.
+    var session1 = driver.currentSession;
+    expect(a_element.session, session1);
+    expect(b_element.session, session1);
+    expect(c_element.session, session1);
+    expect(d_element.session, session1);
+    expect(e_element.session, session1);
 
     // Change `b.dart`, also removes `c.dart` and `d.dart` that import it.
     // But `a.dart` and `d.dart` is not affected.
@@ -841,12 +842,17 @@
       ],
     );
 
-    // Only `a.dart` and `e.dart` are still valid.
-    expect(a_element.isValid, true);
-    expect(b_element.isValid, false);
-    expect(c_element.isValid, false);
-    expect(d_element.isValid, false);
-    expect(e_element.isValid, true);
+    // We have a new session.
+    var session2 = driver.currentSession;
+    expect(session2, isNot(session1));
+
+    // `a.dart` and `e.dart` moved to the new session.
+    // Invalidated libraries stuck with the old session.
+    expect(a_element.session, session2);
+    expect(b_element.session, session1);
+    expect(c_element.session, session1);
+    expect(d_element.session, session1);
+    expect(e_element.session, session2);
   }
 
   test_changeFile_potentiallyAffected_part() async {
@@ -880,10 +886,11 @@
       ],
     );
 
-    // All libraries are valid.
-    expect(b_element.isValid, true);
-    expect(c_element.isValid, true);
-    expect(d_element.isValid, true);
+    // All libraries have the current session.
+    var session1 = driver.currentSession;
+    expect(b_element.session, session1);
+    expect(c_element.session, session1);
+    expect(d_element.session, session1);
 
     // Change `a.dart`, remove `b.dart` that part it.
     // Removes `c.dart` that imports `b.dart`.
@@ -899,10 +906,15 @@
       ],
     );
 
-    // Only `d.dart` is still valid.
-    expect(b_element.isValid, false);
-    expect(c_element.isValid, false);
-    expect(d_element.isValid, true);
+    // We have a new session.
+    var session2 = driver.currentSession;
+    expect(session2, isNot(session1));
+
+    // `d.dart` moved to the new session.
+    // Invalidated libraries stuck with the old session.
+    expect(b_element.session, session1);
+    expect(c_element.session, session1);
+    expect(d_element.session, session2);
   }
 
   test_changeFile_selfConsistent() async {
@@ -1180,9 +1192,8 @@
     var session2 = driver.currentSession;
     expect(session2, isNotNull);
 
-    // We don't discard the session anymore.
-    // So, the session is always the same.
-    expect(session2, same(session1));
+    // We get a new session.
+    expect(session2, isNot(session1));
   }
 
   test_discoverAvailableFiles_packages() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 29798f2..9375dc1 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -1115,6 +1115,32 @@
     // No exceptions.
   }
 
+  test_isReferencedBy_ParameterElement_ofConstructor_super_named() async {
+    await _indexTestUnit('''
+class A {
+  A({required int a});
+}
+class B extends A {
+  B({required super.a}); // ref
+}
+''');
+    var element = findElement.unnamedConstructor('A').parameter('a');
+    assertThat(element)..isReferencedAt('a}); // ref', true);
+  }
+
+  test_isReferencedBy_ParameterElement_ofConstructor_super_positional() async {
+    await _indexTestUnit('''
+class A {
+  A(int a);
+}
+class B extends A {
+  B(super.a); // ref
+}
+''');
+    var element = findElement.unnamedConstructor('A').parameter('a');
+    assertThat(element)..isReferencedAt('a); // ref', true);
+  }
+
   test_isReferencedBy_ParameterElement_optionalNamed_ofConstructor_genericClass() async {
     await _indexTestUnit('''
 class A<T> {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 91057d0..8e54e31 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -1392,6 +1393,46 @@
     await _verifyReferences(method, expected);
   }
 
+  test_searchReferences_ParameterElement_ofConstructor_super_named() async {
+    await resolveTestCode('''
+class A {
+  A({required int a});
+}
+class B extends A {
+  B({required super.a}); // ref
+}
+''');
+    var element = findElement.unnamedConstructor('A').parameter('a');
+    var expected = [
+      _expectIdQ(
+        findElement.unnamedConstructor('B').superFormalParameter('a'),
+        SearchResultKind.REFERENCE,
+        'a}); // ref',
+      ),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
+  test_searchReferences_ParameterElement_ofConstructor_super_positional() async {
+    await resolveTestCode('''
+class A {
+  A(int a);
+}
+class B extends A {
+  B(super.a); // ref
+}
+''');
+    var element = findElement.unnamedConstructor('A').parameter('a');
+    var expected = [
+      _expectIdQ(
+        findElement.unnamedConstructor('B').superFormalParameter('a'),
+        SearchResultKind.REFERENCE,
+        'a); // ref',
+      ),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_ParameterElement_optionalNamed() async {
     await resolveTestCode('''
 foo({p}) {
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 5a90033..6953e85 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -2,16 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/analysis_context.dart';
-import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
-import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.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';
 
@@ -129,85 +123,76 @@
 }
 
 @reflectiveTest
-class AnalysisSessionImplTest with ResourceProviderMixin {
-  late final AnalysisContextCollection contextCollection;
-  late final AnalysisContext context;
-  late final AnalysisSessionImpl session;
-
-  late final String testContextPath;
-  late final String aaaContextPath;
-  late final String bbbContextPath;
-
-  late final String testPath;
-
-  void setUp() {
-    var sdkRoot = newFolder('/sdk');
-    createMockSdk(
-      resourceProvider: resourceProvider,
-      root: sdkRoot,
-    );
-
-    testContextPath = newFolder('/home/test').path;
-    aaaContextPath = newFolder('/home/aaa').path;
-    bbbContextPath = newFolder('/home/bbb').path;
-
-    newDotPackagesFile('/home/test', content: r'''
-test:lib/
-''');
-
-    contextCollection = AnalysisContextCollectionImpl(
-      includedPaths: [testContextPath, aaaContextPath, bbbContextPath],
-      resourceProvider: resourceProvider,
-      sdkPath: sdkRoot.path,
-    );
-    context = contextCollection.contextFor(testContextPath);
-    session = context.currentSession as AnalysisSessionImpl;
-
-    testPath = convertPath('/home/test/lib/test.dart');
-  }
-
+class AnalysisSessionImplTest extends PubPackageResolutionTest {
   test_getErrors() async {
-    newFile(testPath, content: 'class C {');
-    var errorsResult = await session.getErrorsValid(testPath);
+    var test = newFile(testFilePath, content: 'class C {');
+
+    var session = contextFor(testFilePath).currentSession;
+    var errorsResult = await session.getErrorsValid(test.path);
     expect(errorsResult.session, session);
-    expect(errorsResult.path, testPath);
+    expect(errorsResult.path, test.path);
     expect(errorsResult.errors, isNotEmpty);
   }
 
+  test_getErrors_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getErrors(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getErrors_invalidPath_notAbsolute() async {
+    var session = contextFor(testFilePath).currentSession;
     var errorsResult = await session.getErrors('not_absolute.dart');
     expect(errorsResult, isA<InvalidPathResult>());
   }
 
   test_getFile_invalidPath_notAbsolute() async {
+    var session = contextFor(testFilePath).currentSession;
     var errorsResult = session.getFile('not_absolute.dart');
     expect(errorsResult, isA<InvalidPathResult>());
   }
 
+  test_getFileSync_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getFile(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getFileSync_library() async {
-    var path = convertPath('/home/test/lib/a.dart');
-    newFile(path, content: '');
-    var file = session.getFileValid(path);
-    expect(file.path, path);
+    var a = newFile('$testPackageLibPath/a.dart', content: '');
+
+    var session = contextFor(testFilePath).currentSession;
+    var file = session.getFileValid(a.path);
+    expect(file.path, a.path);
     expect(file.uri.toString(), 'package:test/a.dart');
     expect(file.isPart, isFalse);
   }
 
   test_getFileSync_part() async {
-    var path = convertPath('/home/test/lib/a.dart');
-    newFile(path, content: 'part of lib;');
-    var file = session.getFileValid(path);
-    expect(file.path, path);
+    var a = newFile('$testPackageLibPath/a.dart', content: 'part of lib;');
+
+    var session = contextFor(testFilePath).currentSession;
+    var file = session.getFileValid(a.path);
+    expect(file.path, a.path);
     expect(file.uri.toString(), 'package:test/a.dart');
     expect(file.isPart, isTrue);
   }
 
   test_getLibraryByUri() async {
-    newFile(testPath, content: r'''
+    newFile(testFilePath, content: r'''
 class A {}
 class B {}
 ''');
 
+    var session = contextFor(testFilePath).currentSession;
     var result = await session.getLibraryByUriValid('package:test/test.dart');
     var library = result.element;
     expect(library.getType('A'), isNotNull);
@@ -215,40 +200,53 @@
     expect(library.getType('C'), isNull);
   }
 
+  test_getLibraryByUri_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getLibraryByUriValid('package:test/test.dart'),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getLibraryByUri_unresolvedUri() async {
+    var session = contextFor(testFilePath).currentSession;
     var result = await session.getLibraryByUri('package:foo/foo.dart');
     expect(result, isA<CannotResolveUriResult>());
   }
 
   test_getParsedLibrary() async {
-    newFile(testPath, content: r'''
+    var test = newFile('$testPackageLibPath/a.dart', content: r'''
 class A {}
 class B {}
 ''');
 
-    var parsedLibrary = session.getParsedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var parsedLibrary = session.getParsedLibraryValid(test.path);
     expect(parsedLibrary.session, session);
 
     expect(parsedLibrary.units, hasLength(1));
     {
       var parsedUnit = parsedLibrary.units[0];
       expect(parsedUnit.session, session);
-      expect(parsedUnit.path, testPath);
-      expect(parsedUnit.uri, Uri.parse('package:test/test.dart'));
+      expect(parsedUnit.path, test.path);
+      expect(parsedUnit.uri, Uri.parse('package:test/a.dart'));
       expect(parsedUnit.unit.declarations, hasLength(2));
     }
   }
 
   test_getParsedLibrary_getElementDeclaration_class() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 class A {}
 class B {}
 ''');
 
+    var session = contextFor(testFilePath).currentSession;
     var libraryResult = await session.getLibraryByUriValid(
       'package:test/test.dart',
     );
-    var parsedLibrary = session.getParsedLibraryValid(testPath);
+    var parsedLibrary = session.getParsedLibraryValid(test.path);
 
     var element = libraryResult.element.getType('A')!;
     var declaration = parsedLibrary.getElementDeclaration(element)!;
@@ -259,14 +257,15 @@
   }
 
   test_getParsedLibrary_getElementDeclaration_notThisLibrary() async {
-    newFile(testPath, content: '');
+    var test = newFile(testFilePath, content: '');
 
+    var session = contextFor(testFilePath).currentSession;
     var resolvedUnit =
-        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(test.path) as ResolvedUnitResult;
     var typeProvider = resolvedUnit.typeProvider;
     var intClass = typeProvider.intType.element;
 
-    var parsedLibrary = session.getParsedLibraryValid(testPath);
+    var parsedLibrary = session.getParsedLibraryValid(test.path);
 
     expect(() {
       parsedLibrary.getElementDeclaration(intClass);
@@ -274,13 +273,14 @@
   }
 
   test_getParsedLibrary_getElementDeclaration_synthetic() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 int foo = 0;
 ''');
 
-    var parsedLibrary = session.getParsedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var parsedLibrary = session.getParsedLibraryValid(test.path);
 
-    var unitResult = await session.getUnitElementValid(testPath);
+    var unitResult = await session.getUnitElementValid(test.path);
     var fooElement = unitResult.element.topLevelVariables[0];
     expect(fooElement.name, 'foo');
 
@@ -297,14 +297,25 @@
     expect(parsedLibrary.getElementDeclaration(fooElement.setter!), isNull);
   }
 
+  test_getParsedLibrary_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getParsedLibrary(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getParsedLibrary_invalidPartUri() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 part 'a.dart';
 part ':[invalid uri].dart';
 part 'c.dart';
 ''');
 
-    var parsedLibrary = session.getParsedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var parsedLibrary = session.getParsedLibraryValid(test.path);
 
     expect(parsedLibrary.units, hasLength(3));
     expect(
@@ -322,20 +333,18 @@
   }
 
   test_getParsedLibrary_invalidPath_notAbsolute() async {
+    var session = contextFor(testFilePath).currentSession;
     var result = session.getParsedLibrary('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
   test_getParsedLibrary_notLibrary() async {
-    newFile(testPath, content: 'part of "a.dart";');
-    expect(session.getParsedLibrary(testPath), isA<NotLibraryButPartResult>());
+    var test = newFile(testFilePath, content: 'part of "a.dart";');
+    var session = contextFor(testFilePath).currentSession;
+    expect(session.getParsedLibrary(test.path), isA<NotLibraryButPartResult>());
   }
 
   test_getParsedLibrary_parts() 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');
-
     var aContent = r'''
 part 'b.dart';
 part 'c.dart';
@@ -358,38 +367,40 @@
 class C3 {}
 ''';
 
-    newFile(a, content: aContent);
-    newFile(b, content: bContent);
-    newFile(c, content: cContent);
+    var a = newFile('$testPackageLibPath/a.dart', content: aContent);
+    var b = newFile('$testPackageLibPath/b.dart', content: bContent);
+    var c = newFile('$testPackageLibPath/c.dart', content: cContent);
 
-    var parsedLibrary = session.getParsedLibraryValid(a);
+    var session = contextFor(testFilePath).currentSession;
+    var parsedLibrary = session.getParsedLibraryValid(a.path);
     expect(parsedLibrary.units, hasLength(3));
 
     {
       var aUnit = parsedLibrary.units[0];
-      expect(aUnit.path, a);
+      expect(aUnit.path, a.path);
       expect(aUnit.uri, Uri.parse('package:test/a.dart'));
       expect(aUnit.unit.declarations, hasLength(1));
     }
 
     {
       var bUnit = parsedLibrary.units[1];
-      expect(bUnit.path, b);
+      expect(bUnit.path, b.path);
       expect(bUnit.uri, Uri.parse('package:test/b.dart'));
       expect(bUnit.unit.declarations, hasLength(2));
     }
 
     {
       var cUnit = parsedLibrary.units[2];
-      expect(cUnit.path, c);
+      expect(cUnit.path, c.path);
       expect(cUnit.uri, Uri.parse('package:test/c.dart'));
       expect(cUnit.unit.declarations, hasLength(3));
     }
   }
 
   test_getParsedLibraryByElement() async {
-    newFile(testPath, content: '');
+    var test = newFile(testFilePath, content: '');
 
+    var session = contextFor(testFilePath).currentSession;
     var libraryResult = await session.getLibraryByUriValid(
       'package:test/test.dart',
     );
@@ -401,55 +412,64 @@
 
     {
       var unit = parsedLibrary.units[0];
-      expect(unit.path, testPath);
+      expect(unit.path, test.path);
       expect(unit.uri, Uri.parse('package:test/test.dart'));
       expect(unit.unit, isNotNull);
     }
   }
 
   test_getParsedLibraryByElement_differentSession() async {
-    newFile(testPath, content: '');
+    newFile(testFilePath, content: '');
 
+    var session = contextFor(testFilePath).currentSession;
     var libraryResult = await session.getLibraryByUriValid(
       'package:test/test.dart',
     );
     var element = libraryResult.element;
 
-    var aaaSession =
-        contextCollection.contextFor(aaaContextPath).currentSession;
+    var aaaSession = contextFor('$workspaceRootPath/aaa').currentSession;
 
     var result = aaaSession.getParsedLibraryByElement(element);
     expect(result, isA<NotElementOfThisSessionResult>());
   }
 
   test_getParsedUnit() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 class A {}
 class B {}
 ''');
 
-    var unitResult = session.getParsedUnitValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var unitResult = session.getParsedUnitValid(test.path);
     expect(unitResult.session, session);
-    expect(unitResult.path, testPath);
+    expect(unitResult.path, test.path);
     expect(unitResult.uri, Uri.parse('package:test/test.dart'));
     expect(unitResult.unit.declarations, hasLength(2));
   }
 
+  test_getParsedUnit_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getParsedUnit(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getParsedUnit_invalidPath_notAbsolute() async {
+    var session = contextFor(testFilePath).currentSession;
     var result = session.getParsedUnit('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
   test_getResolvedLibrary() async {
-    var a = convertPath('/home/test/lib/a.dart');
-    var b = convertPath('/home/test/lib/b.dart');
-
     var aContent = r'''
 part 'b.dart';
 
 class A /*a*/ {}
 ''';
-    newFile(a, content: aContent);
+    var a = newFile('$testPackageLibPath/a.dart', content: aContent);
 
     var bContent = r'''
 part of 'a.dart';
@@ -457,9 +477,10 @@
 class B /*b*/ {}
 class B2 extends X {}
 ''';
-    newFile(b, content: bContent);
+    var b = newFile('$testPackageLibPath/b.dart', content: bContent);
 
-    var resolvedLibrary = await session.getResolvedLibraryValid(a);
+    var session = contextFor(testFilePath).currentSession;
+    var resolvedLibrary = await session.getResolvedLibraryValid(a.path);
     expect(resolvedLibrary.session, session);
 
     var typeProvider = resolvedLibrary.typeProvider;
@@ -472,7 +493,7 @@
     var bClass = libraryElement.getType('B')!;
 
     var aUnitResult = resolvedLibrary.units[0];
-    expect(aUnitResult.path, a);
+    expect(aUnitResult.path, a.path);
     expect(aUnitResult.uri, Uri.parse('package:test/a.dart'));
     expect(aUnitResult.content, aContent);
     expect(aUnitResult.unit, isNotNull);
@@ -481,7 +502,7 @@
     expect(aUnitResult.errors, isEmpty);
 
     var bUnitResult = resolvedLibrary.units[1];
-    expect(bUnitResult.path, b);
+    expect(bUnitResult.path, b.path);
     expect(bUnitResult.uri, Uri.parse('package:test/b.dart'));
     expect(bUnitResult.content, bContent);
     expect(bUnitResult.unit, isNotNull);
@@ -505,9 +526,10 @@
   }
 
   test_getResolvedLibrary_getElementDeclaration_notThisLibrary() async {
-    newFile(testPath, content: '');
+    var test = newFile(testFilePath, content: '');
 
-    var resolvedLibrary = await session.getResolvedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var resolvedLibrary = await session.getResolvedLibraryValid(test.path);
 
     expect(() {
       var intClass = resolvedLibrary.typeProvider.intType.element;
@@ -516,11 +538,12 @@
   }
 
   test_getResolvedLibrary_getElementDeclaration_synthetic() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 int foo = 0;
 ''');
 
-    var resolvedLibrary = await session.getResolvedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var resolvedLibrary = await session.getResolvedLibraryValid(test.path);
     var unitElement = resolvedLibrary.element.definingCompilationUnit;
 
     var fooElement = unitElement.topLevelVariables[0];
@@ -539,14 +562,25 @@
     expect(resolvedLibrary.getElementDeclaration(fooElement.setter!), isNull);
   }
 
+  test_getResolvedLibrary_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getResolvedLibrary(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getResolvedLibrary_invalidPartUri() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 part 'a.dart';
 part ':[invalid uri].dart';
 part 'c.dart';
 ''');
 
-    var resolvedLibrary = await session.getResolvedLibraryValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var resolvedLibrary = await session.getResolvedLibraryValid(test.path);
 
     expect(resolvedLibrary.units, hasLength(3));
     expect(
@@ -564,20 +598,23 @@
   }
 
   test_getResolvedLibrary_invalidPath_notAbsolute() async {
+    var session = contextFor(testFilePath).currentSession;
     var result = await session.getResolvedLibrary('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
   test_getResolvedLibrary_notLibrary() async {
-    newFile(testPath, content: 'part of "a.dart";');
+    var test = newFile(testFilePath, content: 'part of "a.dart";');
 
-    var result = await session.getResolvedLibrary(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var result = await session.getResolvedLibrary(test.path);
     expect(result, isA<NotLibraryButPartResult>());
   }
 
   test_getResolvedLibraryByElement() async {
-    newFile(testPath, content: '');
+    var test = newFile(testFilePath, content: '');
 
+    var session = contextFor(testFilePath).currentSession;
     var libraryResult = await session.getLibraryByUriValid(
       'package:test/test.dart',
     );
@@ -586,56 +623,79 @@
     var result = await session.getResolvedLibraryByElementValid(element);
     expect(result.session, session);
     expect(result.units, hasLength(1));
-    expect(result.units[0].path, testPath);
+    expect(result.units[0].path, test.path);
     expect(result.units[0].uri, Uri.parse('package:test/test.dart'));
     expect(result.units[0].unit.declaredElement, isNotNull);
   }
 
   test_getResolvedLibraryByElement_differentSession() async {
-    newFile(testPath, content: '');
+    newFile(testFilePath, content: '');
 
+    var session = contextFor(testFilePath).currentSession;
     var libraryResult = await session.getLibraryByUriValid(
       'package:test/test.dart',
     );
     var element = libraryResult.element;
 
-    var aaaSession =
-        contextCollection.contextFor(aaaContextPath).currentSession;
+    var aaaSession = contextFor('$workspaceRootPath/aaa').currentSession;
 
     var result = await aaaSession.getResolvedLibraryByElement(element);
     expect(result, isA<NotElementOfThisSessionResult>());
   }
 
   test_getResolvedUnit() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 class A {}
 class B {}
 ''');
 
+    var session = contextFor(testFilePath).currentSession;
     var unitResult =
-        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(test.path) as ResolvedUnitResult;
     expect(unitResult.session, session);
-    expect(unitResult.path, testPath);
+    expect(unitResult.path, test.path);
     expect(unitResult.uri, Uri.parse('package:test/test.dart'));
     expect(unitResult.unit.declarations, hasLength(2));
     expect(unitResult.typeProvider, isNotNull);
     expect(unitResult.libraryElement, isNotNull);
   }
 
+  test_getResolvedUnit_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getResolvedUnit(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_getUnitElement() async {
-    newFile(testPath, content: r'''
+    var test = newFile(testFilePath, content: r'''
 class A {}
 class B {}
 ''');
 
-    var unitResult = await session.getUnitElementValid(testPath);
+    var session = contextFor(testFilePath).currentSession;
+    var unitResult = await session.getUnitElementValid(test.path);
     expect(unitResult.session, session);
-    expect(unitResult.path, testPath);
+    expect(unitResult.path, test.path);
     expect(unitResult.uri, Uri.parse('package:test/test.dart'));
     expect(unitResult.element.classes, hasLength(2));
   }
 
+  test_getUnitElement_inconsistent() async {
+    var test = newFile(testFilePath, content: '');
+    var session = contextFor(test.path).currentSession;
+    driverFor(test.path).changeFile(test.path);
+    expect(
+      () => session.getUnitElement(test.path),
+      throwsA(isA<InconsistentAnalysisException>()),
+    );
+  }
+
   test_resourceProvider() async {
+    var session = contextFor(testFilePath).currentSession;
     expect(session.resourceProvider, resourceProvider);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index 082ba9d..eac40aa 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -810,6 +810,30 @@
     _assertSource(";", AstTestFactory.emptyStatement());
   }
 
+  void test_visitEnumDeclaration_constant_arguments_named() {
+    var findNode = _parseStringToFindNode(r'''
+enum E {
+  v<double>.named(42)
+}
+''');
+    _assertSource(
+      'enum E {v<double>.named(42)}',
+      findNode.enumDeclaration('enum E'),
+    );
+  }
+
+  void test_visitEnumDeclaration_constant_arguments_unnamed() {
+    var findNode = _parseStringToFindNode(r'''
+enum E {
+  v<double>(42)
+}
+''');
+    _assertSource(
+      'enum E {v<double>(42)}',
+      findNode.enumDeclaration('enum E'),
+    );
+  }
+
   void test_visitEnumDeclaration_constants_multiple() {
     var findNode = _parseStringToFindNode(r'''
 enum E {one, two}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index ba5aa89..73da833 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -1425,6 +1425,7 @@
 
       if (element is PropertyAccessorElement) {
         var variable = element.variable;
+        expect(variable.enclosingElement, same(element.enclosingElement));
         expect(variable.name, element.displayName);
         if (element.isGetter) {
           expect(variable.type, element.returnType);
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 7d2c061..3f5a183 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -258,6 +258,7 @@
 
   List<String> get experiments => [
         EnableString.constructor_tearoffs,
+        EnableString.enhanced_enums,
         EnableString.named_arguments_anywhere,
         EnableString.super_parameters,
       ];
@@ -312,6 +313,7 @@
   void writeTestPackageConfig(
     PackageConfigFileBuilder config, {
     String? languageVersion,
+    bool ffi = false,
     bool js = false,
     bool meta = false,
   }) {
@@ -323,6 +325,14 @@
       languageVersion: languageVersion ?? testPackageLanguageVersion,
     );
 
+    if (ffi) {
+      var ffiPath = '/packages/ffi';
+      MockPackages.addFfiPackageFiles(
+        getFolder(ffiPath),
+      );
+      config.add(name: 'ffi', rootPath: ffiPath);
+    }
+
     if (js) {
       var jsPath = '/packages/js';
       MockPackages.addJsPackageFiles(
diff --git a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
new file mode 100644
index 0000000..ccb6a78
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. 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/src/dart/constant/value.dart';
+
+/// Prints [DartObjectImpl] as a tree, with values and fields.
+class DartObjectPrinter {
+  final StringBuffer sink;
+
+  DartObjectPrinter(this.sink);
+
+  void write(DartObjectImpl? object, String indent) {
+    if (object != null) {
+      var type = object.type;
+      if (type.isDartCoreDouble) {
+        sink.write('double ');
+        sink.writeln(object.toDoubleValue());
+      } else if (type.isDartCoreInt) {
+        sink.write('int ');
+        sink.writeln(object.toIntValue());
+      } else if (type.isDartCoreString) {
+        sink.write('String ');
+        sink.writeln(object.toStringValue());
+      } else if (object.isUserDefinedObject) {
+        var newIndent = '$indent  ';
+        var typeStr = type.getDisplayString(withNullability: true);
+        sink.writeln(typeStr);
+        var fields = object.fields;
+        if (fields != null) {
+          var sortedFields = SplayTreeMap.of(fields);
+          for (var entry in sortedFields.entries) {
+            sink.write(newIndent);
+            sink.write('${entry.key}: ');
+            write(entry.value, newIndent);
+          }
+        }
+      } else {
+        throw UnimplementedError();
+      }
+    } else {
+      sink.writeln('<null>');
+    }
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index 7a52582..43cf553 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -15,6 +15,223 @@
 
 @reflectiveTest
 class EnumDriverResolutionTest extends PubPackageResolutionTest {
+  test_constructor_argumentList_contextType() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v([]);
+  const E(List<int> a);
+}
+''');
+
+    assertType(findNode.listLiteral('[]'), 'List<int>');
+  }
+
+  test_constructor_argumentList_namedType() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v(<void Function(double)>[]);
+  const E(Object a);
+}
+''');
+
+    assertNamedType(
+      findNode.namedType('double'),
+      doubleElement,
+      'double',
+    );
+
+    assertType(
+      findNode.genericFunctionType('void Function'),
+      'void Function(double)',
+    );
+  }
+
+  test_constructor_generic_noTypeArguments_named() async {
+    await assertNoErrorsInCode(r'''
+enum E<T> {
+  v.named(42);
+  const E.named(T a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: elementMatcher(
+        findElement.constructor('named'),
+        substitution: {'T': 'int'},
+      ),
+    );
+
+    assertParameterElement(
+      findNode.integerLiteral('42'),
+      elementMatcher(
+        findElement.parameter('a'),
+        substitution: {'T': 'int'},
+      ),
+    );
+  }
+
+  test_constructor_generic_noTypeArguments_unnamed() async {
+    await assertNoErrorsInCode(r'''
+enum E<T> {
+  v(42);
+  const E(T a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: elementMatcher(
+        findElement.enum_('E').unnamedConstructor,
+        substitution: {'T': 'int'},
+      ),
+    );
+
+    assertParameterElement(
+      findNode.integerLiteral('42'),
+      elementMatcher(
+        findElement.parameter('a'),
+        substitution: {'T': 'int'},
+      ),
+    );
+  }
+
+  test_constructor_generic_typeArguments_named() async {
+    await assertNoErrorsInCode(r'''
+enum E<T> {
+  v<double>.named(42);
+  const E.named(T a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: elementMatcher(
+        findElement.constructor('named'),
+        substitution: {'T': 'double'},
+      ),
+    );
+
+    assertNamedType(
+      findNode.namedType('double'),
+      doubleElement,
+      'double',
+    );
+
+    assertParameterElement(
+      findNode.integerLiteral('42'),
+      elementMatcher(
+        findElement.parameter('a'),
+        substitution: {'T': 'double'},
+      ),
+    );
+  }
+
+  test_constructor_notGeneric_named() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v.named(42);
+  const E.named(int a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: findElement.constructor('named'),
+    );
+
+    assertParameterElement(
+      findNode.integerLiteral('42'),
+      findElement.parameter('a'),
+    );
+  }
+
+  test_constructor_notGeneric_unnamed() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v(42);
+  const E(int a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: findElement.enum_('E').unnamedConstructor,
+    );
+
+    assertParameterElement(
+      findNode.integerLiteral('42'),
+      findElement.parameter('a'),
+    );
+  }
+
+  test_constructor_notGeneric_unnamed_implicit() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: findElement.enum_('E').unnamedConstructor,
+    );
+  }
+
+  test_constructor_unresolved_named() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v.named(42);
+  const E(int a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: null,
+    );
+
+    assertParameterElement(findNode.integerLiteral('42'), null);
+  }
+
+  test_constructor_unresolved_unnamed() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v(42);
+  const E.named(int a);
+}
+''');
+
+    assertEnumConstant(
+      findNode.enumConstantDeclaration('v'),
+      element: findElement.field('v'),
+      constructorElement: null,
+    );
+
+    assertParameterElement(findNode.integerLiteral('42'), null);
+  }
+
+  test_field() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  final foo = 42;
+}
+''');
+
+    assertElement(
+      findNode.variableDeclaration('foo ='),
+      findElement.field('foo', of: 'E'),
+    );
+  }
+
   test_inference_listLiteral() async {
     await assertNoErrorsInCode(r'''
 enum E1 {a, b}
@@ -27,18 +244,6 @@
     assertType(v.type, 'List<Enum>');
   }
 
-  test_isConstantEvaluated() async {
-    await assertNoErrorsInCode(r'''
-enum E {
-  aaa, bbb
-}
-''');
-
-    expect(findElement.field('aaa').isConstantEvaluated, isTrue);
-    expect(findElement.field('bbb').isConstantEvaluated, isTrue);
-    expect(findElement.field('values').isConstantEvaluated, isTrue);
-  }
-
   test_isEnumConstant() async {
     await assertNoErrorsInCode(r'''
 enum E {
@@ -52,4 +257,65 @@
     expect(findElement.field('index').isEnumConstant, isFalse);
     expect(findElement.field('values').isEnumConstant, isFalse);
   }
+
+  test_method() async {
+    await assertNoErrorsInCode(r'''
+enum E<T> {
+  v;
+  int foo<U>(T t, U u) => 0;
+}
+''');
+
+    assertNamedType(
+      findNode.namedType('T t'),
+      findElement.typeParameter('T'),
+      'T',
+    );
+
+    assertNamedType(
+      findNode.namedType('U u'),
+      findElement.typeParameter('U'),
+      'U',
+    );
+
+    assertSimpleFormalParameter(
+      findNode.simpleFormalParameter('T t'),
+      element: findElement.parameter('t'),
+    );
+
+    assertSimpleFormalParameter(
+      findNode.simpleFormalParameter('U u'),
+      element: findElement.parameter('u'),
+    );
+  }
+
+  test_method_toString() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  String toString() => 'E';
+}
+''');
+
+    assertElement(
+      findNode.methodDeclaration('toString'),
+      findElement.method('toString', of: 'E'),
+    );
+  }
+
+  test_value_underscore() async {
+    await assertNoErrorsInCode(r'''
+enum E { _ }
+
+void f() {
+  E._.index;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('index'),
+      element: findElement.getter('index', of: 'E'),
+      type: 'int',
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index c02261d..384b9be 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -122,7 +122,10 @@
     );
     assertParameterElement(
       indexExpression.index,
-      indexElement.parameters[0],
+      elementMatcher(
+        indexElement.parameters[0],
+        substitution: {'T': 'double'},
+      ),
     );
   }
 
@@ -230,7 +233,10 @@
     }
     assertParameterElement(
       indexExpression.index,
-      indexEqElement.parameters[0],
+      elementMatcher(
+        indexEqElement.parameters[0],
+        substitution: {'T': 'double'},
+      ),
     );
 
     var assignment = indexExpression.parent as AssignmentExpression;
@@ -426,7 +432,10 @@
     }
     assertParameterElement(
       indexExpression.index,
-      indexEqElement.parameters[0],
+      elementMatcher(
+        indexEqElement.parameters[0],
+        substitution: {'T': 'double'},
+      ),
     );
 
     var assignment = indexExpression.parent as AssignmentExpression;
@@ -444,7 +453,10 @@
     );
     assertParameterElement(
       assignment.rightHandSide,
-      indexEqElement.parameters[1],
+      elementMatcher(
+        indexEqElement.parameters[1],
+        substitution: {'T': 'double'},
+      ),
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
index a9868b6..fa4ab1c 100644
--- a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
@@ -11,7 +11,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NullSafetyExperimentGlobalTest);
-    defineReflectiveTests(NullSafetyUsingAllowedExperimentsTest);
     defineReflectiveTests(PackageConfigAndLanguageOverrideTest);
   });
 }
@@ -99,171 +98,6 @@
 }
 
 @reflectiveTest
-class NullSafetyUsingAllowedExperimentsTest extends _FeaturesTest {
-  test_jsonConfig_disable_bin() async {
-    _configureAllowedExperimentsTestNullSafety();
-
-    _configureTestWithJsonConfig('''
-{
-  "configVersion": 2,
-  "packages": [
-    {
-      "name": "test",
-      "rootUri": "../",
-      "packageUri": "lib/",
-      "languageVersion": "2.8"
-    }
-  ]
-}
-''');
-
-    var path = '$testPackageRootPath/bin/a.dart';
-
-    await resolveFileCode(path, r'''
-var x = 0;
-''');
-    assertErrorsInResult([]);
-    assertType(findElement.topVar('x').type, 'int*');
-
-    // Upgrade the language version to `2.10`, so enable Null Safety.
-    _changeFile(path);
-    await resolveFileCode(path, r'''
-// @dart = 2.10
-var x = 0;
-''');
-    assertType(findElement.topVar('x').type, 'int');
-  }
-
-  test_jsonConfig_disable_lib() async {
-    _configureAllowedExperimentsTestNullSafety();
-
-    _configureTestWithJsonConfig('''
-{
-  "configVersion": 2,
-  "packages": [
-    {
-      "name": "test",
-      "rootUri": "../",
-      "packageUri": "lib/",
-      "languageVersion": "2.8"
-    }
-  ]
-}
-''');
-
-    var path = testFilePath;
-
-    await resolveFileCode(path, '''
-var x = 0;
-''');
-    assertErrorsInResult([]);
-    assertType(findElement.topVar('x').type, 'int*');
-
-    // Upgrade the language version to `2.10`, so enable Null Safety.
-    _changeFile(path);
-    await assertNoErrorsInCode('''
-// @dart = 2.10
-var x = 0;
-''');
-    assertType(findElement.topVar('x').type, 'int');
-  }
-
-  test_jsonConfig_enable_bin() async {
-    _configureAllowedExperimentsTestNullSafety();
-
-    _configureTestWithJsonConfig('''
-{
-  "configVersion": 2,
-  "packages": [
-    {
-      "name": "test",
-      "rootUri": "../",
-      "packageUri": "lib/"
-    }
-  ]
-}
-''');
-
-    var path = '$testPackageRootPath/bin/a.dart';
-
-    await resolveFileCode(path, r'''
-var x = 0;
-''');
-    assertErrorsInList(result.errors, []);
-    assertType(findElement.topVar('x').type, 'int');
-
-    // Downgrade the version to `2.8`, so disable Null Safety.
-    _changeFile(path);
-    await resolveFileCode(path, r'''
-// @dart = 2.8
-var x = 0;
-''');
-    assertType(findElement.topVar('x').type, 'int*');
-  }
-
-  test_jsonConfig_enable_lib() async {
-    _configureAllowedExperimentsTestNullSafety();
-
-    _configureTestWithJsonConfig('''
-{
-  "configVersion": 2,
-  "packages": [
-    {
-      "name": "test",
-      "rootUri": "../",
-      "packageUri": "lib/"
-    }
-  ]
-}
-''');
-
-    var path = testFilePath;
-
-    await resolveFileCode(path, '''
-var x = 0;
-''');
-    assertErrorsInResult([]);
-    assertType(findElement.topVar('x').type, 'int');
-
-    // Downgrade the version to `2.8`, so disable Null Safety.
-    _changeFile(path);
-    await assertNoErrorsInCode('''
-// @dart = 2.8
-var x = 0;
-''');
-    assertType(findElement.topVar('x').type, 'int*');
-  }
-
-  void _configureAllowedExperimentsTestNullSafety() {
-    _newSdkExperimentsFile(r'''
-{
-  "version": 1,
-  "experimentSets": {
-    "nullSafety": ["non-nullable"]
-  },
-  "sdk": {
-    "default": {
-      "experimentSet": "nullSafety"
-    }
-  },
-  "packages": {
-    "test": {
-      "experimentSet": "nullSafety"
-    }
-  }
-}
-''');
-  }
-
-  void _newSdkExperimentsFile(String content) {
-    newFile(
-      '${sdkRoot.path}/lib/_internal/allowed_experiments.json',
-      content: content,
-    );
-  }
-}
-
-@reflectiveTest
 class PackageConfigAndLanguageOverrideTest extends _FeaturesTest {
   test_jsonConfigDisablesExtensions() async {
     _configureTestWithJsonConfig('''
@@ -313,15 +147,6 @@
 }
 
 class _FeaturesTest extends PubPackageResolutionTest {
-  /// Do necessary work to ensure that the file with the [path] is considered
-  /// changed for the purpose of following analysis.
-  ///
-  /// Currently we just dispose the whole analysis context collection, so when
-  /// we ask to analyze anything again, we will pick up the new file content.
-  void _changeFile(String path) {
-    disposeAnalysisContextCollection();
-  }
-
   void _configureTestWithJsonConfig(String content) {
     newFile(
       '$testPackageRootPath/.dart_tool/package_config.json',
diff --git a/pkg/analyzer/test/src/dart/resolution/library_element_test.dart b/pkg/analyzer/test/src/dart/resolution/library_element_test.dart
index b569f89..61f0885 100644
--- a/pkg/analyzer/test/src/dart/resolution/library_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/library_element_test.dart
@@ -62,34 +62,6 @@
     ]);
   }
 
-  test_language208_experimentNonNullable() async {
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.8',
-    );
-
-    writeTestPackageAnalysisOptionsFile(
-      AnalysisOptionsFileConfig(experiments: [
-        EnableString.non_nullable,
-      ]),
-    );
-
-    await resolveTestCode('');
-
-    _assertLanguageVersion(
-      package: Version.parse('2.8.0'),
-      override: null,
-    );
-
-    _assertFeatureSet([
-      Feature.constant_update_2018,
-      Feature.control_flow_collections,
-      Feature.extension_methods,
-      Feature.set_literals,
-      Feature.spread_collections,
-    ]);
-  }
-
   test_language208_override205() async {
     writeTestPackageConfig(
       PackageConfigFileBuilder(),
@@ -134,36 +106,6 @@
     ]);
   }
 
-  test_language209_experimentNonNullable_override210() async {
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.9',
-    );
-
-    writeTestPackageAnalysisOptionsFile(
-      AnalysisOptionsFileConfig(experiments: [
-        EnableString.non_nullable,
-      ]),
-    );
-
-    await resolveTestCode('// @dart = 2.10');
-
-    // Valid override, even if greater than the package language version.
-    _assertLanguageVersion(
-      package: Version.parse('2.9.0'),
-      override: Version.parse('2.10.0'),
-    );
-
-    _assertFeatureSet([
-      Feature.constant_update_2018,
-      Feature.control_flow_collections,
-      Feature.extension_methods,
-      Feature.non_nullable,
-      Feature.set_literals,
-      Feature.spread_collections,
-    ]);
-  }
-
   test_language209_override299() async {
     writeTestPackageConfig(
       PackageConfigFileBuilder(),
@@ -210,63 +152,6 @@
     ]);
   }
 
-  test_language210_experimentNonNullable() async {
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.10',
-    );
-
-    writeTestPackageAnalysisOptionsFile(
-      AnalysisOptionsFileConfig(experiments: [
-        EnableString.non_nullable,
-      ]),
-    );
-
-    await resolveTestCode('');
-
-    _assertLanguageVersion(
-      package: Version.parse('2.10.0'),
-      override: null,
-    );
-
-    _assertFeatureSet([
-      Feature.constant_update_2018,
-      Feature.control_flow_collections,
-      Feature.extension_methods,
-      Feature.non_nullable,
-      Feature.set_literals,
-      Feature.spread_collections,
-    ]);
-  }
-
-  test_language210_experimentNonNullable_override209() async {
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.10',
-    );
-
-    writeTestPackageAnalysisOptionsFile(
-      AnalysisOptionsFileConfig(experiments: [
-        EnableString.non_nullable,
-      ]),
-    );
-
-    await resolveTestCode('// @dart = 2.9');
-
-    _assertLanguageVersion(
-      package: Version.parse('2.10.0'),
-      override: Version.parse('2.9.0'),
-    );
-
-    _assertFeatureSet([
-      Feature.constant_update_2018,
-      Feature.control_flow_collections,
-      Feature.extension_methods,
-      Feature.set_literals,
-      Feature.spread_collections,
-    ]);
-  }
-
   void _assertFeatureSet(List<Feature> expected) {
     var featureSet = result.libraryElement.featureSet;
 
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index b17dc6f..2cd36d7 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -2,12 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:collection';
-
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -2181,22 +2177,12 @@
     _assertElementAnnotationValueText(elementAnnotation, expected);
   }
 
-  void _assertDartObjectText(DartObject? object, String expected) {
-    var buffer = StringBuffer();
-    _DartObjectPrinter(buffer).write(object as DartObjectImpl?, '');
-    var actual = buffer.toString();
-    if (actual != expected) {
-      print(buffer);
-    }
-    expect(actual, expected);
-  }
-
   void _assertElementAnnotationValueText(
     ElementAnnotation annotation,
     String expected,
   ) {
     var value = annotation.computeConstantValue();
-    _assertDartObjectText(value, expected);
+    assertDartObjectText(value, expected);
   }
 
   void _assertResolvedNodeText(AstNode node, String expected) {
@@ -2219,39 +2205,3 @@
     return buffer.toString();
   }
 }
-
-class _DartObjectPrinter {
-  final StringBuffer sink;
-
-  _DartObjectPrinter(this.sink);
-
-  void write(DartObjectImpl? object, String indent) {
-    if (object != null) {
-      var type = object.type;
-      if (type.isDartCoreDouble) {
-        sink.write('double ');
-        sink.writeln(object.toDoubleValue());
-      } else if (type.isDartCoreInt) {
-        sink.write('int ');
-        sink.writeln(object.toIntValue());
-      } else if (object.isUserDefinedObject) {
-        var newIndent = '$indent  ';
-        var typeStr = type.getDisplayString(withNullability: true);
-        sink.writeln(typeStr);
-        var fields = object.fields;
-        if (fields != null) {
-          var sortedFields = SplayTreeMap.of(fields);
-          for (var entry in sortedFields.entries) {
-            sink.write(newIndent);
-            sink.write('${entry.key}: ');
-            write(entry.value, newIndent);
-          }
-        }
-      } else {
-        throw UnimplementedError();
-      }
-    } else {
-      sink.writeln('<null>');
-    }
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 6a27317..71d4a5a 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -12,6 +13,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -23,6 +25,7 @@
 import 'package:test/test.dart';
 
 import '../../../generated/test_support.dart';
+import 'dart_object_printer.dart';
 
 final isDynamicType = TypeMatcher<DynamicTypeImpl>();
 
@@ -198,6 +201,16 @@
     );
   }
 
+  void assertDartObjectText(DartObject? object, String expected) {
+    var buffer = StringBuffer();
+    DartObjectPrinter(buffer).write(object as DartObjectImpl?, '');
+    var actual = buffer.toString();
+    if (actual != expected) {
+      print(buffer);
+    }
+    expect(actual, expected);
+  }
+
   void assertElement(Object? nodeOrElement, Object? elementOrMatcher) {
     Element? element;
     if (nodeOrElement is AstNode) {
@@ -285,6 +298,15 @@
     expect(element.enclosingElement, expectedEnclosing);
   }
 
+  void assertEnumConstant(
+    EnumConstantDeclaration node, {
+    required FieldElement element,
+    required Object? constructorElement,
+  }) {
+    assertElement(node.declaredElement, element);
+    assertElement(node.constructorElement, constructorElement);
+  }
+
   Future<void> assertErrorsInCode(
       String code, List<ExpectedError> expectedErrors) async {
     addTestFile(code);
@@ -627,9 +649,9 @@
 
   void assertParameterElement(
     Expression expression,
-    ParameterElement expected,
+    Object? elementOrMatcher,
   ) {
-    expect(expression.staticParameterElement, expected);
+    assertElement(expression.staticParameterElement, elementOrMatcher);
   }
 
   void assertParameterElementType(FormalParameter node, String expected) {
@@ -704,6 +726,13 @@
     assertType(node.staticType, type);
   }
 
+  void assertSimpleFormalParameter(
+    SimpleFormalParameter node, {
+    required ParameterElement element,
+  }) {
+    assertElement(node.declaredElement, element);
+  }
+
   void assertSimpleIdentifier(
     Expression node, {
     required Object? element,
diff --git a/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
index 6a24380..42db1a5 100644
--- a/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -46,9 +47,11 @@
   }
 
   test_invalid_notConstructor() async {
-    await assertNoErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 void f(super.a) {}
-''');
+''', [
+      error(CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 7, 5),
+    ]);
 
     var f = findElement.topFunction('f');
     var element = f.superFormalParameter('a');
@@ -127,4 +130,42 @@
       findElement.unnamedConstructor('B').superFormalParameter('a'),
     );
   }
+
+  test_scoping_inBody() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  final int a;
+  A(this.a);
+}
+
+class B extends A {
+  B(super.a) {
+    a; // ref
+  }
+}
+''');
+
+    assertElement(
+      findNode.simple('a; // ref'),
+      findElement.getter('a', of: 'A'),
+    );
+  }
+
+  test_scoping_inInitializer() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  var f;
+  B(super.a) : f = ((){ a; });
+}
+''');
+
+    assertElement(
+      findNode.simple('a; }'),
+      findElement.unnamedConstructor('B').superFormalParameter('a'),
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
index 01a7d14..ae2f294 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_local_test.dart
@@ -163,4 +163,18 @@
 }
 ''');
   }
+
+  test_parameter_superFormal() async {
+    await assertErrorsInCode('''
+class A {
+  A(int a);
+}
+class B extends A {
+  var x;
+  B(super.a) : x = (() { a = 0; });
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL, 78, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
index ff439eb..efab14b 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
@@ -18,6 +18,17 @@
 @reflectiveTest
 class ConflictingTypeVariableAndMemberClassTest
     extends PubPackageResolutionTest {
+  test_constructor() async {
+    await assertErrorsInCode(r'''
+class A<T> {
+  A.T();
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS, 8,
+          1),
+    ]);
+  }
+
   test_field() async {
     await assertErrorsInCode(r'''
 class A<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_const_super_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_const_super_test.dart
index 9dcfbc5..4b81e48 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_const_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_const_super_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class ConstConstructorWithNonConstSuperTest extends PubPackageResolutionTest {
-  test_explicit() async {
+  test_class_explicit() async {
     await assertErrorsInCode(r'''
 class A {
   A();
@@ -28,7 +28,7 @@
     ]);
   }
 
-  test_implicit() async {
+  test_class_implicit() async {
     await assertErrorsInCode(r'''
 class A {
   A();
@@ -40,4 +40,21 @@
       error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 47, 1),
     ]);
   }
+
+  test_enum() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v
+}
+''');
+  }
+
+  test_enum_hasConstructor() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v(0);
+  const E(int a);
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_named_argument_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_named_argument_test.dart
index cb69a3a..74bca78 100644
--- a/pkg/analyzer/test/src/diagnostics/duplicate_named_argument_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_named_argument_test.dart
@@ -42,6 +42,18 @@
     ]);
   }
 
+  test_constructor_superParameter() async {
+    await assertErrorsInCode(r'''
+class A {
+  A({required int a});
+}
+
+class B extends A {
+  B({required super.a}) : super(a: 0);
+}
+''', [error(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, 88, 1)]);
+  }
+
   test_function() async {
     await assertErrorsInCode(r'''
 f({a, b}) {}
diff --git a/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart b/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart
new file mode 100644
index 0000000..915db60
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/syntactic_errors.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../util/ast_check.dart';
+import '../../util/token_check.dart';
+import 'parser_diagnostics.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtraneousModifierTest);
+  });
+}
+
+@reflectiveTest
+class ExtraneousModifierTest extends ParserDiagnosticsTest {
+  test_simpleFormalParameter_const() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(const a);
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 14, 5),
+    ]);
+    check(parseResult.findNode.simpleFormalParameter('a);'))
+      ..keyword.isKeywordConst
+      ..type.isNull
+      ..identifier.isNotNull;
+  }
+
+  test_simpleFormalParameter_var() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var a);
+}
+''');
+    parseResult.assertNoErrors();
+    check(parseResult.findNode.simpleFormalParameter('a);'))
+      ..keyword.isKeywordVar
+      ..type.isNull
+      ..identifier.isNotNull;
+  }
+
+  test_superFormalParameter_var() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var super.a);
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 14, 3),
+    ]);
+    check(parseResult.findNode.superFormalParameter('super.a'))
+      ..keyword.isKeywordVar
+      ..superKeyword.isKeywordSuper
+      ..type.isNull
+      ..identifier.isNotNull
+      ..typeParameters.isNull
+      ..parameters.isNull;
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart b/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart
new file mode 100644
index 0000000..b9c031c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/syntactic_errors.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../util/ast_check.dart';
+import '../../util/token_check.dart';
+import 'parser_diagnostics.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FunctionTypedParameterVarTest);
+  });
+}
+
+@reflectiveTest
+class FunctionTypedParameterVarTest extends ParserDiagnosticsTest {
+  test_superFormalParameter_var_functionTyped() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var super.a<T>());
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 14, 3),
+    ]);
+    check(parseResult.findNode.superFormalParameter('super.a'))
+      ..keyword.isNull
+      ..superKeyword.isKeywordSuper
+      ..type.isNull
+      ..identifier.isNotNull
+      ..typeParameters.isNotNull.typeParameters.hasLength(1)
+      ..parameters.isNotNull;
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
index a4d4a40..5985dde 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
@@ -51,7 +51,8 @@
 }
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -102,7 +103,8 @@
 }
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -117,7 +119,8 @@
 class B	extends A with M {}
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 77, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index 7d7ecd5..2b5c527 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -26,7 +26,8 @@
   String get g { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 71, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 71, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 20, 1)]),
     ]);
   }
 
@@ -39,8 +40,10 @@
   int f;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 19, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 19, 1)]),
     ]);
   }
 
@@ -58,7 +61,8 @@
   String get getter => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6,
+          contextMessages: [message('/home/test/lib/test.dart', 29, 6)]),
     ]);
   }
 
@@ -74,8 +78,10 @@
   double get g => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 73, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 30, 1)]),
     ]);
   }
 
@@ -89,7 +95,8 @@
 }
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -103,7 +110,8 @@
 }
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -118,7 +126,8 @@
 class B	extends A with M {}
 ''', [
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 77, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -177,7 +186,8 @@
   m({a}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -190,7 +200,8 @@
   m({a, c}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -203,7 +214,8 @@
   m({String a}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -216,7 +228,8 @@
   m(String a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 51, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 51, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -229,7 +242,8 @@
   m(String a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 48, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 48, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -245,8 +259,10 @@
   void m(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 147, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 147, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 147, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 76, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 147, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 29, 1)]),
     ]);
   }
 
@@ -263,7 +279,8 @@
   m(String n) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 54, 1)]),
     ]);
   }
 
@@ -280,8 +297,10 @@
   void m(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 140, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 140, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 140, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 29, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 140, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 76, 1)]),
     ]);
   }
 
@@ -294,7 +313,8 @@
   m([String a]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -311,7 +331,8 @@
   m([String n]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 56, 1)]),
     ]);
   }
 
@@ -324,7 +345,8 @@
   m([a]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -337,7 +359,8 @@
   m(a, b, [c]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -350,7 +373,8 @@
   m(a, [c, d]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -363,7 +387,8 @@
   m(a, b) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 44, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 44, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
     ]);
   }
 
@@ -376,7 +401,8 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 68, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 68, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 1)]),
     ]);
   }
 
@@ -391,7 +417,8 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 98, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 98, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
     ]);
   }
 
@@ -404,7 +431,8 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 77, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 77, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 1)]),
     ]);
   }
 
@@ -417,7 +445,8 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 65, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 65, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 1)]),
     ]);
   }
 
@@ -432,7 +461,8 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 87, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 87, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 1)]),
     ]);
   }
 
@@ -449,7 +479,8 @@
   String m() => '';
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
     ]);
   }
 
@@ -462,7 +493,8 @@
   void m() {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 63, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 63, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 1)]),
     ]);
   }
 
@@ -476,8 +508,10 @@
   int foo = 0;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 3),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 19, 3)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 19, 3)]),
     ]);
   }
 
@@ -491,7 +525,8 @@
   int get foo => 0;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 62, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 62, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 23, 3)]),
     ]);
   }
 
@@ -505,7 +540,8 @@
   int foo() => 0;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 56, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 56, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 19, 3)]),
     ]);
   }
 
@@ -519,7 +555,8 @@
   set foo(int _) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 57, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 57, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 16, 3)]),
     ]);
   }
 
@@ -532,7 +569,8 @@
   void set s(String v) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 66, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 66, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 21, 1)]),
     ]);
   }
 
@@ -549,7 +587,8 @@
   set setter14(String _) => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8,
+          contextMessages: [message('/home/test/lib/test.dart', 77, 8)]),
     ]);
   }
 
@@ -567,7 +606,8 @@
   set setter14(String _) => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8,
+          contextMessages: [message('/home/test/lib/test.dart', 77, 8)]),
     ]);
   }
 
@@ -583,8 +623,10 @@
   set s(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 28, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 68, 1)]),
     ]);
   }
 }
@@ -631,7 +673,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 91, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 91, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 44, 1)]),
     ]);
   }
 
@@ -656,7 +699,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 87, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 87, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
     ]);
   }
 
@@ -681,7 +725,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 81, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 81, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 34, 1)]),
     ]);
   }
 
@@ -706,7 +751,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 82, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 82, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 35, 1)]),
     ]);
   }
 
@@ -731,7 +777,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 31, 1)]),
     ]);
   }
 
@@ -756,7 +803,8 @@
   void set x(num value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
     ]);
   }
 
@@ -906,7 +954,8 @@
   void set x(int value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 34, 1)]),
     ]);
   }
 
@@ -955,7 +1004,8 @@
   void set x(int value);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 86, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 86, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_super_formal_parameter_location_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_super_formal_parameter_location_test.dart
new file mode 100644
index 0000000..adaa449
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_super_formal_parameter_location_test.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidSuperFormalParameterLocationTest);
+  });
+}
+
+@reflectiveTest
+class InvalidSuperFormalParameterLocationTest extends PubPackageResolutionTest {
+  test_class_constructor_external() async {
+    await assertErrorsInCode(r'''
+class A {
+  external A(super.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 23, 5),
+    ]);
+  }
+
+  test_class_constructor_factory() async {
+    await assertErrorsInCode(r'''
+class A {
+  factory A(super.a) {
+    return A._();
+  }
+  A._();
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 22, 5),
+    ]);
+  }
+
+  test_class_constructor_redirecting() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(super.a) : this._();
+  A._();
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 14, 5),
+    ]);
+  }
+
+  test_class_method() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo(super.a) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 21, 5),
+    ]);
+  }
+
+  test_extension_method() async {
+    await assertErrorsInCode(r'''
+extension E on int {
+  void foo(super.a) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 32, 5),
+    ]);
+  }
+
+  test_local_function() async {
+    await assertErrorsInCode(r'''
+void f() {
+  // ignore:unused_element
+  void g(super.a) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 47, 5),
+    ]);
+  }
+
+  test_mixin_method() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  void foo(super.a) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 21, 5),
+    ]);
+  }
+
+  test_unit_function() async {
+    await assertErrorsInCode(r'''
+void f(super.a) {}
+''', [
+      error(CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION, 7, 5),
+    ]);
+  }
+
+  test_valid_optionalNamed() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({int? a});
+}
+
+class B extends A {
+  B({super.a});
+}
+''');
+  }
+
+  test_valid_optionalPositional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A([int? a]);
+}
+
+class B extends A {
+  B([super.a]);
+}
+''');
+  }
+
+  test_valid_requiredNamed() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int a});
+}
+
+class B extends A {
+  B({required super.a});
+}
+''');
+  }
+
+  test_valid_requiredPositional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(super.a);
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
index e292d65..4dc5158 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
@@ -11,11 +11,40 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MissingDefaultValueForParameterTest);
+    defineReflectiveTests(MissingDefaultValueForParameterWithAnnotationTest);
   });
 }
 
 @reflectiveTest
 class MissingDefaultValueForParameterTest extends PubPackageResolutionTest {
+  test_closure_nonNullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+var f = ({int a = 0}) {};
+''');
+  }
+
+  test_closure_nonNullable_named_optional_noDefault() async {
+    await assertErrorsInCode('''
+var f = ({int a}) {};
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 14, 1),
+    ]);
+  }
+
+  test_closure_nonNullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+var f = ([int a = 0]) {};
+''');
+  }
+
+  test_closure_nonNullable_positional_optional_noDefault() async {
+    await assertErrorsInCode('''
+var f = ([int a]) {};
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 14, 1),
+    ]);
+  }
+
   test_constructor_externalFactory_nonNullable_named_optional_noDefault() async {
     await assertNoErrorsInCode('''
 class C {
@@ -81,6 +110,54 @@
     ]);
   }
 
+  test_constructor_generative_nonNullable_named_optional_super_hasDefault_explicit() async {
+    await assertNoErrorsInCode('''
+class A {
+  A({required int a});
+}
+class B extends A{
+  B({super.a = 0});
+}
+''');
+  }
+
+  test_constructor_generative_nonNullable_named_optional_super_hasDefault_fromSuper() async {
+    await assertNoErrorsInCode('''
+class A {
+  A({int a = 0});
+}
+class B extends A{
+  B({super.a});
+}
+''');
+  }
+
+  test_constructor_generative_nonNullable_named_optional_super_noDefault() async {
+    await assertErrorsInCode('''
+class A {
+  A({int? a});
+}
+class B extends A{
+  B({int super.a});
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 61, 1),
+    ]);
+  }
+
+  test_constructor_generative_nonNullable_named_optional_super_noDefault_fromSuper() async {
+    await assertErrorsInCode('''
+class A {
+  A({num a = 1.2});
+}
+class B extends A{
+  B({int super.a});
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 66, 1),
+    ]);
+  }
+
   test_constructor_generative_nonNullable_positional_optional_noDefault() async {
     await assertErrorsInCode('''
 class C {
@@ -91,6 +168,54 @@
     ]);
   }
 
+  test_constructor_generative_nonNullable_positional_optional_super_hasDefault_explicit() async {
+    await assertNoErrorsInCode('''
+class A {
+  A(int a);
+}
+class B extends A{
+  B([super.a = 0]);
+}
+''');
+  }
+
+  test_constructor_generative_nonNullable_positional_optional_super_hasDefault_fromSuper() async {
+    await assertNoErrorsInCode('''
+class A {
+  A([int a = 0]);
+}
+class B extends A{
+  B([super.a]);
+}
+''');
+  }
+
+  test_constructor_generative_nonNullable_positional_optional_super_noDefault() async {
+    await assertErrorsInCode('''
+class A {
+  A([int? a]);
+}
+class B extends A{
+  B([int super.a]);
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 61, 1),
+    ]);
+  }
+
+  test_constructor_generative_nonNullable_positional_optional_super_noDefault_fromSuper() async {
+    await assertErrorsInCode('''
+class A {
+  A([num a = 1.2]);
+}
+class B extends A{
+  B([int super.a]);
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 66, 1),
+    ]);
+  }
+
   test_constructor_generative_nullable_named_optional_noDefault() async {
     await assertNoErrorsInCode('''
 class C {
@@ -538,3 +663,24 @@
     ]);
   }
 }
+
+@reflectiveTest
+class MissingDefaultValueForParameterWithAnnotationTest
+    extends PubPackageResolutionTest {
+  test_method_withAnnotation() async {
+    writeTestPackageConfigWithMeta();
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+class C {
+  void foo({@required int a}) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
+          70,
+          1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
index a0e3db6..a94e1c1 100644
--- a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
@@ -16,44 +16,64 @@
 
 @reflectiveTest
 class NoDefaultSuperConstructorTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin, NoDefaultSuperConstructorTestCases {}
-
-mixin NoDefaultSuperConstructorTestCases on PubPackageResolutionTest {
-  test_explicitDefaultSuperConstructor() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  A();
-}
-class B extends A {
-  B() {}
-}
-''');
-  }
-
-  test_implicitDefaultSuperConstructor() async {
-    await assertNoErrorsInCode(r'''
-class A {
-}
-class B extends A {
-  B() {}
-}
-''');
-  }
-
-  test_missingDefaultSuperConstructor_explicitConstructor() async {
+    with WithoutNullSafetyMixin, NoDefaultSuperConstructorTestCases {
+  test_super_requiredPositional_subclass_explicit() async {
     await assertErrorsInCode(r'''
 class A {
   A(p);
 }
 class B extends A {
-  B() {}
+  B();
 }
 ''', [
       error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, 42, 1),
     ]);
   }
+}
 
-  test_missingDefaultSuperConstructor_externalConstructor() async {
+mixin NoDefaultSuperConstructorTestCases on PubPackageResolutionTest {
+  test_super_implicit_subclass_explicit() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_implicit_subclass_implicit() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {}
+''');
+  }
+
+  test_super_noParameters() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A();
+}
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_requiredPositional_subclass_explicit_language214() async {
+    await assertErrorsInCode(r'''
+// @dart = 2.14
+class A {
+  A(p);
+}
+class B extends A {
+  B();
+}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, 58, 1),
+    ]);
+  }
+
+  test_super_requiredPositional_subclass_external() async {
     await assertNoErrorsInCode(r'''
 class A {
   A(p);
@@ -64,24 +84,14 @@
 ''');
   }
 
-  test_missingDefaultSuperConstructor_implicitConstructor() async {
+  test_super_requiredPositional_subclass_implicit() async {
     await assertErrorsInCode(r'''
 class A {
   A(p);
 }
-class B extends A {
-}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 26, 1),
-    ]);
-  }
-
-  test_missingDefaultSuperConstructor_onlyNamedSuperConstructor() async {
-    await assertErrorsInCode(r'''
-class A { A.named() {} }
 class B extends A {}
 ''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 31, 1),
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 26, 1),
     ]);
   }
 }
@@ -89,7 +99,69 @@
 @reflectiveTest
 class NoDefaultSuperConstructorWithNullSafetyTest
     extends PubPackageResolutionTest with NoDefaultSuperConstructorTestCases {
-  test_super_requiredParameter_legacySubclass_explicitConstructor() async {
+  test_super_optionalNamed_subclass_explicit() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({int? a});
+}
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_optionalNamed_subclass_implicit() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({int? a});
+}
+class B extends A {}
+''');
+  }
+
+  test_super_optionalNamed_subclass_superParameter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({int? a});
+}
+class B extends A {
+  B({super.a});
+}
+''');
+  }
+
+  test_super_optionalPositional_subclass_explicit() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A([int? a]);
+}
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_optionalPositional_subclass_implicit() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A([int? a]);
+}
+class B extends A {}
+''');
+  }
+
+  test_super_optionalPositional_subclass_superParameter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A([int? a]);
+}
+class B extends A {
+  B(super.a);
+}
+''');
+  }
+
+  test_super_requiredNamed_legacySubclass_explicitConstructor() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   A({required String s});
@@ -105,11 +177,11 @@
 ''');
   }
 
-  test_super_requiredParameter_legacySubclass_implicitConstructor() async {
+  test_super_requiredNamed_legacySubclass_implicitConstructor() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   A({required String s});
-}
+}O
 ''');
     await assertNoErrorsInCode(r'''
 // @dart=2.8
@@ -118,4 +190,132 @@
 class B extends A {}
 ''');
   }
+
+  test_super_requiredNamed_subclass_explicit() async {
+    await assertErrorsInCode(r'''
+class A {
+  A({required int? a});
+}
+class B extends A {
+  B();
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
+          58,
+          1),
+    ]);
+  }
+
+  test_super_requiredNamed_subclass_implicit() async {
+    await assertErrorsInCode(r'''
+class A {
+  A({required int? a});
+}
+class B extends A {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 42, 1),
+    ]);
+  }
+
+  test_super_requiredNamed_subclass_superParameter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int? a});
+}
+class B extends A {
+  B({required super.a});
+}
+''');
+  }
+
+  test_super_requiredNamed_subclass_superParameter_oneLeft() async {
+    await assertErrorsInCode(r'''
+class A {
+  A({required int? a, required int? b});
+}
+class B extends A {
+  B({required super.a});
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT,
+          75,
+          1),
+    ]);
+  }
+
+  test_super_requiredNamed_subclass_superParameter_optionalNamed_hasDefault() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int? a});
+}
+class B extends A {
+  B({super.a = 0});
+}
+''');
+  }
+
+  test_super_requiredNamed_subclass_superParameter_optionalNamed_noDefault() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int? a});
+}
+class B extends A {
+  B({super.a});
+}
+''');
+  }
+
+  test_super_requiredPositional_subclass_explicit() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p);
+}
+class B extends A {
+  B();
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS,
+          42,
+          1),
+    ]);
+  }
+
+  test_super_requiredPositional_subclass_superParameter_optionalPositional_withDefault() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int? a);
+}
+class B extends A {
+  B([super.a = 0]);
+}
+''');
+  }
+
+  test_super_requiredPositional_subclass_superParameter_optionalPositional_withoutDefault() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int? a);
+}
+class B extends A {
+  B([super.a]);
+}
+''');
+  }
+
+  test_super_requiredPositional_subclass_superParameter_requiredPositional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int? a);
+}
+class B extends A {
+  B(super.a);
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
index e8e1418..dcb8a8f 100644
--- a/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
@@ -86,4 +86,28 @@
       error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 65, 2),
     ]);
   }
+
+  test_superParameter_optional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int? a);
+}
+
+class B extends A {
+  B([super.a]) : super();
+}
+''');
+  }
+
+  test_superParameter_required() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(super.a) : super();
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
index 2bae72c..21454e6 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
@@ -30,7 +30,8 @@
   @override
   int c = 0;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 134, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 134, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 39, 1)]),
     ]);
   }
 
@@ -49,7 +50,8 @@
   @override
   int c = 0;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 131, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 131, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 39, 1)]),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart b/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart
new file mode 100644
index 0000000..975d781
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+
+import '../../generated/test_support.dart';
+
+class ParserDiagnosticsTest {
+  ExpectedError error(
+    ErrorCode code,
+    int offset,
+    int length, {
+    Pattern? correctionContains,
+    String? text,
+    List<Pattern> messageContains = const [],
+    List<ExpectedContextMessage> contextMessages = const [],
+  }) {
+    return ExpectedError(
+      code,
+      offset,
+      length,
+      correctionContains: correctionContains,
+      message: text,
+      messageContains: messageContains,
+      expectedContextMessages: contextMessages,
+    );
+  }
+
+  ParseStringResult parseStringWithErrors(String content) {
+    return parseString(
+      content: content,
+      featureSet: FeatureSet.fromEnableFlags2(
+        sdkLanguageVersion: ExperimentStatus.currentVersion,
+        flags: [
+          Feature.enhanced_enums.enableString,
+          Feature.super_parameters.enableString,
+        ],
+      ),
+      throwIfDiagnostics: false,
+    );
+  }
+}
+
+extension ParseStringResultExtension on ParseStringResult {
+  FindNode get findNode {
+    return FindNode(content, unit);
+  }
+
+  void assertErrors(List<ExpectedError> expectedErrors) {
+    var errorListener = GatheringErrorListener();
+    errorListener.addAll(errors);
+    errorListener.assertErrors(expectedErrors);
+  }
+
+  void assertNoErrors() {
+    assertErrors(const []);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/positional_super_formal_parameter_with_positional_argument_test.dart b/pkg/analyzer/test/src/diagnostics/positional_super_formal_parameter_with_positional_argument_test.dart
new file mode 100644
index 0000000..ddde7c2
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/positional_super_formal_parameter_with_positional_argument_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(
+        PositionalSuperFormalParameterWithPositionalArgumentTest);
+  });
+}
+
+@reflectiveTest
+class PositionalSuperFormalParameterWithPositionalArgumentTest
+    extends PubPackageResolutionTest {
+  test_notReported() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(super.a) : super();
+}
+''');
+  }
+
+  test_reported() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(int a, int b);
+}
+
+class B extends A {
+  B(super.b) : super(0);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT,
+          62,
+          1)
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
index 63d6735..968dd96 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
@@ -27,6 +27,17 @@
     ]);
   }
 
+  test_Finalizable() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+class C extends Finalizable {}
+''', [
+      error(FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS, 35, 11),
+      error(CompileTimeErrorCode.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS, 35,
+          11),
+    ]);
+  }
+
   test_Float() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
@@ -169,6 +180,13 @@
     ]);
   }
 
+  test_Finalizable() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+class C implements Finalizable {}
+''');
+  }
+
   test_Float() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
diff --git a/pkg/analyzer/test/src/diagnostics/super_formal_parameter_type_is_not_subtype_of_associated_test.dart b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_type_is_not_subtype_of_associated_test.dart
new file mode 100644
index 0000000..b32c05c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_type_is_not_subtype_of_associated_test.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperFormalParameterTypeIsNotSubtypeOfAssociatedTest);
+  });
+}
+
+@reflectiveTest
+class SuperFormalParameterTypeIsNotSubtypeOfAssociatedTest
+    extends PubPackageResolutionTest {
+  test_generic_requiredPositional_explicit_notSubtype() async {
+    await assertErrorsInCode(r'''
+class A<T> {
+  A(T a);
+}
+
+class B extends A<int> {
+  B(num super.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+          65,
+          1),
+    ]);
+  }
+
+  test_generic_requiredPositional_explicit_same() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  A(T a);
+}
+
+class B extends A<num> {
+  B(num super.a);
+}
+''');
+  }
+
+  test_generic_requiredPositional_explicit_subtype() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  A(T a);
+}
+
+class B extends A<num> {
+  B(int super.a);
+}
+''');
+  }
+
+  test_requiredNamed_explicit_notSubtype() async {
+    await assertErrorsInCode(r'''
+class A {
+  A({required int a});
+}
+
+class B extends A {
+  B({required num super.a});
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+          80,
+          1),
+    ]);
+  }
+
+  test_requiredNamed_explicit_same() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required num a});
+}
+
+class B extends A {
+  B({required num super.a});
+}
+''');
+  }
+
+  test_requiredNamed_explicit_subtype() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required num a});
+}
+
+class B extends A {
+  B({required int super.a});
+}
+''');
+  }
+
+  test_requiredNamed_inherited() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int a});
+}
+
+class B extends A {
+  B({required super.a});
+}
+''');
+  }
+
+  test_requiredPositional_explicit_notSubtype() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(num super.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+          59,
+          1),
+    ]);
+  }
+
+  /// No implicit coercions, like downcast from `dynamic`.
+  test_requiredPositional_explicit_notSubtype_dynamic() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(dynamic super.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
+          63,
+          1),
+    ]);
+  }
+
+  test_requiredPositional_explicit_same() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(num a);
+}
+
+class B extends A {
+  B(num super.a);
+}
+''');
+  }
+
+  test_requiredPositional_explicit_subtype() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(num a);
+}
+
+class B extends A {
+  B(int super.a);
+}
+''');
+  }
+
+  test_requiredPositional_inherited() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(super.a);
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_named_test.dart b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_named_test.dart
new file mode 100644
index 0000000..80bb982
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_named_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperFormalParameterWithoutAssociatedNamedTest);
+  });
+}
+
+@reflectiveTest
+class SuperFormalParameterWithoutAssociatedNamedTest
+    extends PubPackageResolutionTest {
+  test_explicit_optional() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B({super.a}) : super();
+}
+''', [
+      error(
+          CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
+          43,
+          1)
+    ]);
+  }
+
+  test_explicit_required() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B({required super.a}) : super();
+}
+''', [
+      error(
+          CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
+          52,
+          1)
+    ]);
+  }
+
+  test_implicit_optional() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B({super.a});
+}
+''', [
+      error(
+          CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
+          43,
+          1)
+    ]);
+  }
+
+  test_implicit_required() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B({required super.a});
+}
+''', [
+      error(
+          CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
+          52,
+          1)
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_positional_test.dart b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_positional_test.dart
new file mode 100644
index 0000000..c88f091
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/super_formal_parameter_without_associated_positional_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperFormalParameterWithoutAssociatedPositionalTest);
+  });
+}
+
+@reflectiveTest
+class SuperFormalParameterWithoutAssociatedPositionalTest
+    extends PubPackageResolutionTest {
+  test_explicit_optional() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B([super.a]) : super();
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+          43,
+          1)
+    ]);
+  }
+
+  test_explicit_required() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B(super.a) : super();
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+          42,
+          1)
+    ]);
+  }
+
+  test_implicit_optional() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B([super.a]);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+          43,
+          1)
+    ]);
+  }
+
+  test_implicit_required() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  B(super.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
+          42,
+          1)
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 485fb55..2529d3a 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -194,6 +194,7 @@
     as extra_annotation_on_struct_field;
 import 'extra_positional_arguments_test.dart' as extra_positional_arguments;
 import 'extra_size_annotation_carray_test.dart' as extra_size_annotation_carray;
+import 'extraneous_modifier_test.dart' as extraneous_modifier;
 import 'ffi_leaf_call_must_not_use_handle_test.dart'
     as ffi_leaf_call_must_not_use_handle;
 import 'ffi_native_test.dart' as ffi_native_test;
@@ -227,6 +228,7 @@
     as for_in_of_invalid_element_type;
 import 'for_in_of_invalid_type_test.dart' as for_in_of_invalid_type;
 import 'for_in_with_const_variable_test.dart' as for_in_with_const_variable;
+import 'function_typed_parameter_var_test.dart' as function_typed_parameter_var;
 import 'generic_function_type_cannot_be_bound_test.dart'
     as generic_function_type_cannot_be_bound;
 import 'generic_struct_subclass_test.dart' as generic_struct_subclass;
@@ -346,6 +348,8 @@
 import 'invalid_required_positional_param_test.dart'
     as invalid_required_positional_param;
 import 'invalid_sealed_annotation_test.dart' as invalid_sealed_annotation;
+import 'invalid_super_formal_parameter_location_test.dart'
+    as invalid_super_formal_parameter_location;
 import 'invalid_super_in_initializer_test.dart' as invalid_super_in_initializer;
 import 'invalid_type_argument_in_const_list_test.dart'
     as invalid_type_argument_in_const_list;
@@ -542,6 +546,8 @@
 import 'packed_nesting_non_packed_test.dart' as packed_nesting_non_packed;
 import 'part_of_different_library_test.dart' as part_of_different_library;
 import 'part_of_non_part_test.dart' as part_of_non_part;
+import 'positional_super_formal_parameter_with_positional_argument_test.dart'
+    as positional_super_formal_parameter_with_positional_argument;
 import 'prefix_collides_with_top_level_member_test.dart'
     as prefix_collides_with_top_level_member;
 import 'prefix_identifier_not_followed_by_dot_test.dart'
@@ -622,6 +628,12 @@
 import 'subtype_of_ffi_class_test.dart' as subtype_of_ffi_class;
 import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
 import 'subtype_of_struct_class_test.dart' as subtype_of_struct_class;
+import 'super_formal_parameter_type_is_not_subtype_of_associated_test.dart'
+    as super_formal_parameter_type_is_not_subtype_of_associated;
+import 'super_formal_parameter_without_associated_named_test.dart'
+    as super_formal_parameter_without_associated_named;
+import 'super_formal_parameter_without_associated_positional_test.dart'
+    as super_formal_parameter_without_associated_positional;
 import 'super_in_extension_test.dart' as super_in_extension;
 import 'super_in_invalid_context_test.dart' as super_in_invalid_context;
 import 'super_in_redirecting_constructor_test.dart'
@@ -855,6 +867,7 @@
     extra_annotation_on_struct_field.main();
     extra_positional_arguments.main();
     extra_size_annotation_carray.main();
+    extraneous_modifier.main();
     ffi_leaf_call_must_not_use_handle.main();
     ffi_native_test.main();
     field_in_struct_with_initializer.main();
@@ -874,6 +887,7 @@
     for_in_of_invalid_element_type.main();
     for_in_of_invalid_type.main();
     for_in_with_const_variable.main();
+    function_typed_parameter_var.main();
     generic_function_type_cannot_be_bound.main();
     generic_struct_subclass.main();
     getter_not_assignable_setter_types.main();
@@ -952,6 +966,7 @@
     invalid_required_optional_positional_param.main();
     invalid_required_positional_param.main();
     invalid_sealed_annotation.main();
+    invalid_super_formal_parameter_location.main();
     invalid_super_in_initializer.main();
     invalid_type_argument_in_const_list.main();
     invalid_type_argument_in_const_map.main();
@@ -1082,6 +1097,7 @@
     packed_nesting_non_packed.main();
     part_of_different_library.main();
     part_of_non_part.main();
+    positional_super_formal_parameter_with_positional_argument.main();
     prefix_collides_with_top_level_member.main();
     prefix_identifier_not_followed_by_dot.main();
     prefix_shadowed_by_local_declaration.main();
@@ -1132,6 +1148,9 @@
     subtype_of_ffi_class.main();
     subtype_of_sealed_class.main();
     subtype_of_struct_class.main();
+    super_formal_parameter_type_is_not_subtype_of_associated.main();
+    super_formal_parameter_without_associated_named.main();
+    super_formal_parameter_without_associated_positional.main();
     super_in_extension.main();
     super_in_invalid_context.main();
     super_in_redirecting_constructor.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
index 483d1dc..9c11a5e 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
@@ -15,6 +15,19 @@
 
 @reflectiveTest
 class UndefinedMethodTest extends PubPackageResolutionTest {
+  test_conditional_expression_condition_context() async {
+    await assertErrorsInCode('''
+T castObject<T>(Object value) => value as T;
+
+main() {
+  (castObject(true)..whatever()) ? 1 : 2;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_METHOD, 76, 8,
+          messageContains: ["type 'bool'"]),
+    ]);
+  }
+
   test_constructor_defined() async {
     await assertNoErrorsInCode(r'''
 class C {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index c377ca0..fb070cc 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -1700,6 +1700,78 @@
 
 @reflectiveTest
 class UnusedElementWithNullSafetyTest extends PubPackageResolutionTest {
+  test_class_isUsed_isExpression_expression() async {
+    await assertNoErrorsInCode('''
+class _A {}
+void f(Object p) {
+  if (_A() is int) {
+  }
+}
+''');
+  }
+
+  test_class_notUsed_isExpression_typeArgument() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is List<_A>) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_isExpression_typeInFunctionType() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is void Function(_A)) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_isExpression_typeInTypeParameter() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is void Function<T extends _A>()) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_variableDeclaration() async {
+    await assertErrorsInCode('''
+class _A {}
+void f() {
+  _A? v;
+  print(v);
+}
+print(x) {}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_variableDeclaration_typeArgument() async {
+    await assertErrorsInCode('''
+class _A {}
+main() {
+  List<_A>? v;
+  print(v);
+}
+print(x) {}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
   test_optionalParameter_isUsed_genericConstructor() async {
     await assertNoErrorsInCode('''
 class C<T> {
@@ -1786,6 +1858,98 @@
     expect(result.errors, isNotEmpty);
   }
 
+  test_parameter_optionalNamed_fieldFormal_isUsed_constructorInvocation() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A({this.f});
+}
+f() => _A(f: 0);
+''');
+  }
+
+  test_parameter_optionalNamed_fieldFormal_isUsed_factoryRedirect() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A({this.f});
+  factory _A.named({int? f}) = _A;
+}
+f() => _A.named(f: 0);
+''');
+  }
+
+  test_parameter_optionalNamed_fieldFormal_notUsed() async {
+    await assertErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A({this.f});
+}
+f() => _A();
+''', [
+      error(HintCode.UNUSED_ELEMENT_PARAMETER, 38, 1),
+    ]);
+  }
+
+  test_parameter_optionalNamed_fieldFormal_notUsed_factoryRedirect() async {
+    await assertErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A({this.f});
+  factory _A.named() = _A;
+}
+f() => _A.named();
+''', [
+      error(HintCode.UNUSED_ELEMENT_PARAMETER, 38, 1),
+    ]);
+  }
+
+  test_parameter_optionalPositional_fieldFormal_isUsed_constructorInvocation() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A([this.f]);
+}
+f() => _A(0);
+''');
+  }
+
+  test_parameter_optionalPositional_fieldFormal_isUsed_factoryRedirect() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A([this.f]);
+  factory _A.named([int a]) = _A;
+}
+f() => _A.named(0);
+''');
+  }
+
+  test_parameter_optionalPositional_fieldFormal_notUsed() async {
+    await assertErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A([this.f]);
+}
+f() => _A();
+''', [
+      error(HintCode.UNUSED_ELEMENT_PARAMETER, 38, 1),
+    ]);
+  }
+
+  test_parameter_optionalPositional_fieldFormal_notUsed_factoryRedirect() async {
+    await assertErrorsInCode(r'''
+class _A {
+  final int? f;
+  _A([this.f]);
+  factory _A.named() = _A;
+}
+f() => _A.named();
+''', [
+      error(HintCode.UNUSED_ELEMENT_PARAMETER, 38, 1),
+    ]);
+  }
+
   test_typeAlias_interfaceType_isUsed_typeName_isExpression() async {
     await assertNoErrorsInCode(r'''
 typedef _A = List<int>;
diff --git a/pkg/analyzer/test/src/diagnostics/unused_result_test.dart b/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
index cce3dca..812bf13 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
@@ -363,6 +363,62 @@
     ]);
   }
 
+  test_getter_expressionStatement_id_dotResult_dotId() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class A {
+  @useResult
+  int get foo => 0;
+}
+
+void f(A a) {
+  a.foo.isEven;
+}
+''');
+  }
+
+  test_getter_expressionStatement_result() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@useResult
+int get foo => 0;
+
+void f() {
+  foo;
+}
+''', [
+      error(HintCode.UNUSED_RESULT, 77, 3),
+    ]);
+  }
+
+  test_getter_expressionStatement_result_dotId() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@useResult
+int get foo => 0;
+
+void f() {
+  foo.isEven;
+}
+''');
+  }
+
+  test_getter_expressionStatement_result_dotId_dotId() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@useResult
+int get foo => 0;
+
+void f() {
+  foo.isEven.hashCode;
+}
+''');
+  }
+
   test_getter_result_passed() async {
     await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/fasta/ast_builder_test.dart b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
index be10148..c31f6e7 100644
--- a/pkg/analyzer/test/src/fasta/ast_builder_test.dart
+++ b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
@@ -4,10 +4,13 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer_utilities/check/check.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/parser_test_base.dart';
+import '../../util/ast_check.dart';
+import '../../util/token_check.dart';
+import '../diagnostics/parser_diagnostics.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -16,14 +19,15 @@
 }
 
 @reflectiveTest
-class AstBuilderTest extends FastaParserTestCase {
+class AstBuilderTest extends ParserDiagnosticsTest {
   void test_constructor_factory_misnamed() {
-    CompilationUnit unit = parseCompilationUnit('''
+    var parseResult = parseStringWithErrors(r'''
 class A {
   factory B() => throw 0;
 }
 ''');
-    expect(unit, isNotNull);
+    parseResult.assertNoErrors();
+    var unit = parseResult.unit;
     expect(unit.declarations, hasLength(1));
     var declaration = unit.declarations[0] as ClassDeclaration;
     expect(declaration, isNotNull);
@@ -36,14 +40,15 @@
   }
 
   void test_constructor_wrongName() {
-    CompilationUnit unit = parseCompilationUnit('''
+    var parseResult = parseStringWithErrors(r'''
 class A {
   B() : super();
 }
-''', errors: [
-      expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 12, 1),
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 12, 1),
     ]);
-    expect(unit, isNotNull);
+    var unit = parseResult.unit;
     expect(unit.declarations, hasLength(1));
     var declaration = unit.declarations[0] as ClassDeclaration;
     expect(declaration, isNotNull);
@@ -54,14 +59,15 @@
   }
 
   void test_getter_sameNameAsClass() {
-    CompilationUnit unit = parseCompilationUnit('''
+    var parseResult = parseStringWithErrors(r'''
 class A {
   get A => 0;
 }
-''', errors: [
-      expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
     ]);
-    expect(unit, isNotNull);
+    var unit = parseResult.unit;
     expect(unit.declarations, hasLength(1));
     var declaration = unit.declarations[0] as ClassDeclaration;
     expect(declaration, isNotNull);
@@ -71,4 +77,21 @@
     expect(member.isGetter, isTrue);
     expect(member.name.name, 'A');
   }
+
+  void test_superFormalParameter() {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(super.a);
+}
+''');
+    parseResult.assertNoErrors();
+    check(parseResult.findNode.superFormalParameter('super.a'))
+      ..type.isNull
+      ..superKeyword.isKeywordSuper
+      ..identifier.which((it) => it
+        ..name.isEqualTo('a')
+        ..inDeclarationContext.isTrue)
+      ..typeParameters.isNull
+      ..parameters.isNull;
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 4fb0b3a..5b4aab2 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -318,11 +318,7 @@
       _writeElements('fields', e.fields, _writePropertyInducingElement);
 
       var constructors = e.constructors;
-      if (e.isEnum) {
-        expect(constructors, isEmpty);
-      } else {
-        expect(constructors, isNotEmpty);
-      }
+      expect(constructors, isNotEmpty);
       _writeElements('constructors', constructors, _writeConstructorElement);
 
       _writeElements('accessors', e.accessors, _writePropertyAccessorElement);
@@ -501,6 +497,17 @@
     _assertNonSyntheticElementSelf(e);
   }
 
+  void _writeFieldFormalParameterField(ParameterElement e) {
+    if (e is FieldFormalParameterElement) {
+      var field = e.field;
+      if (field != null) {
+        _writeElementReference('field', field);
+      } else {
+        _writelnWithIndent('field: <null>');
+      }
+    }
+  }
+
   void _writeFunctionElement(FunctionElement e) {
     _writeIndentedLine(() {
       _writeIf(e.isExternal, 'external ');
@@ -671,6 +678,7 @@
       _writeParameterElements(e.parameters);
       _writeConstantInitializer(e);
       _writeNonSyntheticElement(e);
+      _writeFieldFormalParameterField(e);
       _writeSuperConstructorParameter(e);
     });
   }
@@ -764,6 +772,7 @@
       _writeIf(e.isLate, 'late ');
       _writeIf(e.isFinal, 'final ');
       _writeIf(e.isConst, 'const ');
+      _writeIf(e is FieldElementImpl && e.isEnumConstant, 'enumConstant ');
 
       _writeName(e);
     });
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 3f5806f..3ca0b95 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -821,6 +821,19 @@
   }
 
   @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    _writeln('ImplicitCallReference');
+    _withIndent(() {
+      var properties = _Properties();
+      properties.addNode('expression', node.expression);
+      properties.addNode('typeArguments', node.typeArguments);
+      properties.addTypeList('typeArgumentTypes', node.typeArgumentTypes);
+      _addExpression(properties, node);
+      _writeProperties(properties);
+    });
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _writeNextCodeLine(node);
     _writeln('ImportDirective');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3d50b66..2610746 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -100,6 +100,7 @@
     sdkLanguageVersion: Version.parse('2.16.0'),
     flags: [
       EnableString.constructor_tearoffs,
+      EnableString.enhanced_enums,
       EnableString.super_parameters,
     ],
   );
@@ -246,6 +247,7 @@
             parameters
               requiredPositional final this.x @36
                 type: dynamic
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -272,6 +274,7 @@
             parameters
               requiredPositional final this.x @32
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -298,6 +301,7 @@
             parameters
               requiredPositional final this.x @28
                 type: dynamic
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -332,6 +336,7 @@
                 parameters
                   requiredPositional b @37
                     type: double
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -366,6 +371,7 @@
                 parameters
                   requiredPositional b @41
                     type: double
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -403,6 +409,7 @@
                 parameters
                   requiredPositional t @53
                     type: T
+                field: self::@class::C::@field::f
         accessors
           synthetic get f @-1
             returnType: dynamic Function()
@@ -433,6 +440,7 @@
             parameters
               requiredPositional final this.x @17
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: int
@@ -465,6 +473,7 @@
             parameters
               requiredPositional final this.x @17
                 type: dynamic
+                field: <null>
 ''');
   }
 
@@ -484,6 +493,7 @@
             parameters
               requiredPositional final this.x @32
                 type: dynamic
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: num
@@ -510,6 +520,7 @@
             parameters
               requiredPositional final this.x @28
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: num
@@ -536,6 +547,7 @@
             parameters
               requiredPositional final this.x @24
                 type: num
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: num
@@ -562,6 +574,7 @@
             parameters
               requiredPositional final this.x @32
                 type: dynamic
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -588,6 +601,7 @@
             parameters
               requiredPositional final this.x @28
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -614,6 +628,7 @@
             parameters
               requiredPositional final this.x @24
                 type: dynamic
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -640,6 +655,7 @@
             parameters
               optionalNamed final this.x @25
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: int
@@ -670,6 +686,7 @@
                   IntegerLiteral
                     literal: 42 @28
                     staticType: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: int
@@ -696,6 +713,7 @@
             parameters
               optionalPositional final this.x @25
                 type: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: int
@@ -726,6 +744,7 @@
                   IntegerLiteral
                     literal: 42 @29
                     staticType: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: int
@@ -1453,7 +1472,6 @@
 ''');
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/47951')
   test_class_constructor_parameters_super_explicitType_function() async {
     var library = await checkLibrary('''
 class A {
@@ -1492,7 +1510,6 @@
 ''');
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/47951')
   test_class_constructor_parameters_super_explicitType_interface() async {
     var library = await checkLibrary('''
 class A {
@@ -1518,13 +1535,45 @@
         constructors
           @47
             parameters
-              requiredPositional final super.a @49
+              requiredPositional final super.a @59
                 type: int
                 superConstructorParameter: a@18
             superConstructor: self::@class::A::@constructor::•
 ''');
   }
 
+  test_class_constructor_parameters_super_explicitType_interface_nullable() async {
+    var library = await checkLibrary('''
+class A {
+  A(num? a);
+}
+
+class B extends A {
+  B(int? super.a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class A @6
+        constructors
+          @12
+            parameters
+              requiredPositional a @19
+                type: num?
+      class B @32
+        supertype: A
+        constructors
+          @48
+            parameters
+              requiredPositional final super.a @61
+                type: int?
+                superConstructorParameter: a@19
+            superConstructor: self::@class::A::@constructor::•
+''');
+  }
+
   test_class_constructor_parameters_super_invalid_topFunction() async {
     var library = await checkLibrary('''
 void f(super.a) {}
@@ -1615,6 +1664,38 @@
 ''');
   }
 
+  test_class_constructor_parameters_super_optionalNamed_unresolved2() async {
+    var library = await checkLibrary('''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B({super.a});
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class A @6
+        constructors
+          @12
+            parameters
+              requiredPositional a @18
+                type: int
+      class B @31
+        supertype: A
+        constructors
+          @47
+            parameters
+              optionalNamed final super.a @56
+                type: dynamic
+                superConstructorParameter: <null>
+            superConstructor: self::@class::A::@constructor::•
+''');
+  }
+
   test_class_constructor_parameters_super_optionalPositional() async {
     var library = await checkLibrary('''
 class A {
@@ -1770,6 +1851,38 @@
 ''');
   }
 
+  test_class_constructor_parameters_super_requiredPositional_unresolved2() async {
+    var library = await checkLibrary('''
+class A {
+  A({required int a})
+}
+
+class B extends A {
+  B(super.a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class A @6
+        constructors
+          @12
+            parameters
+              requiredNamed a @28
+                type: int
+      class B @41
+        supertype: A
+        constructors
+          @57
+            parameters
+              requiredPositional final super.a @65
+                type: dynamic
+                superConstructorParameter: <null>
+            superConstructor: self::@class::A::@constructor::•
+''');
+  }
+
   test_class_constructor_params() async {
     var library = await checkLibrary('class C { C(x, int y); }');
     checkElementText(library, r'''
@@ -3546,6 +3659,7 @@
             parameters
               requiredPositional final this.foo @36
                 type: int
+                field: self::@class::A::@field::foo
         accessors
           synthetic get foo @-1
             returnType: int
@@ -3574,6 +3688,7 @@
             parameters
               requiredPositional final this.v @34
                 type: int
+                field: self::@class::C::@field::v
             superConstructor: self::@class::D::@constructor::•
         accessors
           synthetic get v @-1
@@ -8186,33 +8301,110 @@
         codeLength: 26
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const aaa @11
+          static const enumConstant aaa @11
             codeOffset: 11
             codeLength: 3
             type: E
-          static const bbb @16
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant bbb @16
             codeOffset: 16
             codeLength: 3
             type: E
-          static const ccc @21
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant ccc @21
             codeOffset: 21
             codeLength: 3
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::aaa
+                    staticType: E
+                    token: aaa @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::bbb
+                    staticType: E
+                    token: bbb @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::ccc
+                    staticType: E
+                    token: ccc @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get aaa @-1
             returnType: E
           synthetic static get bbb @-1
             returnType: E
           synthetic static get ccc @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -9781,12 +9973,14 @@
             parameters
               requiredPositional final this.t @41
                 type: T
+                field: self::@class::C::@field::t
           const named @55
             periodOffset: 54
             nameEnd: 60
             parameters
               requiredPositional final this.t @66
                 type: T
+                field: self::@class::C::@field::t
         accessors
           synthetic get t @-1
             returnType: T
@@ -12431,6 +12625,7 @@
                     staticElement: self::@function::foo
                     staticType: int Function()
                     token: foo @40
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -12472,6 +12667,7 @@
                     staticElement: dart:core::@class::num::@method::+
                     staticInvokeType: num Function(num)
                     staticType: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -12510,6 +12706,7 @@
                     staticElement: dart:core::@class::num::@method::+
                     staticInvokeType: num Function(num)
                     staticType: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -13356,27 +13553,104 @@
       enum E @30
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @33
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @36
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant c @39
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @33
-            type: E
-          static const b @36
-            type: E
-          static const c @39
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
           synthetic static get c @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -15574,27 +15848,104 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @8
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant c @14
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @8
-            type: E
-          static const b @11
-            type: E
-          static const c @14
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
           synthetic static get c @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -15627,19 +15978,50 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @8
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @8
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -15821,6 +16203,7 @@
                     staticType: void Function(dynamic)
                     typeArgumentTypes
                       dynamic
+                field: self::@class::X::@field::f
         accessors
           synthetic get f @-1
             returnType: void Function(dynamic)
@@ -16596,50 +16979,181 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @8
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @8
-            type: E
-          static const b @11
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
       enum E @19
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant c @22
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant d @25
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant e @28
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const c @22
-            type: E
-          static const d @25
-            type: E
-          static const e @28
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::d
+                    staticType: E
+                    token: d @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::e
+                    staticType: E
+                    token: e @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get c @-1
             returnType: E
           synthetic static get d @-1
             returnType: E
           synthetic static get e @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -16861,6 +17375,477 @@
 ''');
   }
 
+  test_enum_constant_inference() async {
+    var library = await checkLibrary(r'''
+enum E<T> {
+  int(1), string('2');
+  const E(T a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          covariant T @7
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          static const enumConstant int @14
+            type: E<int>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  arguments
+                    IntegerLiteral
+                      literal: 1 @18
+                      staticType: int
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: int}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: int}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<int>
+                staticType: E<int>
+          static const enumConstant string @22
+            type: E<String>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  arguments
+                    SimpleStringLiteral
+                      literal: '2' @29
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: String}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: String}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<String>
+                staticType: E<String>
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::int
+                    staticType: E<int>
+                    token: int @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::string
+                    staticType: E<String>
+                    token: string @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          const @43
+            parameters
+              requiredPositional a @47
+                type: T
+        accessors
+          synthetic static get int @-1
+            returnType: E<int>
+          synthetic static get string @-1
+            returnType: E<String>
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  /// Test that a constant named `_name` renames the synthetic `name` field.
+  test_enum_constant_name() async {
+    var library = await checkLibrary(r'''
+enum E {
+  _name;
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant _name @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::_name
+                    staticType: E
+                    token: _name @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get _name @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_constant_typeArguments() async {
+    var library = await checkLibrary(r'''
+enum E<T> {
+  v<double>(42);
+  const E(T a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          covariant T @7
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          static const enumConstant v @14
+            type: E<double>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  arguments
+                    IntegerLiteral
+                      literal: 42 @24
+                      staticType: double
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: double}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: double}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<double>
+                    typeArguments: TypeArgumentList
+                      arguments
+                        NamedType
+                          name: SimpleIdentifier
+                            staticElement: dart:core::@class::double
+                            staticType: null
+                            token: double @16
+                          type: double
+                      leftBracket: < @15
+                      rightBracket: > @22
+                staticType: E<double>
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E<double>
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          const @37
+            parameters
+              requiredPositional a @41
+                type: T
+        accessors
+          synthetic static get v @-1
+            returnType: E<double>
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_constant_underscore() async {
+    var library = await checkLibrary('''
+enum E {
+  _
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant _ @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::_
+                    staticType: E
+                    token: _ @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get _ @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_constructor_named() async {
+    var library = await checkLibrary(r'''
+enum E {
+  v.named(42);
+  const E.named(int a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant v @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  arguments
+                    IntegerLiteral
+                      literal: 42 @19
+                      staticType: int
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::named
+                    staticType: null
+                    token: named @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::named
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          const named @34
+            periodOffset: 33
+            nameEnd: 39
+            parameters
+              requiredPositional a @44
+                type: int
+        accessors
+          synthetic static get v @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_constructor_unnamed() async {
+    var library = await checkLibrary(r'''
+enum E {
+  v(42);
+  const E(int a);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant v @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  arguments
+                    IntegerLiteral
+                      literal: 42 @13
+                      staticType: int
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          const @26
+            parameters
+              requiredPositional a @32
+                type: int
+        accessors
+          synthetic static get v @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
   test_enum_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -16876,19 +17861,675 @@
         documentationComment: /**\n * Docs\n */
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v @69
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v @69
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_field() async {
+    var library = await checkLibrary(r'''
+enum E {
+  v;
+  final foo = 42;
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant v @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+          final foo @22
+            type: int
+            constantInitializer
+              IntegerLiteral
+                literal: 42 @28
+                staticType: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+          synthetic get foo @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_method() async {
+    var library = await checkLibrary(r'''
+enum E<T> {
+  v;
+  int foo<U>(T t, U u) => 0;
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          covariant T @7
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          static const enumConstant v @14
+            type: E<dynamic>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: dynamic}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: dynamic}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<dynamic>
+                staticType: E<dynamic>
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E<dynamic>
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E<dynamic>
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          foo @23
+            typeParameters
+              covariant U @27
+            parameters
+              requiredPositional t @32
+                type: T
+              requiredPositional u @37
+                type: U
+            returnType: int
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_method_toString() async {
+    var library = await checkLibrary(r'''
+enum E {
+  v;
+  String toString() => 'E';
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        supertype: Enum
+        fields
+          static const enumConstant v @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
+        methods
+          toString @23
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters() async {
+    var library = await checkLibrary('''
+enum E<T> {
+  v
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          covariant T @7
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          static const enumConstant v @14
+            type: E<dynamic>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: dynamic}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: dynamic}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<dynamic>
+                staticType: E<dynamic>
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E<dynamic>
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E<dynamic>
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_bound() async {
+    var library = await checkLibrary('''
+enum E<T extends num, U extends T> {
+  v
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      notSimplyBounded enum E @5
+        typeParameters
+          covariant T @7
+            bound: num
+            defaultType: num
+          covariant U @22
+            bound: T
+            defaultType: num
+        supertype: Enum
+        fields
+          static const enumConstant v @39
+            type: E<num, num>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: num, U: num}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: num, U: num}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<num, num>
+                staticType: E<num, num>
+          synthetic static const values @-1
+            type: List<E<num, num>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E<num, num>
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<num, num>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E<num, num>
+          synthetic static get values @-1
+            returnType: List<E<num, num>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_cycle_1of1() async {
+    var library = await checkLibrary('''
+enum E<T extends T> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      notSimplyBounded enum E @5
+        typeParameters
+          covariant T @7
+            bound: dynamic
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_cycle_2of3() async {
+    var library = await checkLibrary(r'''
+enum E<T extends V, U extends num, V extends T> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      notSimplyBounded enum E @5
+        typeParameters
+          covariant T @7
+            bound: dynamic
+            defaultType: dynamic
+          covariant U @20
+            bound: num
+            defaultType: num
+          covariant V @35
+            bound: dynamic
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic, num, dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic, num, dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic, num, dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_defaultType_cycle_genericFunctionType() async {
+    var library = await checkLibrary(r'''
+enum E<T extends void Function(E)> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      notSimplyBounded enum E @5
+        typeParameters
+          covariant T @7
+            bound: void Function(E<dynamic>)
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_variance_contravariant() async {
+    var library = await checkLibrary('''
+enum E<in T> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          contravariant T @10
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_variance_covariant() async {
+    var library = await checkLibrary('''
+enum E<out T> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          covariant T @11
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_variance_invariant() async {
+    var library = await checkLibrary('''
+enum E<inout T> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          invariant T @13
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+''');
+  }
+
+  test_enum_typeParameters_variance_multiple() async {
+    var library = await checkLibrary('''
+enum E<inout T, in U, out V> {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @5
+        typeParameters
+          invariant T @13
+            defaultType: dynamic
+          contravariant U @19
+            defaultType: dynamic
+          covariant V @26
+            defaultType: dynamic
+        supertype: Enum
+        fields
+          synthetic static const values @-1
+            type: List<E<dynamic, dynamic, dynamic>>
+            constantInitializer
+              ListLiteral
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic, dynamic, dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get values @-1
+            returnType: List<E<dynamic, dynamic, dynamic>>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -16912,25 +18553,79 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const a @32
+          static const enumConstant a @32
             documentationComment: /**\n   * aaa\n   */
             type: E
-          static const b @47
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @47
             documentationComment: /// bbb
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -16959,11 +18654,7 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const a @46
+          static const enumConstant a @46
             documentationComment: /**\n   * aaa\n   */
             metadata
               Annotation
@@ -16974,7 +18665,26 @@
                   staticType: null
                   token: annotation @33
             type: E
-          static const b @75
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @75
             documentationComment: /// bbb
             metadata
               Annotation
@@ -16985,15 +18695,54 @@
                   staticType: null
                   token: annotation @62
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -17019,23 +18768,77 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v1 @9
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant v2 @13
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v1 @9
-            type: E
-          static const v2 @13
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v1
+                    staticType: E
+                    token: v1 @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v2
+                    staticType: E
+                    token: v2 @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v1 @-1
             returnType: E
           synthetic static get v2 @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -17051,38 +18854,100 @@
       enum E1 @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v1 @10
+            type: E1
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E1::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E1::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E1
+                      staticType: null
+                      token: E1 @-1
+                    type: E1
+                staticType: E1
           synthetic static const values @-1
             type: List<E1>
-          static const v1 @10
-            type: E1
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E1::@getter::v1
+                    staticType: E1
+                    token: v1 @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E1>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E1>
           synthetic static get v1 @-1
             returnType: E1
+          synthetic static get values @-1
+            returnType: List<E1>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
       enum E2 @20
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v2 @25
+            type: E2
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E2::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E2::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E2
+                      staticType: null
+                      token: E2 @-1
+                    type: E2
+                staticType: E2
           synthetic static const values @-1
             type: List<E2>
-          static const v2 @25
-            type: E2
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E2::@getter::v2
+                    staticType: E2
+                    token: v2 @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E2>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E2>
           synthetic static get v2 @-1
             returnType: E2
+          synthetic static get values @-1
+            returnType: List<E2>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -17156,27 +19021,104 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @8
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant c @14
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @8
-            type: E
-          static const b @11
-            type: E
-          static const c @14
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
           synthetic static get c @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -17862,6 +19804,7 @@
         parameters
           requiredPositional final this.a @16
             type: int
+            field: <null>
         returnType: void
 ''');
   }
@@ -17882,6 +19825,7 @@
               IntegerLiteral
                 literal: 42 @20
                 staticType: int
+            field: <null>
         returnType: void
 ''');
   }
@@ -17901,6 +19845,7 @@
             parameters
               requiredPositional b @22
                 type: int
+            field: <null>
         returnType: void
 ''');
   }
@@ -19495,6 +21440,63 @@
 ''');
   }
 
+  test_implicitCallTearoff() async {
+    var library = await checkLibrary(r'''
+class C {
+  void call() {}
+}
+
+class D {
+  const D(C c) : this.named(c);
+
+  const D.named(void Function() f);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class C @6
+        constructors
+          synthetic @-1
+        methods
+          call @17
+            returnType: void
+      class D @36
+        constructors
+          const @48
+            parameters
+              requiredPositional c @52
+                type: C
+            constantInitializers
+              RedirectingConstructorInvocation
+                argumentList: ArgumentList
+                  arguments
+                    ImplicitCallReference
+                      expression: SimpleIdentifier
+                        staticElement: c@52
+                        staticType: C
+                        token: c @68
+                      staticType: void Function()
+                  leftParenthesis: ( @67
+                  rightParenthesis: ) @69
+                constructorName: SimpleIdentifier
+                  staticElement: self::@class::D::@constructor::named
+                  staticType: null
+                  token: named @62
+                period: . @61
+                staticElement: self::@class::D::@constructor::named
+                thisKeyword: this @57
+            redirectedConstructor: self::@class::D::@constructor::named
+          const named @83
+            periodOffset: 82
+            nameEnd: 88
+            parameters
+              requiredPositional f @105
+                type: void Function()
+''');
+  }
+
   test_implicitConstructor_named_const() async {
     var library = await checkLibrary('''
 class C {
@@ -19518,6 +21520,7 @@
             parameters
               requiredPositional final this.x @49
                 type: Object
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: Object
@@ -22407,6 +24410,7 @@
             parameters
               requiredPositional final this.foo @41
                 type: dynamic
+                field: <null>
             returnType: void
 ''');
   }
@@ -22432,6 +24436,7 @@
             parameters
               requiredPositional final this.x @23
                 type: dynamic
+                field: <null>
             returnType: void
 ''');
   }
@@ -23952,11 +25957,7 @@
       enum E @19
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const v @26
+          static const enumConstant v @26
             metadata
               Annotation
                 atSign: @ @23
@@ -23966,13 +25967,48 @@
                   staticType: null
                   token: a @24
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -24015,6 +26051,7 @@
             parameters
               requiredPositional final this.value @48
                 type: dynamic
+                field: self::@class::A::@field::value
         accessors
           synthetic get value @-1
             returnType: dynamic
@@ -24022,11 +26059,7 @@
       enum E @64
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const a @78
+          static const enumConstant a @78
             metadata
               Annotation
                 arguments: ArgumentList
@@ -24043,9 +26076,47 @@
                   staticType: null
                   token: A @71
             type: E
-          static const b @83
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @83
             type: E
-          static const c @96
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant c @96
             metadata
               Annotation
                 arguments: ArgumentList
@@ -24062,17 +26133,60 @@
                   staticType: null
                   token: A @89
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
           synthetic static get c @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -24096,19 +26210,50 @@
               token: a @15
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v @26
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v @26
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -24349,6 +26494,7 @@
                       staticElement: self::@getter::a
                       staticType: null
                       token: a @40
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -24398,6 +26544,7 @@
                   NullLiteral
                     literal: null @48
                     staticType: Null
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -25593,11 +27740,7 @@
               token: foo @17
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
-          synthetic static const values @-1
-            type: List<E>
-          static const e1 @37
+          static const enumConstant e1 @37
             metadata
               Annotation
                 atSign: @ @32
@@ -25607,9 +27750,47 @@
                   staticType: null
                   token: foo @33
             type: E
-          static const e2 @43
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant e2 @43
             type: E
-          static const e3 @54
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant e3 @54
             metadata
               Annotation
                 atSign: @ @49
@@ -25619,17 +27800,60 @@
                   staticType: null
                   token: foo @50
             type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::e1
+                    staticType: E
+                    token: e1 @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::e2
+                    staticType: E
+                    token: e2 @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::e3
+                    staticType: E
+                    token: e3 @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get e1 @-1
             returnType: E
           synthetic static get e2 @-1
             returnType: E
           synthetic static get e3 @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -26646,6 +28870,95 @@
 ''');
   }
 
+  test_metadata_typeParameter_ofEnum() async {
+    var library = await checkLibrary('''
+const a = 42;
+enum E<@a T> {
+  v
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    enums
+      enum E @19
+        typeParameters
+          covariant T @24
+            defaultType: dynamic
+            metadata
+              Annotation
+                atSign: @ @21
+                element: <null>
+                name: SimpleIdentifier
+                  staticElement: <null>
+                  staticType: null
+                  token: a @22
+        supertype: Enum
+        fields
+          static const enumConstant v @31
+            type: E<dynamic>
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: ConstructorMember
+                      base: self::@enum::E::@constructor::•
+                      substitution: {T: dynamic}
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: ConstructorMember
+                    base: self::@enum::E::@constructor::•
+                    substitution: {T: dynamic}
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E<dynamic>
+                staticType: E<dynamic>
+          synthetic static const values @-1
+            type: List<E<dynamic>>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E<dynamic>
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E<dynamic>>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
+        accessors
+          synthetic static get v @-1
+            returnType: E<dynamic>
+          synthetic static get values @-1
+            returnType: List<E<dynamic>>
+          synthetic get index @-1
+            returnType: int
+        methods
+          synthetic toString @-1
+            returnType: String
+    topLevelVariables
+      static const a @6
+        type: int
+        constantInitializer
+          IntegerLiteral
+            literal: 42 @10
+            staticType: int
+    accessors
+      synthetic static get a @-1
+        returnType: int
+''');
+  }
+
   test_metadata_typeParameter_ofFunction() async {
     var library = await checkLibrary('const a = null; f<@a T>() {}');
     checkElementText(library, r'''
@@ -26837,27 +29150,104 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant a @8
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant b @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+          static const enumConstant c @14
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const a @8
-            type: E
-          static const b @11
-            type: E
-          static const c @14
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::c
+                    staticType: E
+                    token: c @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get a @-1
             returnType: E
           synthetic static get b @-1
             returnType: E
           synthetic static get c @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -28148,31 +30538,86 @@
       enum E @5
         supertype: Enum
         fields
+          static const enumConstant a @11
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+            nonSynthetic: self::@enum::E::@field::a
+          static const enumConstant b @14
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
+            nonSynthetic: self::@enum::E::@field::b
+          synthetic static const values @-1
+            type: List<E>
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::a
+                    staticType: E
+                    token: a @-1
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::b
+                    staticType: E
+                    token: b @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+            nonSynthetic: self::@enum::E
           synthetic final index @-1
             type: int
             nonSynthetic: self::@enum::E
-          synthetic static const values @-1
-            type: List<E>
+        constructors
+          synthetic const @-1
             nonSynthetic: self::@enum::E
-          static const a @11
-            type: E
-            nonSynthetic: self::@enum::E::@constant::a
-          static const b @14
-            type: E
-            nonSynthetic: self::@enum::E::@constant::b
         accessors
-          synthetic get index @-1
-            returnType: int
-            nonSynthetic: self::@enum::E
+          synthetic static get a @-1
+            returnType: E
+            nonSynthetic: self::@enum::E::@field::a
+          synthetic static get b @-1
+            returnType: E
+            nonSynthetic: self::@enum::E::@field::b
           synthetic static get values @-1
             returnType: List<E>
             nonSynthetic: self::@enum::E
-          synthetic static get a @-1
-            returnType: E
-            nonSynthetic: self::@enum::E::@constant::a
-          synthetic static get b @-1
-            returnType: E
-            nonSynthetic: self::@enum::E::@constant::b
+          synthetic get index @-1
+            returnType: int
+            nonSynthetic: self::@enum::E
         methods
           synthetic toString @-1
             returnType: String
@@ -28775,6 +31220,7 @@
                   IntegerLiteral
                     literal: 1 @44
                     staticType: int
+                field: self::@class::C::@field::x
           named @53
             periodOffset: 52
             nameEnd: 58
@@ -28785,6 +31231,7 @@
                   IntegerLiteral
                     literal: 1 @68
                     staticType: int
+                field: self::@class::C::@field::x
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -29368,6 +31815,32 @@
 ''');
   }
 
+  test_type_inference_classField_fromNullSafe_toLegacy() async {
+    testFile = convertPath('/home/test/lib/test.dart');
+    addLibrarySource('/home/test/lib/a.dart', '''
+class E {
+  static final a = 0;
+}
+''');
+    var library = await checkLibrary('''
+// @dart = 2.9
+import 'a.dart';
+final v = E.a;
+''');
+    checkElementText(library, r'''
+library
+  imports
+    package:test/a.dart
+  definingUnit
+    topLevelVariables
+      static final v @38
+        type: int*
+    accessors
+      synthetic static get v @-1
+        returnType: int*
+''');
+  }
+
   test_type_inference_closure_with_function_typed_parameter() async {
     var library = await checkLibrary('''
 var x = (int f(String x)) => 0;
@@ -29464,6 +31937,7 @@
             parameters
               requiredPositional final this.value @34
                 type: T
+                field: self::@class::A::@field::value
         accessors
           synthetic get value @-1
             returnType: T
@@ -29521,6 +31995,7 @@
             parameters
               requiredPositional final this.value @34
                 type: T
+                field: self::@class::A::@field::value
         accessors
           synthetic get value @-1
             returnType: T
@@ -29602,6 +32077,7 @@
             parameters
               requiredPositional final this.f @35
                 type: int
+                field: self::@class::A::@field::f
         accessors
           synthetic get f @-1
             returnType: int
@@ -29786,6 +32262,7 @@
             parameters
               requiredPositional final this.f @85
                 type: T
+                field: self::@class::C::@field::f
         accessors
           synthetic get f @-1
             returnType: T
@@ -30117,19 +32594,50 @@
       enum E @16
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v @20
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v @20
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -30224,19 +32732,50 @@
         enum E @27
           supertype: Enum
           fields
-            synthetic final index @-1
-              type: int
+            static const enumConstant v @31
+              type: E
+              constantInitializer
+                InstanceCreationExpression
+                  argumentList: ArgumentList
+                    leftParenthesis: ( @0
+                    rightParenthesis: ) @0
+                  constructorName: ConstructorName
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E::@constructor::•
+                      staticType: null
+                      token:  @-1
+                    period: . @0
+                    staticElement: self::@enum::E::@constructor::•
+                    type: NamedType
+                      name: SimpleIdentifier
+                        staticElement: self::@enum::E
+                        staticType: null
+                        token: E @-1
+                      type: E
+                  staticType: E
             synthetic static const values @-1
               type: List<E>
-            static const v @31
-              type: E
+              constantInitializer
+                ListLiteral
+                  elements
+                    SimpleIdentifier
+                      staticElement: self::@enum::E::@getter::v
+                      staticType: E
+                      token: v @-1
+                  leftBracket: [ @0
+                  rightBracket: ] @0
+                  staticType: List<E>
+            synthetic final index @-1
+              type: int
+          constructors
+            synthetic const @-1
           accessors
-            synthetic get index @-1
-              returnType: int
-            synthetic static get values @-1
-              returnType: List<E>
             synthetic static get v @-1
               returnType: E
+            synthetic static get values @-1
+              returnType: List<E>
+            synthetic get index @-1
+              returnType: int
           methods
             synthetic toString @-1
               returnType: String
@@ -30265,19 +32804,50 @@
       enum E @42
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v @46
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v @46
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
@@ -30343,19 +32913,50 @@
         enum E @27
           supertype: Enum
           fields
-            synthetic final index @-1
-              type: int
+            static const enumConstant v @31
+              type: E
+              constantInitializer
+                InstanceCreationExpression
+                  argumentList: ArgumentList
+                    leftParenthesis: ( @0
+                    rightParenthesis: ) @0
+                  constructorName: ConstructorName
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E::@constructor::•
+                      staticType: null
+                      token:  @-1
+                    period: . @0
+                    staticElement: self::@enum::E::@constructor::•
+                    type: NamedType
+                      name: SimpleIdentifier
+                        staticElement: self::@enum::E
+                        staticType: null
+                        token: E @-1
+                      type: E
+                  staticType: E
             synthetic static const values @-1
               type: List<E>
-            static const v @31
-              type: E
+              constantInitializer
+                ListLiteral
+                  elements
+                    SimpleIdentifier
+                      staticElement: self::@enum::E::@getter::v
+                      staticType: E
+                      token: v @-1
+                  leftBracket: [ @0
+                  rightBracket: ] @0
+                  staticType: List<E>
+            synthetic final index @-1
+              type: int
+          constructors
+            synthetic const @-1
           accessors
-            synthetic get index @-1
-              returnType: int
-            synthetic static get values @-1
-              returnType: List<E>
             synthetic static get v @-1
               returnType: E
+            synthetic static get values @-1
+              returnType: List<E>
+            synthetic get index @-1
+              returnType: int
           methods
             synthetic toString @-1
               returnType: String
@@ -30419,19 +33020,50 @@
         enum E @27
           supertype: Enum
           fields
-            synthetic final index @-1
-              type: int
+            static const enumConstant v @31
+              type: E
+              constantInitializer
+                InstanceCreationExpression
+                  argumentList: ArgumentList
+                    leftParenthesis: ( @0
+                    rightParenthesis: ) @0
+                  constructorName: ConstructorName
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E::@constructor::•
+                      staticType: null
+                      token:  @-1
+                    period: . @0
+                    staticElement: self::@enum::E::@constructor::•
+                    type: NamedType
+                      name: SimpleIdentifier
+                        staticElement: self::@enum::E
+                        staticType: null
+                        token: E @-1
+                      type: E
+                  staticType: E
             synthetic static const values @-1
               type: List<E>
-            static const v @31
-              type: E
+              constantInitializer
+                ListLiteral
+                  elements
+                    SimpleIdentifier
+                      staticElement: self::@enum::E::@getter::v
+                      staticType: E
+                      token: v @-1
+                  leftBracket: [ @0
+                  rightBracket: ] @0
+                  staticType: List<E>
+            synthetic final index @-1
+              type: int
+          constructors
+            synthetic const @-1
           accessors
-            synthetic get index @-1
-              returnType: int
-            synthetic static get values @-1
-              returnType: List<E>
             synthetic static get v @-1
               returnType: E
+            synthetic static get values @-1
+              returnType: List<E>
+            synthetic get index @-1
+              returnType: int
           methods
             synthetic toString @-1
               returnType: String
@@ -30563,19 +33195,50 @@
       enum E @5
         supertype: Enum
         fields
-          synthetic final index @-1
-            type: int
+          static const enumConstant v @9
+            type: E
+            constantInitializer
+              InstanceCreationExpression
+                argumentList: ArgumentList
+                  leftParenthesis: ( @0
+                  rightParenthesis: ) @0
+                constructorName: ConstructorName
+                  name: SimpleIdentifier
+                    staticElement: self::@enum::E::@constructor::•
+                    staticType: null
+                    token:  @-1
+                  period: . @0
+                  staticElement: self::@enum::E::@constructor::•
+                  type: NamedType
+                    name: SimpleIdentifier
+                      staticElement: self::@enum::E
+                      staticType: null
+                      token: E @-1
+                    type: E
+                staticType: E
           synthetic static const values @-1
             type: List<E>
-          static const v @9
-            type: E
+            constantInitializer
+              ListLiteral
+                elements
+                  SimpleIdentifier
+                    staticElement: self::@enum::E::@getter::v
+                    staticType: E
+                    token: v @-1
+                leftBracket: [ @0
+                rightBracket: ] @0
+                staticType: List<E>
+          synthetic final index @-1
+            type: int
+        constructors
+          synthetic const @-1
         accessors
-          synthetic get index @-1
-            returnType: int
-          synthetic static get values @-1
-            returnType: List<E>
           synthetic static get v @-1
             returnType: E
+          synthetic static get values @-1
+            returnType: List<E>
+          synthetic get index @-1
+            returnType: int
         methods
           synthetic toString @-1
             returnType: String
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index 7a9a91c..f2133b0 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -318,8 +318,10 @@
   var aaa;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 64, 3)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 3)]),
     ]);
   }
 
@@ -3478,6 +3480,7 @@
                 constantInitializer
                   SimpleStringLiteral
                     literal: 'hello' @37
+                field: self::@class::A::@field::f
         accessors
           synthetic get f @-1
             returnType: int
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 5a33bcb..0b8f745 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -1639,7 +1639,8 @@
   S foo() => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 130, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 130, 3,
+          contextMessages: [message('/home/test/lib/test.dart', 63, 3)]),
     ]);
   }
 
@@ -1725,8 +1726,10 @@
   dynamic get f4 => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 226, 2),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 84, 2)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 226, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 120, 2)]),
     ]);
   }
 
@@ -1749,8 +1752,10 @@
   ToVoid<dynamic> get g => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 143, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 231, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 143, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 62, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 231, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 62, 1)]),
     ]);
   }
 
@@ -2014,7 +2019,8 @@
   int x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 46, 1)]),
     ]);
   }
 
@@ -2036,8 +2042,10 @@
   String x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 112, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 197, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 112, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 197, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 25, 1)]),
     ]);
   }
 
@@ -2079,10 +2087,12 @@
   num x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 28, 1)]),
       error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 184, 1),
       error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 184, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 216, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 216, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 28, 1)]),
       error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 228, 1),
       error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 228, 1),
     ]);
@@ -2130,34 +2140,44 @@
 }
 ''', [
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 80, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 80, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 80, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 124, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 177, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 177, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 177, 1),
       error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED, 177, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 259, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 259, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 259, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 259, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(
           CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
           271,
           2),
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 300, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 300, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 300, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(
           CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
           320,
           2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 347, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 347, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 347, 1),
       error(
           CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
           372,
           2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 403, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 403, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
       error(CompileTimeErrorCode.GETTER_NOT_ASSIGNABLE_SETTER_TYPES, 403, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 495, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 495, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 495, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 495, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 42, 1)]),
     ]);
   }
 
@@ -2174,7 +2194,8 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 79, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 79, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 38, 1)]),
     ]);
   }
 
@@ -2191,7 +2212,22 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 81, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 81, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 44, 1)]),
+    ]);
+  }
+
+  test_invalidOverrides_contextMessage() async {
+    await assertErrorsInCode('''
+class A {
+  void method() {}
+}
+class B extends A {
+  void method(String a) {}
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 58, 6,
+          contextMessages: [message('/home/test/lib/test.dart', 17, 6)]),
     ]);
   }
 
@@ -2213,7 +2249,8 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 95, 1)]),
     ]);
   }
 
@@ -2234,7 +2271,8 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 95, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
     ]);
   }
 
@@ -2256,7 +2294,8 @@
   int x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 135, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 135, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
     ]);
   }
 
@@ -2286,12 +2325,18 @@
 class U2 = Base with M1, M2;
 class U3 = Base with M2, M1;
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 144, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 177, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 218, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 271, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 304, 2),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 144, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 177, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 218, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 271, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 304, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 40, 1)]),
     ]);
   }
 
@@ -2317,8 +2362,10 @@
 
 class U1 = Base with M1, M2;
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 148, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 180, 2),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 148, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 54, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 180, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 54, 1)]),
     ]);
   }
 
@@ -2492,10 +2539,14 @@
   dynamic m6(dynamic value) => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 227, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 252, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 277, 2),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 354, 2),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 227, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 71, 2)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 252, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 92, 2)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 277, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 113, 2)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 354, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 176, 2)]),
     ]);
   }
 
@@ -2522,8 +2573,10 @@
   void g(dynamic x) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 156, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 224, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 156, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 99, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 224, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 99, 1)]),
     ]);
   }
 
@@ -2576,8 +2629,10 @@
 
 class U1 = Base with M;
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 146, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 146, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
     ]);
   }
 
@@ -2604,8 +2659,10 @@
           CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
           62,
           4),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 137, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 164, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 137, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 164, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
     ]);
   }
 
@@ -2628,7 +2685,8 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 145, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 145, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 92, 1)]),
     ]);
   }
 
@@ -2690,7 +2748,8 @@
   void n(A a);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 59, 1)]),
     ]);
   }
 
@@ -2720,7 +2779,8 @@
 
 class E extends B implements A { }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 4),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 4,
+          contextMessages: [message('/home/test/lib/test.dart', 24, 4)]),
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 159, 1),
       error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 189, 1),
     ]);
@@ -2933,10 +2993,14 @@
   void set i(dynamic x) {}
 }
  ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 220, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 255, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 362, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 397, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 220, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 85, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 255, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 116, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 362, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 85, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 397, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 116, 1)]),
     ]);
   }
 
@@ -2987,7 +3051,8 @@
   set f5(B value) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 263, 2),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 263, 2,
+          contextMessages: [message('/home/test/lib/test.dart', 111, 2)]),
     ]);
   }
 
@@ -3048,7 +3113,8 @@
     m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 96, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 96, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 47, 1)]),
     ]);
   }
 
@@ -3069,7 +3135,8 @@
   m(B a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 85, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 85, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 45, 1)]),
     ]);
   }
 
@@ -3430,7 +3497,8 @@
   T method<T>(T x) => x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 227, 6),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 227, 6,
+          contextMessages: [message('/home/test/lib/test.dart', 176, 6)]),
     ]);
   }
 
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 4840db6..279763f 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -423,8 +423,10 @@
   get a => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 150, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 246, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 116, 1)]),
     ]);
   }
 
@@ -709,7 +711,8 @@
   int z = new B().x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 22, 1)]),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 97, 1),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 118, 1),
     ]);
@@ -2141,7 +2144,8 @@
   print(y);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
       error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD, 91, 5),
     ]);
   }
@@ -2199,8 +2203,10 @@
   print(y);
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 74, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 74, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 12, 1)]),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 33, 1)]),
       error(HintCode.UNNECESSARY_CAST, 132, 12),
     ]);
   }
@@ -3679,7 +3685,8 @@
   int z = new B().x;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 1,
+          contextMessages: [message('/home/test/lib/test.dart', 23, 1)]),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 106, 1),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 127, 1),
     ]);
diff --git a/pkg/analyzer/test/util/ast_check.dart b/pkg/analyzer/test/util/ast_check.dart
new file mode 100644
index 0000000..0cc0ab6
--- /dev/null
+++ b/pkg/analyzer/test/util/ast_check.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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_utilities/check/check.dart';
+
+extension FormalParameterExtension on CheckTarget<FormalParameter> {
+  CheckTarget<SimpleIdentifier?> get identifier {
+    return nest(
+      value.identifier,
+      (selected) => 'has identifier ${valueStr(selected)}',
+    );
+  }
+}
+
+extension SimpleFormalParameterExtension on CheckTarget<SimpleFormalParameter> {
+  CheckTarget<Token?> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeAnnotation?> get type {
+    return nest(
+      value.type,
+      (selected) => 'has type ${valueStr(selected)}',
+    );
+  }
+}
+
+extension SimpleIdentifierExtension on CheckTarget<SimpleIdentifier> {
+  CheckTarget<bool> get inDeclarationContext {
+    return nest(
+      value.inDeclarationContext(),
+      (selected) => 'has inDeclarationContext() ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<String> get name {
+    return nest(
+      value.name,
+      (selected) => 'has name ${valueStr(selected)}',
+    );
+  }
+}
+
+extension SuperFormalParameterExtension on CheckTarget<SuperFormalParameter> {
+  CheckTarget<SimpleIdentifier> get identifier {
+    return nest(
+      value.identifier,
+      (selected) => 'has identifier ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<Token?> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<FormalParameterList?> get parameters {
+    return nest(
+      value.parameters,
+      (selected) => 'has parameters ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<Token?> get superKeyword {
+    return nest(
+      value.superKeyword,
+      (selected) => 'has superKeyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeAnnotation?> get type {
+    return nest(
+      value.type,
+      (selected) => 'has type ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeParameterList?> get typeParameters {
+    return nest(
+      value.typeParameters,
+      (selected) => 'has typeParameters ${valueStr(selected)}',
+    );
+  }
+}
+
+extension TypeParameterListExtension on CheckTarget<TypeParameterList> {
+  CheckTarget<List<TypeParameter>> get typeParameters {
+    return nest(
+      value.typeParameters,
+      (selected) => 'has typeParameters ${valueStr(selected)}',
+    );
+  }
+}
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 7fe6cbe..d39b7db 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -145,7 +145,7 @@
   var byteStore = MemoryByteStore();
   var analysisOptions = AnalysisOptionsImpl()
     ..contextFeatures = config.featureSet;
-  var driver = AnalysisDriver.tmp1(
+  var driver = AnalysisDriver(
     scheduler: scheduler,
     logger: logger,
     resourceProvider: resourceProvider,
diff --git a/pkg/analyzer/test/util/token_check.dart b/pkg/analyzer/test/util/token_check.dart
new file mode 100644
index 0000000..7d8fc24
--- /dev/null
+++ b/pkg/analyzer/test/util/token_check.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All 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/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer_utilities/check/check.dart';
+
+extension KeywordTokenExtension on CheckTarget<KeywordToken> {
+  CheckTarget<Keyword> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+}
+
+extension TokenExtension on CheckTarget<Token?> {
+  CheckTarget<KeywordToken> get isKeyword {
+    return isA<KeywordToken>();
+  }
+
+  void get isKeywordConst {
+    isKeyword.keyword.isEqualTo(Keyword.CONST);
+  }
+
+  void get isKeywordSuper {
+    isKeyword.keyword.isEqualTo(Keyword.SUPER);
+  }
+
+  void get isKeywordVar {
+    isKeyword.keyword.isEqualTo(Keyword.VAR);
+  }
+}
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index d5ee1bf..873f700 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -451,6 +451,6 @@
         );
       }
     }
-    writeTestPackageConfig(packageConfigBuilder, meta: true);
+    writeTestPackageConfig(packageConfigBuilder, ffi: true, meta: true);
   }
 }
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 8f8c3aa..c8454b0 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -649,6 +649,101 @@
 }
 {% endprettify %}
 
+### annotation_on_pointer_field
+
+_Fields in a struct class whose type is 'Pointer' shouldn't have any
+annotations._
+
+#### Description
+
+The analyzer produces this diagnostic when a field that's declared in a
+subclass of `Struct` and has the type `Pointer` also has an annotation
+associated with it.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `p`, which
+has the type `Pointer` and is declared in a subclass of `Struct`, has the
+annotation `@Double()`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  [!@Double()!]
+  external Pointer<Int8> p;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the annotations from the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  external Pointer<Int8> p;
+}
+{% endprettify %}
+
+### argument_must_be_a_constant
+
+_Argument '{0}' must be a constant._
+
+#### Description
+
+The analyzer produces this diagnostic when an invocation of either
+`Pointer.asFunction` or `DynamicLibrary.lookupFunction` has an `isLeaf`
+argument whose value isn't a constant expression.
+
+The analyzer also produces this diagnostic when the value of the
+`exceptionalReturn` argument of `Pointer.fromFunction`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the value of the
+`isLeaf` argument is a parameter, and hence isn't a constant:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int Function(int) fromPointer(
+    Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
+  return p.asFunction(isLeaf: [!isLeaf!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If there's a suitable constant that can be used, then replace the argument
+with a constant:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+const isLeaf = false;
+
+int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+  return p.asFunction(isLeaf: isLeaf);
+}
+{% endprettify %}
+
+If there isn't a suitable constant, then replace the argument with a
+boolean literal:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
+  return p.asFunction(isLeaf: true);
+}
+{% endprettify %}
+
 ### argument_type_not_assignable
 
 _The argument type '{0}' can't be assigned to the parameter type '{1}'._
@@ -2696,6 +2791,58 @@
 C<T> newC<T>() => C<T>();
 {% endprettify %}
 
+### creation_of_struct_or_union
+
+_Subclasses of 'Struct' and 'Union' are backed by native memory, and can't be
+instantiated by a generative constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when a subclass of either `Struct`
+or `Union` is instantiated using a generative constructor.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C` is being
+instantiated using a generative constructor:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  external int a;
+}
+
+void f() {
+  [!C!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you need to allocate the structure described by the class, then use the
+`ffi` package to do so:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class C extends Struct {
+  @Int32()
+  external int a;
+}
+
+void f() {
+  final pointer = calloc.allocate<C>(4);
+  final c = pointer.ref;
+  print(c);
+  calloc.free(pointer);
+}
+{% endprettify %}
+
 ### creation_with_non_type
 
 _The name '{0}' isn't a class._
@@ -3501,9 +3648,10 @@
 
 #### Description
 
-The analyzer produces this diagnostic when there's more than one field
-formal parameter for the same field in a constructor's parameter list. It
-isn't useful to assign a value that will immediately be overwritten.
+The analyzer produces this diagnostic when there's more than one
+initializing formal parameter for the same field in a constructor's
+parameter list. It isn't useful to assign a value that will immediately be
+overwritten.
 
 #### Example
 
@@ -3520,7 +3668,7 @@
 
 #### Common fixes
 
-Remove one of the field formal parameters:
+Remove one of the initializing formal parameters:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -3776,6 +3924,58 @@
 var x = min(2, min(0, 1));
 {% endprettify %}
 
+### empty_struct
+
+_The class '{0}' can't be empty because it's a subclass of '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a subclass of `Struct` or
+`Union` doesn't have any fields. Having an empty `Struct` or `Union`
+isn't supported.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C`, which
+extends `Struct`, doesn't declare any fields:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class [!C!] extends Struct {}
+{% endprettify %}
+
+#### Common fixes
+
+If the class is intended to be a struct, then declare one or more fields:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  external int x;
+}
+{% endprettify %}
+
+If the class is intended to be used as a type argument to `Pointer`, then
+make it a subclass of `Opaque`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Opaque {}
+{% endprettify %}
+
+If the class isn't intended to be a struct, then remove or change the
+extends clause:
+
+{% prettify dart tag=pre+code %}
+class C {}
+{% endprettify %}
+
 ### equal_elements_in_const_set
 
 _Two elements in a constant set literal can't be equal._
@@ -4547,6 +4747,46 @@
 If there are multiple cascaded accesses, you'll need to duplicate the
 extension override for each one.
 
+### extra_annotation_on_struct_field
+
+_Fields in a struct class must have exactly one annotation indicating the native
+type._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` has more than one annotation describing the native type of the
+field.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `x` has two
+annotations describing the native type of the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  [!@Int16()!]
+  external int x;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove all but one of the annotations:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+class C extends Struct {
+  @Int32()
+  external int x;
+}
+{% endprettify %}
+
 ### extra_positional_arguments
 
 _Too many positional arguments: {0} expected, but {1} found._
@@ -4624,6 +4864,46 @@
 }
 {% endprettify %}
 
+### extra_size_annotation_carray
+
+_'Array's must have exactly one 'Array' annotation._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` has more than one annotation describing the size of the native
+array.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `a0` has two
+annotations that specify the size of the native array:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(4)
+  [!@Array(8)!]
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove all but one of the annotations:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8)
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
 ### field_initialized_by_multiple_initializers
 
 _The field '{0}' can't be initialized twice in the same constructor._
@@ -4718,7 +4998,8 @@
 #### Example
 
 The following code produces this diagnostic because the field `f` is
-initialized both by a field formal parameter and in the initializer list:
+initialized both by an initializing formal parameter and in the
+initializer list:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4769,14 +5050,14 @@
 
 #### Description
 
-The analyzer produces this diagnostic when a factory constructor has a
-field formal parameter. Factory constructors can't assign values to fields
-because no instance is created; hence, there is no field to assign.
+The analyzer produces this diagnostic when a factory constructor has an
+initializing formal parameter. Factory constructors can't assign values to
+fields because no instance is created; hence, there is no field to assign.
 
 #### Example
 
 The following code produces this diagnostic because the factory constructor
-uses a field formal parameter:
+uses an initializing formal parameter:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4788,7 +5069,7 @@
 
 #### Common fixes
 
-Replace the field formal parameter with a normal parameter:
+Replace the initializing formal parameter with a normal parameter:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4798,6 +5079,51 @@
 }
 {% endprettify %}
 
+### field_initializer_in_struct
+
+_Constructors in subclasses of 'Struct' and 'Union' can't have field
+initializers._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor in a subclass of
+either `Struct` or `Union` has one or more field initializers.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C` has a
+constructor with an initializer for the field `f`:
+
+{% prettify dart tag=pre+code %}
+// @dart = 2.9
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  int f;
+
+  C() : [!f = 0!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the field initializer:
+
+{% prettify dart tag=pre+code %}
+// @dart = 2.9
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  int f;
+
+  C();
+}
+{% endprettify %}
+
 ### field_initializer_not_assignable
 
 _The initializer type '{0}' can't be assigned to the field type '{1}' in a const
@@ -4862,8 +5188,8 @@
 #### Examples
 
 The following code produces this diagnostic because the constructor
-`C.zero`, which redirects to the constructor `C`, has a field formal
-parameter that initializes the field `f`:
+`C.zero`, which redirects to the constructor `C`, has an initializing
+formal parameter that initializes the field `f`:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4891,8 +5217,8 @@
 
 #### Common fixes
 
-If the initialization is done by a field formal parameter, then use a
-normal parameter:
+If the initialization is done by an initializing formal parameter, then
+use a normal parameter:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4923,14 +5249,16 @@
 
 #### Description
 
-The analyzer produces this diagnostic when the type of a field formal
-parameter isn't assignable to the type of the field being initialized.
+The analyzer produces this diagnostic when the type of an initializing
+formal parameter isn't assignable to the type of the field being
+initialized.
 
 #### Example
 
-The following code produces this diagnostic because the field formal
-parameter has the type `String`, but the type of the field is `int`. The
-parameter must have a type that is a subtype of the field's type.
+The following code produces this diagnostic because the initializing
+formal parameter has the type `String`, but the type of the field is
+`int`. The parameter must have a type that is a subtype of the field's
+type.
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4966,8 +5294,8 @@
 {% endprettify %}
 
 If the types of both the field and the parameter are correct, then use an
-initializer rather than a field formal parameter to convert the parameter
-value into a value of the correct type:
+initializer rather than an initializing formal parameter to convert the
+parameter value into a value of the correct type:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -4977,6 +5305,82 @@
 }
 {% endprettify %}
 
+### field_in_struct_with_initializer
+
+_Fields in subclasses of 'Struct' and 'Union' can't have initializers._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` has an initializer.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `p` has an
+initializer:
+
+{% prettify dart tag=pre+code %}
+// @dart = 2.9
+import 'dart:ffi';
+
+class C extends Struct {
+  Pointer [!p!] = nullptr;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the initializer:
+
+{% prettify dart tag=pre+code %}
+// @dart = 2.9
+import 'dart:ffi';
+
+class C extends Struct {
+  Pointer p;
+}
+{% endprettify %}
+
+### field_must_be_external_in_struct
+
+_Fields of 'Struct' and 'Union' subclasses must be marked external._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of either
+`Struct` or `Union` isn't marked as being `external`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `a` isn't
+marked as being `external`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int16()
+  int [!a!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add the required `external` modifier:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int16()
+  external int a;
+}
+{% endprettify %}
+
 ### final_initialized_in_declaration_and_constructor
 
 _'{0}' is final and was given a value when it was declared, so it can't be set
@@ -5052,7 +5456,7 @@
 
 For instance fields, you can add an initializer as shown in the previous
 example, or you can initialize the field in every constructor. You can
-initialize the field by using a field formal parameter:
+initialize the field by using an initializing formal parameter:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -5102,8 +5506,8 @@
 
 #### Common fixes
 
-If the value should be passed in to the constructor directly, then use a
-field formal parameter to initialize the field `value`:
+If the value should be passed in to the constructor directly, then use an
+initializing formal parameter to initialize the field `value`:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -5365,6 +5769,42 @@
 }
 {% endprettify %}
 
+### generic_struct_subclass
+
+_The class '{0}' can't extend 'Struct' or 'Union' because '{0}' is generic._
+
+#### Description
+
+The analyzer produces this diagnostic when a subclass of either `Struct`
+or `Union` has a type parameter.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `S` defines
+the type parameter `T`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class [!S!]<T> extends Struct {
+  external Pointer notEmpty;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the type parameters from the class:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class S extends Struct {
+  external Pointer notEmpty;
+}
+{% endprettify %}
+
 ### getter_not_subtype_setter_types
 
 _The return type of getter '{0}' is '{1}' which isn't a subtype of the type
@@ -5880,14 +6320,14 @@
 
 #### Description
 
-The analyzer produces this diagnostic when a static field is initialized in
-a constructor using either a field formal parameter or an assignment in the
-initializer list.
+The analyzer produces this diagnostic when a static field is initialized
+in a constructor using either an initializing formal parameter or an
+assignment in the initializer list.
 
 #### Example
 
-The following code produces this diagnostic because the static field `a` is
-being initialized by the field formal parameter `this.a`:
+The following code produces this diagnostic because the static field `a`
+is being initialized by the initializing formal parameter `this.a`:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -5936,10 +6376,10 @@
 
 #### Description
 
-The analyzer produces this diagnostic when a field formal parameter is
-found in a constructor in a class that doesn't declare the field being
-initialized. Constructors can't initialize fields that aren't declared and
-fields that are inherited from superclasses.
+The analyzer produces this diagnostic when an initializing formal
+parameter is found in a constructor in a class that doesn't declare the
+field being initialized. Constructors can't initialize fields that aren't
+declared and fields that are inherited from superclasses.
 
 #### Example
 
@@ -6561,6 +7001,53 @@
     version: ^1.4.0
 ```
 
+### invalid_exception_value
+
+_The method 'Pointer.fromFunction' can't have an exceptional return value (the
+second argument) when the return type of the function is either 'void', 'Handle' or 'Pointer'._
+
+#### Description
+
+The analyzer produces this diagnostic when an invocation of the method
+`Pointer.fromFunction` has a second argument (the exceptional return
+value) and the type to be returned from the invocation is either `void`,
+`Handle` or `Pointer`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because a second argument is
+provided when the return type of `f` is `void`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = Void Function(Int8);
+
+void f(int i) {}
+
+void g() {
+  Pointer.fromFunction<T>(f, [!42!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the exception value:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = Void Function(Int8);
+
+void f(int i) {}
+
+void g() {
+  Pointer.fromFunction<T>(f);
+}
+{% endprettify %}
+
 ### invalid_extension_argument_count
 
 _Extension overrides must have exactly one argument: the value of 'this' in the
@@ -6673,6 +7160,52 @@
 }
 {% endprettify %}
 
+### invalid_field_type_in_struct
+
+_Fields in struct classes can't have the type '{0}'. They can only be declared
+as 'int', 'double', 'Array', 'Pointer', or subtype of 'Struct' or 'Union'._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` has a type other than `int`, `double`, `Array`, `Pointer`, or
+subtype of `Struct` or `Union`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `str` has
+the type `String`, which isn't one of the allowed types for fields in a
+subclass of `Struct`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  external [!String!] s;
+
+  @Int32()
+  external int i;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Use one of the allowed types for the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class C extends Struct {
+  external Pointer<Utf8> s;
+
+  @Int32()
+  external int i;
+}
+{% endprettify %}
+
 ### invalid_implementation_override
 
 _'{1}.{0}' ('{2}') isn't a valid concrete implementation of '{3}.{0}' ('{4}')._
@@ -7744,6 +8277,112 @@
 }
 {% endprettify %}
 
+### leaf_call_must_not_return_handle
+
+_FFI leaf call can't return a 'Handle'._
+
+#### Description
+
+The analyzer produces this diagnostic when the value of the `isLeaf`
+argument in an invocation of either `Pointer.asFunction` or
+`DynamicLibrary.lookupFunction` is `true` and the function that would be
+returned would have a return type of `Handle`.
+
+The analyzer also produces this diagnostic when the value of the `isLeaf`
+argument in an `FfiNative` annotation is `true` and the type argument on
+the annotation is a function type whose return type is `Handle`.
+
+In all of these cases, leaf calls are only supported for the types `bool`,
+`int`, `float`, `double`, and, as a return type `void`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the function `p`
+returns a `Handle`, but the `isLeaf` argument is `true`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Handle Function()>> p) {
+  [!p.asFunction<Object Function()>(isLeaf: true)!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the function returns a handle, then remove the `isLeaf` argument:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Handle Function()>> p) {
+  p.asFunction<Object Function()>();
+}
+{% endprettify %}
+
+If the function returns one of the supported types, then correct the type
+information:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Int32 Function()>> p) {
+  p.asFunction<int Function()>(isLeaf: true);
+}
+{% endprettify %}
+
+### leaf_call_must_not_take_handle
+
+_FFI leaf call can't take arguments of type 'Handle'._
+
+#### Description
+
+The analyzer produces this diagnostic when the value of the `isLeaf`
+argument in an invocation of either `Pointer.asFunction` or
+`DynamicLibrary.lookupFunction` is `true` and the function that would be
+returned would have a parameter of type `Handle`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the function `p` has a
+parameter of type `Handle`, but the `isLeaf` argument is `true`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+  [!p.asFunction<void Function(Object)>(isLeaf: true)!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the function has at least one parameter of type `Handle`, then remove
+the `isLeaf` argument:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
+  p.asFunction<void Function(Object)>();
+}
+{% endprettify %}
+
+If none of the function's parameters are `Handle`s, then correct the type
+information:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
+  p.asFunction<void Function(int)>(isLeaf: true);
+}
+{% endprettify %}
+
 ### list_element_type_not_assignable
 
 _The element type '{0}' can't be assigned to the list type '{1}'._
@@ -8023,6 +8662,96 @@
 var m = <String, int>{'a' : 2};
 {% endprettify %}
 
+### mismatched_annotation_on_struct_field
+
+_The annotation doesn't match the declared type of the field._
+
+#### Description
+
+The analyzer produces this diagnostic when the annotation on a field in a
+subclass of `Struct` or `Union` doesn't match the Dart type of the field.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the annotation
+`Double` doesn't match the Dart type `int`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  [!@Double()!]
+  external int x;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the field is correct, then change the annotation to match:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  external int x;
+}
+{% endprettify %}
+
+If the annotation is correct, then change the type of the field to match:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Double()
+  external double x;
+}
+{% endprettify %}
+
+### missing_annotation_on_struct_field
+
+_Fields in a struct class must either have the type 'Pointer' or an annotation
+indicating the native type._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` or `Union` whose type requires an annotation doesn't have one.
+The Dart types `int`, `double`, and `Array` are used to represent multiple
+C types, and the annotation specifies which of the compatible C types the
+field represents.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `x` doesn't
+have an annotation indicating the underlying width of the integer value:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  external [!int!] x;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add an appropriate annotation to the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int64()
+  external int x;
+}
+{% endprettify %}
+
 ### missing_dart_library
 
 _Required library '{0}' is missing._
@@ -8042,6 +8771,8 @@
 _The parameter '{0}' can't have a value of 'null' because of its type, but the
 implicit default value is 'null'._
 
+_With null safety, use the 'required' keyword, not the '@required' annotation._
+
 #### Description
 
 The analyzer produces this diagnostic when an optional parameter, whether
@@ -8152,6 +8883,96 @@
 }
 {% endprettify %}
 
+### missing_exception_value
+
+_The method 'Pointer.fromFunction' must have an exceptional return value (the
+second argument) when the return type of the function is neither 'void', 'Handle', nor 'Pointer'._
+
+#### Description
+
+The analyzer produces this diagnostic when an invocation of the method
+`Pointer.fromFunction` doesn't have a second argument (the exceptional
+return value) when the type to be returned from the invocation is neither
+`void`, `Handle`, nor `Pointer`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the type returned by
+`f` is expected to be an 8-bit integer but the call to `fromFunction`
+doesn't include an exceptional return argument:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int f(int i) => i * 2;
+
+void g() {
+  Pointer.[!fromFunction!]<Int8 Function(Int8)>(f);
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add an exceptional return type:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int f(int i) => i * 2;
+
+void g() {
+  Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
+}
+{% endprettify %}
+
+### missing_field_type_in_struct
+
+_Fields in struct classes must have an explicitly declared type of 'int',
+'double' or 'Pointer'._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of
+`Struct` or `Union` doesn't have a type annotation. Every field must have
+an explicit type, and the type must either be `int`, `double`, `Pointer`,
+or a subclass of either `Struct` or `Union`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `str`
+doesn't have a type annotation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  external var [!str!];
+
+  @Int32()
+  external int i;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Explicitly specify the type of the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+class C extends Struct {
+  external Pointer<Utf8> str;
+
+  @Int32()
+  external int i;
+}
+{% endprettify %}
+
 ### missing_name
 
 _The 'name' field is required but missing._
@@ -8283,6 +9104,44 @@
 Add a `return` statement that makes the return value explicit, even if
 `null` is the appropriate value.
 
+### missing_size_annotation_carray
+
+_Fields of type 'Array' must have exactly one 'Array' annotation._
+
+#### Description
+
+The analyzer produces this diagnostic when a field in a subclass of either
+`Struct` or `Union` has a type of `Array` but doesn't have a single
+`Array` annotation indicating the dimensions of the array.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `a0` doesn't
+have an `Array` annotation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  external [!Array<Uint8>!] a0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Ensure that there's exactly one `Array` annotation on the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8)
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
 ### mixin_application_concrete_super_invoked_member_type
 
 _The super-invoked member '{0}' has the type '{1}', and the concrete member in
@@ -8814,6 +9673,115 @@
 }
 {% endprettify %}
 
+### must_be_a_native_function_type
+
+_The type '{0}' given to '{1}' must be a valid 'dart:ffi' native function type._
+
+#### Description
+
+The analyzer produces this diagnostic when an invocation of either
+`Pointer.fromFunction` or `DynamicLibrary.lookupFunction` has a type
+argument(whether explicit or inferred) that isn't a native function type.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the type `T` can be
+any subclass of `Function` but the type argument for `fromFunction` is
+required to be a native function type:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int f(int i) => i * 2;
+
+class C<T extends Function> {
+  void g() {
+    Pointer.fromFunction<[!T!]>(f, 0);
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Use a native function type as the type argument to the invocation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+int f(int i) => i * 2;
+
+class C<T extends Function> {
+  void g() {
+    Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
+  }
+}
+{% endprettify %}
+
+### must_be_a_subtype
+
+_The type '{0}' must be a subtype of '{1}' for '{2}'._
+
+#### Description
+
+The analyzer produces this diagnostic in two cases:
+- In an invocation of `Pointer.fromFunction` where the type argument
+  (whether explicit or inferred) isn't a supertype of the type of the
+  function passed as the first argument to the method.
+- In an invocation of `DynamicLibrary.lookupFunction` where the first type
+  argument isn't a supertype of the second type argument.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the type of the
+function `f` (`String Function(int)`) isn't a subtype of the type
+argument `T` (`Int8 Function(Int8)`):
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = Int8 Function(Int8);
+
+double f(double i) => i;
+
+void g() {
+  Pointer.fromFunction<T>([!f!], 5.0);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the function is correct, then change the type argument to match:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = Float Function(Float);
+
+double f(double i) => i;
+
+void g() {
+  Pointer.fromFunction<T>(f, 5.0);
+}
+{% endprettify %}
+
+If the type argument is correct, then change the function to match:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = Int8 Function(Int8);
+
+int f(int i) => i;
+
+void g() {
+  Pointer.fromFunction<T>(f, 5);
+}
+{% endprettify %}
+
 ### must_be_immutable
 
 _This class (or a class that this class inherits from) is marked as
@@ -9634,6 +10602,52 @@
 var s = {i};
 {% endprettify %}
 
+### non_constant_type_argument
+
+_The type arguments to '{0}' must be known at compile time, so they can't be
+type parameters._
+
+#### Description
+
+The analyzer produces this diagnostic when the type arguments to a method
+are required to be known at compile time, but a type parameter, whose
+value can't be known at compile time, is used as a type argument.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the type argument to
+`Pointer.asFunction` must be known at compile time, but the type parameter
+`R`, which isn't known at compile time, is being used as the type
+argument:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef T = int Function(int);
+
+class C<R extends T> {
+  void m(Pointer<NativeFunction<T>> p) {
+    p.asFunction<[!R!]>();
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove any uses of type parameters:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C {
+  void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
+    p.asFunction<int Function(int)>();
+  }
+}
+{% endprettify %}
+
 ### non_const_call_to_literal_constructor
 
 _This instance creation must be 'const', because the {0} constructor is marked
@@ -9722,6 +10736,134 @@
 If the generative constructor is the unnamed constructor, and if there are
 no arguments being passed to it, then you can remove the super invocation.
 
+### non_native_function_type_argument_to_pointer
+
+_Can't invoke 'asFunction' because the function signature '{0}' for the pointer
+isn't a valid C function signature._
+
+#### Description
+
+The analyzer produces this diagnostic when the method `asFunction` is
+invoked on a pointer to a native function, but the signature of the native
+function isn't a valid C function signature.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because function signature
+associated with the pointer `p` (`FNative`) isn't a valid C function
+signature:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef FNative = int Function(int);
+typedef F = int Function(int);
+
+class C {
+  void f(Pointer<NativeFunction<FNative>> p) {
+    p.asFunction<[!F!]>();
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Make the `NativeFunction` signature a valid C signature:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+typedef FNative = Int8 Function(Int8);
+typedef F = int Function(int);
+
+class C {
+  void f(Pointer<NativeFunction<FNative>> p) {
+    p.asFunction<F>();
+  }
+}
+{% endprettify %}
+
+### non_positive_array_dimension
+
+_Array dimensions must be positive numbers._
+
+#### Description
+
+The analyzer produces this diagnostic when a dimension given in an `Array`
+annotation is less than or equal to zero (`0`).
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because an array dimension of
+`-1` was provided:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class MyStruct extends Struct {
+  @Array([!-8!])
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Change the dimension to be a positive integer:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class MyStruct extends Struct {
+  @Array(8)
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
+### non_sized_type_argument
+
+_The type '{1}' isn't a valid type argument for '{0}'. The type argument must be
+a native integer, 'Float', 'Double', 'Pointer', or subtype of 'Struct', 'Union', or 'AbiSpecificInteger'._
+
+#### Description
+
+The analyzer produces this diagnostic when the type argument for the class
+`Array` isn't one of the valid types: either a native integer, `Float`,
+`Double`, `Pointer`, or subtype of `Struct`, `Union`, or
+`AbiSpecificInteger`.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the type argument to
+`Array` is `Void`, and `Void` isn't one of the valid types:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8)
+  external Array<[!Void!]> a0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Change the type argument to one of the valid types:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8)
+  external Array<Uint8> a0;
+}
+{% endprettify %}
+
 ### non_sync_factory
 
 _Factory bodies can't use 'async', 'async*', or 'sync*'._
@@ -10714,6 +11856,165 @@
 
 If the member can't be removed, then remove the annotation.
 
+### packed_annotation
+
+_Structs must have at most one 'Packed' annotation._
+
+#### Description
+
+The analyzer produces this diagnostic when a subclass of `Struct` has more
+than one `Packed` annotation.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C`, which
+is a subclass of `Struct`, has two `Packed` annotations:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(1)
+[!@Packed(1)!]
+class C extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove all but one of the annotations:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(1)
+class C extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+{% endprettify %}
+
+### packed_annotation_alignment
+
+_Only packing to 1, 2, 4, 8, and 16 bytes is supported._
+
+#### Description
+
+The analyzer produces this diagnostic when the argument to the `Packed`
+annotation isn't one of the allowed values: 1, 2, 4, 8, or 16.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the argument to the
+`Packed` annotation (`3`) isn't one of the allowed values:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed([!3!])
+class C extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Change the alignment to be one of the allowed values:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(4)
+class C extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+{% endprettify %}
+
+### packed_nesting_non_packed
+
+_Nesting the non-packed or less tightly packed struct '{0}' in a packed struct
+'{1}' isn't supported._
+
+#### Description
+
+The analyzer produces this diagnostic when a subclass of `Struct` that is
+annotated as being `Packed` declares a field whose type is also a subclass
+of `Struct` and the field's type is either not packed or is packed less
+tightly.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `Outer`,
+which is a subclass of `Struct` and is packed on 1-byte boundaries,
+declared a field whose type (`Inner`) is packed on 8-byte boundaries:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(8)
+class Inner extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+
+@Packed(1)
+class Outer extends Struct {
+  external Pointer<Uint8> notEmpty;
+
+  external [!Inner!] nestedLooselyPacked;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the inner struct should be packed more tightly, then change the
+argument to the inner struct's `Packed` annotation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(1)
+class Inner extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+
+@Packed(1)
+class Outer extends Struct {
+  external Pointer<Uint8> notEmpty;
+
+  external Inner nestedLooselyPacked;
+}
+{% endprettify %}
+
+If the outer struct should be packed less tightly, then change the
+argument to the outer struct's `Packed` annotation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+@Packed(8)
+class Inner extends Struct {
+  external Pointer<Uint8> notEmpty;
+}
+
+@Packed(8)
+class Outer extends Struct {
+  external Pointer<Uint8> notEmpty;
+
+  external Inner nestedLooselyPacked;
+}
+{% endprettify %}
+
+If the inner struct doesn't have an annotation and should be packed, then
+add an annotation.
+
+If the inner struct doesn't have an annotation and the outer struct
+shouldn't be packed, then remove its annotation.
+
 ### part_of_different_library
 
 _Expected this library to be part of '{0}', not '{1}'._
@@ -12555,6 +13856,58 @@
 var y = convert.json.encode(x.min(0, 1));
 {% endprettify %}
 
+### size_annotation_dimensions
+
+_'Array's must have an 'Array' annotation that matches the dimensions._
+
+#### Description
+
+The analyzer produces this diagnostic when the number of dimensions
+specified in an `Array` annotation doesn't match the number of nested
+arrays specified by the type of a field.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the field `a0` has a
+type with three nested arrays, but only two dimensions are given in the
+`Array` annotation:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  [!@Array(8, 8)!]
+  external Array<Array<Array<Uint8>>> a0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the field is correct, then fix the annotation to have the
+required number of dimensions:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8, 8, 4)
+  external Array<Array<Array<Uint8>>> a0;
+}
+{% endprettify %}
+
+If the type of the field is wrong, then fix the type of the field:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Array(8, 8)
+  external Array<Array<Uint8>> a0;
+}
+{% endprettify %}
+
 ### static_access_to_instance_member
 
 _Instance member '{0}' can't be accessed using static access._
@@ -12718,6 +14071,55 @@
 class B {}
 {% endprettify %}
 
+### subtype_of_ffi_class
+
+_The class '{0}' can't extend '{1}'._
+
+_The class '{0}' can't implement '{1}'._
+
+_The class '{0}' can't mix in '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a class extends any FFI class
+other than `Struct` or `Union`, or implements or mixes in any FFI class.
+`Struct` and `Union` are the only FFI classes that can be subtyped, and
+then only by extending them.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C` extends
+`Double`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends [!Double!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If the class should extend either `Struct` or `Union`, then change the
+declaration of the class:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class C extends Struct {
+  @Int32()
+  external int i;
+}
+{% endprettify %}
+
+If the class shouldn't extend either `Struct` or `Union`, then remove any
+references to FFI classes:
+
+{% prettify dart tag=pre+code %}
+class C {}
+{% endprettify %}
+
 ### subtype_of_sealed_class
 
 _The class '{0}' shouldn't be extended, mixed in, or implemented because it's
@@ -12769,6 +14171,62 @@
 the sealed class so that it's no longer sealed or move the subclass into
 the same package as the sealed class.
 
+### subtype_of_struct_class
+
+_The class '{0}' can't extend '{1}' because '{1}' is a subtype of 'Struct',
+'Union', or 'AbiSpecificInteger'._
+
+_The class '{0}' can't implement '{1}' because '{1}' is a subtype of 'Struct',
+'Union', or 'AbiSpecificInteger'._
+
+_The class '{0}' can't mix in '{1}' because '{1}' is a subtype of 'Struct',
+'Union', or 'AbiSpecificInteger'._
+
+#### Description
+
+The analyzer produces this diagnostic when a class extends, implements, or
+mixes in a class that extends either `Struct` or `Union`. Classes can only
+extend either `Struct` or `Union` directly.
+
+For more information about FFI, see [C interop using dart:ffi][].
+
+#### Example
+
+The following code produces this diagnostic because the class `C` extends
+`S`, and `S` extends `Struct`:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class S extends Struct {
+  external Pointer f;
+}
+
+class C extends [!S!] {
+  external Pointer g;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you're trying to define a struct or union that shares some fields
+declared by a different struct or union, then extend `Struct` or `Union`
+directly and copy the shared fields:
+
+{% prettify dart tag=pre+code %}
+import 'dart:ffi';
+
+class S extends Struct {
+  external Pointer f;
+}
+
+class C extends Struct {
+  external Pointer f;
+
+  external Pointer g;
+}
+{% endprettify %}
+
 ### supertype_expands_to_type_parameter
 
 _A type alias that expands to a type parameter can't be implemented._
diff --git a/pkg/analyzer/tool/experiments/experiments_test.dart b/pkg/analyzer/tool/experiments/experiments_test.dart
index 575c084..dc8e2ac 100644
--- a/pkg/analyzer/tool/experiments/experiments_test.dart
+++ b/pkg/analyzer/tool/experiments/experiments_test.dart
@@ -10,7 +10,7 @@
 import 'generate.dart';
 
 /// Check that all targets have been code generated.  If they haven't tell the
-/// user to run generate_all.dart.
+/// user to run `generate.dart`.
 main() async {
   String script = Platform.script.toFilePath(windows: Platform.isWindows);
   List<String> components = split(script);
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index b18c095..981e0cf 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -1069,12 +1069,12 @@
         if (convertItem == null) {
           convertField = localName;
         } else if (type.isList) {
-          convertField = '$localName.map((_value) =>'
-              ' ${convertItem('_value')}).toList()';
+          convertField = '$localName.map((value) =>'
+              ' ${convertItem('value')}).toList()';
         } else {
           convertField = convertItem(localName);
         }
-        return '_result[${quoted(name)}] = $convertField';
+        return 'result[${quoted(name)}] = $convertField';
       }
 
       void writeConditionalStatement(String condition, String statement) {
@@ -1087,7 +1087,7 @@
       out('@override');
       out('Map<String, Object> toJson() {');
       indent(() {
-        out('Map<String, Object> _result = <String, Object>{};');
+        out('Map<String, Object> result = <String, Object>{};');
 
         indent(() {
           for (idl_model.FieldDeclaration field in cls.fields) {
@@ -1099,7 +1099,7 @@
           }
         });
 
-        out('return _result;');
+        out('return result;');
       });
       out('}');
       out();
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index cba223d..a1c3097 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1388,7 +1388,7 @@
   <dl><dt class="value">ANNOTATION</dt><dt class="value">BUILT_IN</dt><dt class="value">CLASS</dt><dt class="value">COMMENT_BLOCK</dt><dt class="value">COMMENT_DOCUMENTATION</dt><dt class="value">COMMENT_END_OF_LINE</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_TEAR_OFF</dt><dt class="value">DIRECTIVE</dt><dt class="value">DYNAMIC_TYPE</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
-      </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">FIELD</dt><dd>
+      </dd><dt class="value">DYNAMIC_LOCAL_VARIABLE_DECLARATION</dt><dt class="value">DYNAMIC_LOCAL_VARIABLE_REFERENCE</dt><dt class="value">DYNAMIC_PARAMETER_DECLARATION</dt><dt class="value">DYNAMIC_PARAMETER_REFERENCE</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
       </dd><dt class="value">FIELD_STATIC</dt><dd>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 434f6bf..61b9776 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -612,14 +612,11 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
-  /// The index in the list of libraries that could be imported to make this
-  /// suggestion accessible in the file where completion was requested. The
-  /// server provides this list of libraries together with suggestions, so that
-  /// information about the library can be shared for multiple suggestions.
-  /// This field is omitted if the library is already imported, so that the
-  /// suggestion can be inserted as is, or if getSuggestions was used rather
-  /// than getSuggestions2.
-  int? libraryUriToImportIndex;
+  /// True if the suggestion is for an element from a not yet imported library.
+  /// This field is omitted if the element is declared locally, or is from
+  /// library is already imported, so that the suggestion can be inserted as
+  /// is, or if getSuggestions was used rather than getSuggestions2.
+  bool? isNotImported;
 
   CompletionSuggestion(
       this.kind,
@@ -645,7 +642,7 @@
       this.hasNamedParameters,
       this.parameterName,
       this.parameterType,
-      this.libraryUriToImportIndex});
+      this.isNotImported});
 
   factory CompletionSuggestion.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -784,11 +781,10 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
-      int? libraryUriToImportIndex;
-      if (json.containsKey('libraryUriToImportIndex')) {
-        libraryUriToImportIndex = jsonDecoder.decodeInt(
-            jsonPath + '.libraryUriToImportIndex',
-            json['libraryUriToImportIndex']);
+      bool? isNotImported;
+      if (json.containsKey('isNotImported')) {
+        isNotImported = jsonDecoder.decodeBool(
+            jsonPath + '.isNotImported', json['isNotImported']);
       }
       return CompletionSuggestion(kind, relevance, completion, selectionOffset,
           selectionLength, isDeprecated, isPotential,
@@ -808,7 +804,7 @@
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
           parameterType: parameterType,
-          libraryUriToImportIndex: libraryUriToImportIndex);
+          isNotImported: isNotImported);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
     }
@@ -888,9 +884,9 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
-    var libraryUriToImportIndex = this.libraryUriToImportIndex;
-    if (libraryUriToImportIndex != null) {
-      result['libraryUriToImportIndex'] = libraryUriToImportIndex;
+    var isNotImported = this.isNotImported;
+    if (isNotImported != null) {
+      result['isNotImported'] = isNotImported;
     }
     return result;
   }
@@ -927,7 +923,7 @@
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
           parameterType == other.parameterType &&
-          libraryUriToImportIndex == other.libraryUriToImportIndex;
+          isNotImported == other.isNotImported;
     }
     return false;
   }
@@ -957,7 +953,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
-        libraryUriToImportIndex,
+        isNotImported,
       ]);
 }
 
@@ -1238,12 +1234,17 @@
   /// this field will not be defined.
   String? aliasedType;
 
+  /// If the element belongs to a library, the URI of the library. Otherwise,
+  /// this field will not be defined.
+  String? libraryUri;
+
   Element(this.kind, this.name, this.flags,
       {this.location,
       this.parameters,
       this.returnType,
       this.typeParameters,
-      this.aliasedType});
+      this.aliasedType,
+      this.libraryUri});
 
   factory Element.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1293,12 +1294,18 @@
         aliasedType = jsonDecoder.decodeString(
             jsonPath + '.aliasedType', json['aliasedType']);
       }
+      String? libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      }
       return Element(kind, name, flags,
           location: location,
           parameters: parameters,
           returnType: returnType,
           typeParameters: typeParameters,
-          aliasedType: aliasedType);
+          aliasedType: aliasedType,
+          libraryUri: libraryUri);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Element', json);
     }
@@ -1337,6 +1344,10 @@
     if (aliasedType != null) {
       result['aliasedType'] = aliasedType;
     }
+    var libraryUri = this.libraryUri;
+    if (libraryUri != null) {
+      result['libraryUri'] = libraryUri;
+    }
     return result;
   }
 
@@ -1353,7 +1364,8 @@
           parameters == other.parameters &&
           returnType == other.returnType &&
           typeParameters == other.typeParameters &&
-          aliasedType == other.aliasedType;
+          aliasedType == other.aliasedType &&
+          libraryUri == other.libraryUri;
     }
     return false;
   }
@@ -1368,6 +1380,7 @@
         returnType,
         typeParameters,
         aliasedType,
+        libraryUri,
       );
 }
 
@@ -1869,6 +1882,7 @@
 ///   DYNAMIC_PARAMETER_REFERENCE
 ///   ENUM
 ///   ENUM_CONSTANT
+///   EXTENSION
 ///   FIELD
 ///   FIELD_STATIC
 ///   FUNCTION
@@ -1982,6 +1996,9 @@
   static const HighlightRegionType ENUM_CONSTANT =
       HighlightRegionType._('ENUM_CONSTANT');
 
+  static const HighlightRegionType EXTENSION =
+      HighlightRegionType._('EXTENSION');
+
   /// Deprecated - no longer sent.
   static const HighlightRegionType FIELD = HighlightRegionType._('FIELD');
 
@@ -2197,6 +2214,7 @@
     DYNAMIC_PARAMETER_REFERENCE,
     ENUM,
     ENUM_CONSTANT,
+    EXTENSION,
     FIELD,
     FIELD_STATIC,
     FUNCTION,
@@ -2301,6 +2319,8 @@
         return ENUM;
       case 'ENUM_CONSTANT':
         return ENUM_CONSTANT;
+      case 'EXTENSION':
+        return EXTENSION;
       case 'FIELD':
         return FIELD;
       case 'FIELD_STATIC':
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 23110a9..24a549e 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
@@ -578,9 +578,15 @@
       Expression argument, int index, Set<String> usedNames) {
     // append type name
     var type = argument.staticType;
+    var library = dartFileEditBuilder.resolvedUnit.libraryElement;
     if (type == null || type.isBottom || type.isDartCoreNull) {
       type = DynamicTypeImpl.instance;
     }
+    if (argument is NamedExpression &&
+        library.isNonNullableByDefault &&
+        type.nullabilitySuffix == NullabilitySuffix.none) {
+      write('required ');
+    }
     if (writeType(type, addSupertypeProposals: true, groupName: 'TYPE$index')) {
       write(' ');
     }
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 e235487..ce716df 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -117,6 +117,16 @@
   /// otherwise this is `null`.
   ParameterElement? _parameterElement;
 
+  /// The enclosing [ClassElement], or `null` if not in a class.
+  late final ClassElement? enclosingClassElement = containingNode
+      .thisOrAncestorOfType<ClassOrMixinDeclaration>()
+      ?.declaredElement;
+
+  /// The enclosing [ExtensionElement], or `null` if not in an extension.
+  late final ExtensionElement? enclosingExtensionElement = containingNode
+      .thisOrAncestorOfType<ExtensionDeclaration>()
+      ?.declaredElement;
+
   /// Compute the appropriate [CompletionTarget] for the given [offset] within
   /// the [entryPoint].
   factory CompletionTarget.forOffset(AstNode entryPoint, int offset) {
@@ -564,6 +574,7 @@
     if (token.type != TokenType.EOF && offset >= token.offset) {
       return null;
     }
+    final startToken = token;
     token = token.precedingComments;
     while (token != null) {
       if (offset <= token.offset) {
@@ -576,6 +587,21 @@
       }
       token = token.next;
     }
+
+    // It's possible the supplied token was a DartDoc token and there were
+    // normal comments before it that don't show up in precedingComments so
+    // check for them too.
+    token = startToken.previous;
+    while (token != null &&
+        offset <= token.end &&
+        (token.type == TokenType.SINGLE_LINE_COMMENT ||
+            token.type == TokenType.MULTI_LINE_COMMENT)) {
+      if (offset >= token.offset) {
+        return token;
+      }
+      token = token.previous;
+    }
+
     return null;
   }
 
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 2110c49..a525245 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -956,6 +956,8 @@
       Element? element;
       if (grandparent is ConstructorReferenceNode) {
         element = grandparent.staticElement;
+      } else if (grandparent is InstanceCreationExpression) {
+        element = grandparent.constructorName.staticElement;
       } else if (grandparent is MethodInvocation) {
         element = grandparent.methodName.staticElement;
       }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
index 96f4683..1209c3f 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
@@ -54,6 +54,10 @@
   /// The relevance used when suggesting a named argument corresponding to a
   /// named parameter that is required.
   static const int requiredNamedArgument = 950;
+
+  /// The relevance used when suggesting a super-constructor parameter as
+  /// a super formal parameter.
+  static const int superFormalParameter = 1000;
 }
 
 /// A name scope for constants that are related to the relevance of completion
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 5ad2871..537f6c2 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -482,6 +482,20 @@
   }
 
   @override
+  void visitSuperFormalParameter(SuperFormalParameter node) {
+    var element = node.declaredElement;
+    if (element is SuperFormalParameterElementImpl) {
+      var superParameter = element.superConstructorParameter;
+      computer._addRegionForToken(node.superKeyword, superParameter);
+      computer._addRegionForNode(node.identifier, superParameter);
+    }
+
+    node.type?.accept(this);
+    node.typeParameters?.accept(this);
+    node.parameters?.accept(this);
+  }
+
+  @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     /// Return the element for the type inferred for each of the variables in
     /// the given list of [variables], or `null` if not all variable have the
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index f49f000..cdb3f12 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -165,7 +165,7 @@
           'hasNamedParameters': isBool,
           'parameterName': isString,
           'parameterType': isString,
-          'libraryUriToImportIndex': isInt
+          'isNotImported': isBool
         }));
 
 /// CompletionSuggestionKind
@@ -237,7 +237,8 @@
       'parameters': isString,
       'returnType': isString,
       'typeParameters': isString,
-      'aliasedType': isString
+      'aliasedType': isString,
+      'libraryUri': isString
     }));
 
 /// ElementKind
@@ -378,6 +379,7 @@
 ///   DYNAMIC_PARAMETER_REFERENCE
 ///   ENUM
 ///   ENUM_CONSTANT
+///   EXTENSION
 ///   FIELD
 ///   FIELD_STATIC
 ///   FUNCTION
@@ -459,6 +461,7 @@
   'DYNAMIC_PARAMETER_REFERENCE',
   'ENUM',
   'ENUM_CONSTANT',
+  'EXTENSION',
   'FIELD',
   'FIELD_STATIC',
   'FUNCTION',
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 481147a..c7211d4 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
@@ -1145,7 +1145,10 @@
       });
     });
     var edit = getEdit(builder);
-    expect(edit.replacement, equalsIgnoringWhitespace('String s, {int index}'));
+    var expectedReplacement = this is WithoutNullSafetyMixin
+        ? 'String s, {int index}'
+        : 'String s, {required int index}';
+    expect(edit.replacement, equalsIgnoringWhitespace(expectedReplacement));
   }
 
   Future<void> test_writeParametersMatchingArguments_required() async {
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 00b5663..969a0ee 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -380,16 +380,14 @@
           omitted if the parameterName field is omitted.
         </p>
       </field>
-      <field name="libraryUriToImportIndex" experimental="true" optional="true">
-        <ref>int</ref>
+      <field name="isNotImported" optional="true" experimental="true">
+        <ref>bool</ref>
         <p>
-          The index in the list of libraries that could be imported to make
-          this suggestion accessible in the file where completion was requested.
-          The server provides this list of libraries together with suggestions,
-          so that information about the library can be shared for multiple
-          suggestions. This field is omitted if the library is  already
-          imported, so that the suggestion can be inserted as is, or if
-          <tt>getSuggestions</tt> was used rather than <tt>getSuggestions2</tt>.
+          True if the suggestion is for an element from a not yet imported
+          library. This field is omitted if the element is declared locally,
+          or is from library is already imported, so that the suggestion can
+          be inserted as is, or if <tt>getSuggestions</tt> was used rather
+          than <tt>getSuggestions2</tt>.
         </p>
       </field>
     </object>
@@ -565,6 +563,13 @@
           Otherwise this field will not be defined.
         </p>
       </field>
+      <field name="libraryUri" optional="true" experimental="true">
+        <ref>String</ref>
+        <p>
+          If the element belongs to a library, the URI of the library.
+          Otherwise, this field will not be defined.
+        </p>
+      </field>
     </object>
   </type>
   <type name="ElementKind">
@@ -714,6 +719,7 @@
       </value>
       <value><code>ENUM</code></value>
       <value><code>ENUM_CONSTANT</code></value>
+      <value><code>EXTENSION</code></value>
       <value>
         <code>FIELD</code>
         <p>Deprecated - no longer sent.</p>
diff --git a/pkg/analyzer_utilities/lib/check/iterable.dart b/pkg/analyzer_utilities/lib/check/iterable.dart
index 0e3e0d3..0b921bf 100644
--- a/pkg/analyzer_utilities/lib/check/iterable.dart
+++ b/pkg/analyzer_utilities/lib/check/iterable.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer_utilities/check/check.dart';
 import 'package:meta/meta.dart';
+import 'package:test/test.dart' as test_package;
 
 extension IterableExtension<T> on CheckTarget<Iterable<T>> {
   void get isEmpty {
@@ -18,6 +19,38 @@
     }
   }
 
+  /// Succeeds if there is an element that matches the [matcher],
+  void containsMatch(void Function(CheckTarget<T> element) matcher) {
+    var elementList = value.toList();
+    for (var i = 0; i < elementList.length; i++) {
+      if (_matches(elementList, i, matcher)) {
+        return;
+      }
+    }
+    fail('Does not contain at least one element that matches');
+  }
+
+  /// Fails if for any matcher there is an element that matches.
+  void excludesAll(
+    Iterable<void Function(CheckTarget<T> element)> matchers,
+  ) {
+    var elementList = value.toList();
+    var matcherList = matchers.toList();
+    var included = <int>[];
+    for (var i = 0; i < matcherList.length; i++) {
+      var matcher = matcherList[i];
+      for (var j = 0; j < elementList.length; j++) {
+        if (_matches(elementList, j, matcher)) {
+          included.add(i);
+          break;
+        }
+      }
+    }
+    if (included.isNotEmpty) {
+      fail('Unexpectedly includes matchers at ${valueStr(included)}');
+    }
+  }
+
   @UseResult.unless(parameterDefined: 'expected')
   CheckTarget<int> hasLength([int? expected]) {
     var actual = value.length;
@@ -28,4 +61,139 @@
 
     return nest(actual, (length) => 'has length $length');
   }
+
+  /// Succeeds if for each matcher in [matchers] there is at least one
+  /// matching element.
+  void includesAll(
+    Iterable<void Function(CheckTarget<T> element)> matchers,
+  ) {
+    var elementList = value.toList();
+    var matcherList = matchers.toList();
+    var notIncluded = <int>[];
+    for (var i = 0; i < matcherList.length; i++) {
+      var matcher = matcherList[i];
+      notIncluded.add(i);
+      for (var j = 0; j < elementList.length; j++) {
+        if (_matches(elementList, j, matcher)) {
+          notIncluded.removeLast();
+          break;
+        }
+      }
+    }
+    if (notIncluded.isNotEmpty) {
+      fail('Does not include matchers at ${valueStr(notIncluded)}');
+    }
+  }
+
+  /// Succeeds if for each matcher there is exactly one matching element,
+  /// in the same relative order.
+  void includesAllInOrder(
+    Iterable<void Function(CheckTarget<T> element)> matchers,
+  ) {
+    var elementList = value.toList();
+    var matcherList = matchers.toList();
+    var elementIndex = 0;
+    for (var i = 0; i < matcherList.length; i++) {
+      var matcher = matcherList[i];
+      var hasMatch = false;
+      for (; elementIndex < elementList.length; elementIndex++) {
+        if (_matches(elementList, elementIndex, matcher)) {
+          hasMatch = true;
+          for (var j = elementIndex + 1; j < elementList.length; j++) {
+            if (_matches(elementList, j, matcher)) {
+              fail(
+                'Matcher at ${valueStr(i)} matches elements at '
+                '${valueStr(elementIndex)} and ${valueStr(j)}',
+              );
+            }
+          }
+          break;
+        } else {}
+      }
+      if (!hasMatch) {
+        fail('Does not include matcher at ${valueStr(i)}');
+      }
+    }
+  }
+
+  /// Succeeds if the number of [matchers] is exactly the same as the number
+  /// of elements in [value], and each matcher matches the element at the
+  /// corresponding index.
+  void matches(
+    Iterable<void Function(CheckTarget<T> element)> matchers,
+  ) {
+    var elementList = value.toList();
+    var matcherList = matchers.toList();
+    if (elementList.length != matcherList.length) {
+      fail('Expected ${valueStr(matcherList.length)} elements, '
+          'actually ${valueStr(elementList.length)}');
+    }
+
+    for (var index = 0; index < matcherList.length; index++) {
+      var element = elementList[index];
+      var matcher = matcherList[index];
+      matcher(
+        nest(
+          element,
+          (element) => 'element ${valueStr(element)} at ${valueStr(index)}',
+        ),
+      );
+    }
+  }
+
+  /// Succeeds if the number of [matchers] is exactly the same as the number
+  /// of elements in [value], and for each matcher there is exactly one element
+  /// that matches.
+  void matchesInAnyOrder(
+    Iterable<void Function(CheckTarget<T> element)> matchers,
+  ) {
+    var elementList = value.toList();
+    var matcherList = matchers.toList();
+    if (elementList.length != matcherList.length) {
+      fail('Expected ${valueStr(matcherList.length)} elements, '
+          'actually ${valueStr(elementList.length)}');
+    }
+
+    for (var matcherIndex = 0;
+        matcherIndex < matcherList.length;
+        matcherIndex++) {
+      var matcher = matcherList[matcherIndex];
+      T? matchedElement;
+      for (var elementIndex = 0;
+          elementIndex < elementList.length;
+          elementIndex++) {
+        var element = elementList[elementIndex];
+        if (!_matches(elementList, elementIndex, matcher)) {
+          continue;
+        }
+        // The element matches, check that it is unique.
+        if (matchedElement == null) {
+          matchedElement = element;
+        } else {
+          fail('Already matched ${valueStr(matchedElement)}, '
+              'found ${valueStr(element)}');
+        }
+      }
+      if (matchedElement == null) {
+        fail('No match at ${valueStr(matcherIndex)}');
+      }
+    }
+  }
+
+  bool _matches(
+    List<T> elementList,
+    int index,
+    void Function(CheckTarget<T> element) matcher,
+  ) {
+    var elementTarget = nest(
+      elementList[index],
+      (element) => 'element ${valueStr(element)} at ${valueStr(index)}',
+    );
+    try {
+      matcher(elementTarget);
+      return true;
+    } on test_package.TestFailure {
+      return false;
+    }
+  }
 }
diff --git a/pkg/analyzer_utilities/test/check/check_test.dart b/pkg/analyzer_utilities/test/check/check_test.dart
index 907438f..b88501c 100644
--- a/pkg/analyzer_utilities/test/check/check_test.dart
+++ b/pkg/analyzer_utilities/test/check/check_test.dart
@@ -62,6 +62,39 @@
       });
     });
     group('Iterable', () {
+      test('containsMatch', () {
+        check(<int>[0]).containsMatch((e) => e.isZero);
+        check(<int>[1, 0, 2]).containsMatch((e) => e.isZero);
+        _fails(() => check(<int>[]).containsMatch((e) => e.isZero));
+        _fails(() => check(<int>[1]).containsMatch((e) => e.isZero));
+      });
+      test('excludesAll', () {
+        check(<int>[]).excludesAll([
+          (e) => e.isEqualTo(0),
+        ]);
+        check([1]).excludesAll([
+          (e) => e.isEqualTo(0),
+          (e) => e.isEqualTo(2),
+        ]);
+        // Fails if any match.
+        _fails(() {
+          check(<int>[0]).excludesAll([
+            (e) => e.isEqualTo(0),
+          ]);
+        });
+        _fails(() {
+          check(<int>[0]).excludesAll([
+            (e) => e.isZero,
+          ]);
+        });
+        _fails(() {
+          check(<int>[0]).excludesAll([
+            (e) => e.isEqualTo(2),
+            (e) => e.isEqualTo(1),
+            (e) => e.isEqualTo(0),
+          ]);
+        });
+      });
       test('hasLength', () {
         check(<int>[]).hasLength().isZero;
         check(<int>[0]).hasLength().isEqualTo(1);
@@ -80,6 +113,74 @@
         _fails(() => check(<int>[]).hasLength().isEqualTo(1));
         _fails(() => check(<int>[0]).hasLength().isEqualTo(0));
       });
+      test('includesAll', () {
+        // Extra elements are OK.
+        check([0, 1, 2]).includesAll([
+          (e) => e.isEqualTo(0),
+          (e) => e.isEqualTo(1),
+        ]);
+        // Order does not matter.
+        check([0, 1, 2]).includesAll([
+          (e) => e.isEqualTo(1),
+          (e) => e.isEqualTo(0),
+        ]);
+        // Must have all elements.
+        _fails(() {
+          check(<int>[]).includesAll([
+            (e) => e.isEqualTo(0),
+          ]);
+        });
+        _fails(() {
+          check([0]).includesAll([
+            (e) => e.isEqualTo(0),
+            (e) => e.isEqualTo(1),
+          ]);
+        });
+        _fails(() {
+          check([1]).includesAll([
+            (e) => e.isEqualTo(0),
+            (e) => e.isEqualTo(1),
+          ]);
+        });
+      });
+      test('includesAllInOrder', () {
+        // Extra elements are OK.
+        check([0, 1, 2, 3, 4]).includesAllInOrder([
+          (e) => e.isEqualTo(0),
+          (e) => e.isEqualTo(3),
+        ]);
+        // Exactly one element should match.
+        _fails(() {
+          check([0, 1, 0, 2]).includesAllInOrder([
+            (e) => e.isZero,
+          ]);
+        });
+        // Must be in the requested order.
+        _fails(() {
+          check([0, 1, 2]).includesAllInOrder([
+            (e) => e.isEqualTo(1),
+            (e) => e.isEqualTo(0),
+          ]);
+        });
+        // Must have all elements.
+        _fails(() {
+          check(<int>[]).includesAllInOrder([
+            (e) => e.isEqualTo(0),
+          ]);
+        });
+        _fails(() {
+          check([0]).includesAllInOrder([
+            (e) => e.isEqualTo(0),
+            (e) => e.isEqualTo(1),
+          ]);
+        });
+        _fails(() {
+          check([1]).includesAllInOrder([
+            (e) => e.isEqualTo(0),
+            (e) => e.isEqualTo(1),
+          ]);
+        });
+      });
       test('isEmpty', () {
         check(<int>[]).isEmpty;
         check(<int>{}).isEmpty;
@@ -96,6 +197,76 @@
         _fails(() => check(<int>[]).isNotEmpty);
         _fails(() => check(<int>{}).isNotEmpty);
       });
+      test('matches', () {
+        check(<int>[]).matches([]);
+        check(<int>[0]).matches([
+          (e) => e.isEqualTo(0),
+        ]);
+        check(<int>[0, 1]).matches([
+          (e) => e.isEqualTo(0),
+          (e) => e.isEqualTo(1),
+        ]);
+        // Order is important.
+        _fails(
+          () => check([0, 1]).matches([
+            (e) => e.isEqualTo(1),
+            (e) => e.isEqualTo(0),
+          ]),
+        );
+        // Too few matchers.
+        _fails(
+          () => check([0, 1]).matches([
+            (e) => e.isEqualTo(0),
+          ]),
+        );
+        // Too many matchers.
+        _fails(
+          () => check([0]).matches([
+            (e) => e.isEqualTo(0),
+            (e) => e.isEqualTo(1),
+          ]),
+        );
+      });
+      test('matchesInAnyOrder', () {
+        // Order does not matter.
+        check([0, 1]).matchesInAnyOrder([
+          (e) => e.isEqualTo(0),
+          (e) => e.isEqualTo(1),
+        ]);
+        check([0, 1]).matchesInAnyOrder([
+          (e) => e.isEqualTo(1),
+          (e) => e.isEqualTo(0),
+        ]);
+        // Matchers can be different.
+        check([0, 1]).matchesInAnyOrder([
+          (e) => e.isZero,
+          (e) => e.isEqualTo(1),
+        ]);
+        check([0, 10]).matchesInAnyOrder([
+          (e) => e.isZero,
+          (e) => e.isGreaterThan(5),
+        ]);
+        // Wrong number of matchers.
+        _fails(
+          () => check([0, 1]).matchesInAnyOrder([
+            (e) => e.isZero,
+          ]),
+        );
+        // The first matcher accepts more than one element.
+        _fails(
+          () => check([1, 2]).matchesInAnyOrder([
+            (e) => e.isGreaterThan(0),
+            (e) => e.isEqualTo(2),
+          ]),
+        );
+        // The second matcher accepts more than one element.
+        _fails(
+          () => check([1, 2]).matchesInAnyOrder([
+            (e) => e.isEqualTo(2),
+            (e) => e.isGreaterThan(0),
+          ]),
+        );
+      });
     });
     group('nullability', () {
       const int? notNullable = 0;
diff --git a/pkg/async_helper/lib/async_helper.dart b/pkg/async_helper/lib/async_helper.dart
index 1f3acb1..d4d536f 100644
--- a/pkg/async_helper/lib/async_helper.dart
+++ b/pkg/async_helper/lib/async_helper.dart
@@ -89,56 +89,50 @@
   return f().then(asyncSuccess);
 }
 
-bool _pass(dynamic object) => true;
-
-/// Calls [f] and verifies that it throws a `T`.
+/// Verifies that the asyncronous [result] throws a [T].
 ///
-/// The optional [check] function can provide additional validation that the
-/// correct object is being thrown. For example, to check the content of the
-/// thrown object you could write this:
+/// Fails if [result] completes with a value, or it completes with
+/// an error which is not a [T].
 ///
-///     asyncExpectThrows<MyException>(myThrowingFunction,
-///          (e) => e.myMessage.contains("WARNING"));
-///
-/// If `f` fails an expectation (i.e., throws an [ExpectException]), that
-/// exception is not caught by [asyncExpectThrows]. The test is still considered
-/// failing.
-void asyncExpectThrows<T>(Future<void> f(),
-    [bool check(T error) = _pass, String reason = ""]) {
-  var type = "";
-  if (T != dynamic && T != Object) type = "<$T>";
+/// Returns the accepted thrown object.
+/// For example, to check the content of the thrown object,
+/// you could write this:
+/// ```
+/// var e = await asyncExpectThrows<MyException>(asyncExpression)
+/// Expect.isTrue(e.myMessage.contains("WARNING"));
+/// ```
+/// If `result` completes with an [ExpectException] error from another
+/// failed test expectation, that error cannot be caught and accepted.
+Future<T> asyncExpectThrows<T extends Object>(Future<void> result,
+    [String reason = ""]) {
   // Handle null being passed in from legacy code while also avoiding producing
   // an unnecessary null check warning here.
   if ((reason as dynamic) == null) reason = "";
+
+  var type = "";
+  if (T != dynamic && T != Object) type = "<$T>";
   var header = "asyncExpectThrows$type(${reason}):";
 
+  if ((result as dynamic) == null) {
+    Expect.testError("$header result Future must not be null.");
+  }
   // TODO(rnystrom): It might useful to validate that T is not bound to
   // ExpectException since that won't work.
 
-  if (f is! Function()) {
-    // Only throws from executing the function body should count as throwing.
-    // The failure to even call `f` should throw outside the try/catch.
-    Expect.testError("$header Function not callable with zero arguments.");
-  }
-
-  var result = f();
-  if (result is! Future) {
-    Expect.testError("$header Function did not return a Future.");
-  }
-
   asyncStart();
-  result.then<Null>((_) {
+  return result.then<T>((_) {
     throw ExpectException("$header Did not throw.");
-  }).catchError((error, stack) {
+  }, onError: (error, stack) {
     // A test failure doesn't count as throwing.
     if (error is ExpectException) throw error;
 
-    if (error is! T || (check != null && !check(error))) {
+    if (error is! T) {
       // Throws something unexpected.
       throw ExpectException(
           "$header Unexpected '${Error.safeToString(error)}'\n$stack");
     }
 
     asyncEnd();
+    return error;
   });
 }
diff --git a/pkg/async_helper/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
index fa5d319..5b58930 100644
--- a/pkg/async_helper/lib/async_minitest.dart
+++ b/pkg/async_helper/lib/async_minitest.dart
@@ -215,14 +215,14 @@
   Expect.isNull(o);
 }
 
-void _checkThrow<T>(dynamic v, void onError(error)) {
+void _checkThrow<T extends Object>(dynamic v, void onError(error)) {
   if (v is Future) {
     asyncStart();
     v.then((_) {
       Expect.fail("Did not throw");
     }, onError: (e, s) {
       if (e is! T) throw e;
-      if (onError != null) onError(e);
+      onError(e);
       asyncEnd();
     });
     return;
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index c8aba18..ed1087c 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -5,10 +5,6 @@
 library leg_apiimpl;
 
 import 'dart:async';
-import 'dart:convert' show utf8;
-
-import 'package:front_end/src/api_unstable/dart2js.dart'
-    show getSupportedLibraryNames;
 
 import '../compiler_new.dart' as api;
 import 'common/metrics.dart' show Metrics, Metric;
@@ -17,7 +13,6 @@
 import 'compiler.dart';
 import 'diagnostics/messages.dart' show Message;
 import 'environment.dart';
-import 'io/source_file.dart';
 import 'options.dart' show CompilerOptions;
 
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
@@ -58,55 +53,22 @@
         null, null, null, null, message, api.Diagnostic.VERBOSE_INFO);
   }
 
-  Future setupSdk() {
-    var future = Future.value(null);
-    _Environment env = environment;
-    if (env.supportedLibraries == null) {
-      future = future.then((_) {
-        Uri specificationUri = options.librariesSpecificationUri;
-        return provider.readFromUri(specificationUri).then((api.Input spec) {
-          String json = null;
-          // TODO(sigmund): simplify this, we have some API inconsistencies when
-          // our internal input adds a terminating zero.
-          if (spec is SourceFile) {
-            json = spec.slowText();
-          } else if (spec is Binary) {
-            json = utf8.decode(spec.data);
-          }
-
-          // TODO(sigmund): would be nice to front-load some of the CFE option
-          // processing and parse this .json file only once.
-          env.supportedLibraries = getSupportedLibraryNames(specificationUri,
-                  json, options.compileForServer ? "dart2js_server" : "dart2js")
-              .toSet();
-        });
-      });
-    }
-    // TODO(johnniwinther): This does not apply anymore.
-    // The incremental compiler sets up the sdk before run.
-    // Therefore this will be called a second time.
-    return future;
-  }
-
   @override
   Future<bool> run() {
     Duration setupDuration = measurer.elapsedWallClock;
-    return selfTask.measureSubtask("impl.run", () {
-      return setupSdk().then((_) {
-        return super.run();
-      }).then((bool success) {
-        if (options.verbose) {
-          StringBuffer timings = StringBuffer();
-          computeTimings(setupDuration, timings);
-          logVerbose('$timings');
-        }
-        if (options.reportPrimaryMetrics || options.reportSecondaryMetrics) {
-          StringBuffer metrics = StringBuffer();
-          collectMetrics(metrics);
-          logInfo('$metrics');
-        }
-        return success;
-      });
+    return selfTask.measureSubtask("impl.run", () async {
+      bool success = await super.run();
+      if (options.verbose) {
+        StringBuffer timings = StringBuffer();
+        computeTimings(setupDuration, timings);
+        logVerbose('$timings');
+      }
+      if (options.reportPrimaryMetrics || options.reportSecondaryMetrics) {
+        StringBuffer metrics = StringBuffer();
+        collectMetrics(metrics);
+        logInfo('$metrics');
+      }
+      return success;
     });
   }
 
@@ -233,50 +195,18 @@
 class _Environment implements Environment {
   final Map<String, String> definitions;
   Map<String, String> _completeMap;
-  Set<String> supportedLibraries;
 
   _Environment(this.definitions);
 
   @override
-  String valueOf(String name) {
-    if (_completeMap != null) return _completeMap[name];
-    var result = definitions[name];
-    if (result != null || definitions.containsKey(name)) return result;
-    if (!name.startsWith(_dartLibraryEnvironmentPrefix)) return null;
-
-    String libraryName = name.substring(_dartLibraryEnvironmentPrefix.length);
-
-    // Private libraries are not exposed to the users.
-    if (libraryName.startsWith("_")) return null;
-    if (supportedLibraries.contains(libraryName)) return "true";
-    return null;
-  }
-
-  @override
   Map<String, String> toMap() {
     if (_completeMap == null) {
       _completeMap = Map<String, String>.from(definitions);
-      for (String libraryName in supportedLibraries) {
-        if (!libraryName.startsWith("_")) {
-          String key = '${_dartLibraryEnvironmentPrefix}${libraryName}';
-          if (!definitions.containsKey(key)) {
-            _completeMap[key] = "true";
-          }
-        }
-      }
     }
     return _completeMap;
   }
 }
 
-/// For every 'dart:' library, a corresponding environment variable is set
-/// to "true". The environment variable's name is the concatenation of
-/// this prefix and the name (without the 'dart:'.
-///
-/// For example 'dart:html' has the environment variable 'dart.library.html' set
-/// to "true".
-const String _dartLibraryEnvironmentPrefix = 'dart.library.';
-
 class _TimingData {
   final String description;
   final int milliseconds;
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 18fa4cb..55ad35e 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -142,6 +142,10 @@
 
   static const String cfeInvocationModes = '--cfe-invocation-modes';
 
+  /// Flag to indicate how the compiler is invoked. Used to ensure
+  /// dart2js is only invoked from supported tools and through the Dart CLI.
+  static const String invoker = '--invoker';
+
   /// Flag to stop after splitting the program.
   static const String stopAfterProgramSplit = '--stop-after-program-split';
 
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index dad3d720..35d9f52 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1087,9 +1087,6 @@
   const _EmptyEnvironment();
 
   @override
-  String valueOf(String key) => null;
-
-  @override
   Map<String, String> toMap() => const {};
 }
 
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 8a49df4..a57892b 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -139,6 +139,7 @@
   ReadStrategy readStrategy = ReadStrategy.fromDart;
   WriteStrategy writeStrategy = WriteStrategy.toJs;
   FeatureOptions features = FeatureOptions();
+  String invoker;
 
   void passThrough(String argument) => options.add(argument);
   void ignoreOption(String argument) {}
@@ -480,6 +481,10 @@
     passThrough(argument);
   }
 
+  void setInvoker(String argument) {
+    invoker = extractParameter(argument);
+  }
+
   void handleThrowOnError(String argument) {
     throwOnError = true;
     String parameter = extractParameter(argument, isOptionalArgument: true);
@@ -645,6 +650,7 @@
     OptionHandler(Flags.testMode, passThrough),
     OptionHandler('${Flags.dumpSsa}=.+', passThrough),
     OptionHandler('${Flags.cfeInvocationModes}=.+', passThrough),
+    OptionHandler('${Flags.invoker}=.+', setInvoker),
     OptionHandler('${Flags.verbosity}=.+', passThrough),
 
     // Experimental features.
@@ -694,6 +700,13 @@
 
   parseCommandLine(handlers, argv);
 
+  if (invoker == null) {
+    warning("The 'dart2js' entrypoint script is deprecated, "
+        "please use 'dart compile js' instead.");
+  } else if (verbose != null) {
+    print("Compiler invoked from: '$invoker'");
+  }
+
   // TODO(johnniwinther): Measure time for reading files.
   SourceFileProvider inputProvider;
   if (bazelPaths != null) {
@@ -1128,28 +1141,25 @@
   // before and after running the compiler. Another two lines may be
   // used to print an error message.
   print('''
-Usage: dart2js [options] dartfile
+Compile Dart to JavaScript.
 
-Compiles Dart to JavaScript.
-
-Common options:
-  -o <file> Generate the output into <file>.
-  -m        Generate minified output.
-  -h        Display this message (add -v for information about all options).''');
+Usage: dart compile js [arguments] <dart entry point>
+  -h, --help      Print this usage information (add -v for information about all options).
+  -o, --output    Write the output to <file name>.
+  -O<0,1,2,3,4>   Set the compiler optimization level (defaults to -O1).
+  ''');
 }
 
 void verboseHelp() {
   print(r'''
-Usage: dart2js [options] dartfile
+Compile Dart to JavaScript.
 
-Compiles Dart to JavaScript.
-
-Supported options:
+Usage: dart compile js [arguments] <dart entry point>
   -h, /h, /?, --help
-    Display this message (add -v for information about all options).
+    Print this usage information (add -v for information about all options).
 
-  -o <file>, --out=<file>
-    Generate the output into <file>.
+  -o <file name>, --out=<file name>
+    Write the output to <file name>.
 
   -m, --minify
     Generate minified output.
@@ -1352,6 +1362,15 @@
   fail(message);
 }
 
+void warning(String message) {
+  if (diagnosticHandler != null) {
+    diagnosticHandler.report(
+        null, null, -1, -1, message, api.Diagnostic.WARNING);
+  } else {
+    print('Warning: $message');
+  }
+}
+
 Future<void> main(List<String> arguments) async {
   // Expand `@path/to/file`
   // When running from bazel, argument of the form `@path/to/file` might be
@@ -1359,7 +1378,7 @@
   // file and expanding them into the resulting argument list.
   //
   // TODO: Move this logic to a single place and share it among all tools.
-  if (arguments.last.startsWith('@')) {
+  if (arguments.length > 0 && arguments.last.startsWith('@')) {
     var extra = _readLines(arguments.last.substring(1));
     arguments = arguments.take(arguments.length - 1).followedBy(extra).toList();
   }
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
index 2520547..2428f3e 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
@@ -28,12 +28,10 @@
   /// Imports which load before [import].
   final Set<Constraint> predecessors = {};
 
-  /// Whether or not this [ConstraintNode] should always apply transitions as
+  /// Whether or not this [Constraint] should always apply transitions as
   /// opposed to conditionally applying transitions.
   bool get alwaysApplyTransitions {
-    return combinerType == null ||
-        combinerType == CombinerType.and ||
-        combinerType == CombinerType.fuse;
+    return combinerType == null || combinerType == CombinerType.and;
   }
 
   Constraint(this.name, this.imports, this.combinerType) {
@@ -122,19 +120,36 @@
 
     // 3) Build a graph of [Constraint]s by processing user constraints and
     // intializing each [Constraint]'s predecessor / successor members.
-    for (var constraint in nodes.ordered) {
-      var successor = nodeToConstraintMap[constraint.successor];
-      var predecessor = nodeToConstraintMap[constraint.predecessor];
+    void createEdge(NamedNode successorNode, NamedNode predecessorNode) {
+      var successor = nodeToConstraintMap[successorNode];
+      var predecessor = nodeToConstraintMap[predecessorNode];
       successor.predecessors.add(predecessor);
       predecessor.successors.add(successor);
     }
 
+    for (var constraint in nodes.ordered) {
+      if (constraint is RelativeOrderNode) {
+        createEdge(constraint.successor, constraint.predecessor);
+      } else if (constraint is FuseNode) {
+        // Fuse nodes are just syntactic sugar for generating cycles in the
+        // ordering graph.
+        for (var node1 in constraint.nodes) {
+          for (var node2 in constraint.nodes) {
+            if (node1 != node2) {
+              createEdge(node1, node2);
+            }
+          }
+        }
+      }
+    }
+
     // 4) Compute the transitive closure of constraints. This gives us a map of
     // transitiveTransitions, where each key is a parent [ImportEntity] and each
     // value represents the transitive set of child [ImportEntity]s which are
     // always loaded after the parent.
     Map<ImportEntity, Set<ImportEntity>> singletonTransitions = {};
     Map<Constraint, SetTransition> setTransitions = {};
+    Map<Constraint, Set<ImportEntity>> processed = {};
     Queue<_WorkItem> queue = Queue.from(nodeToConstraintMap.values
         .where((node) => node.successors.isEmpty)
         .map((node) => _WorkItem(node)));
@@ -154,14 +169,6 @@
         for (var import in imports) {
           // We insert an implicit 'self' transition for every import.
           var transitions = singletonTransitions[import] ??= {import};
-
-          // In the case of [CombinerType.fuse], the nodes in the
-          // [Constraint] form a strongly connected component,
-          // i.e. [ImportEntity]s that are always part of a
-          // single [ImportSet].
-          if (constraint.combinerType == CombinerType.fuse) {
-            transitions.addAll(imports);
-          }
           transitions.addAll(transitiveChildren);
         }
       } else {
@@ -177,6 +184,14 @@
         ...transitiveChildren,
       };
       for (var predecessor in constraint.predecessors) {
+        // We allow cycles in the constraint graph, so we need to support
+        // reprocessing constraints when we need to consider new transitive
+        // children.
+        if (processed.containsKey(predecessor) &&
+            processed[predecessor].containsAll(predecessorTransitiveChildren)) {
+          continue;
+        }
+        (processed[predecessor] ??= {}).addAll(predecessorTransitiveChildren);
         queue.add(_WorkItem(predecessor,
             transitiveChildren: predecessorTransitiveChildren));
       }
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
index 92068f6..17a6904 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
@@ -71,13 +71,11 @@
 
 /// A [CombinerType] defines how to combine multiple [ReferenceNode]s in a
 /// single step.
-enum CombinerType { fuse, and, or }
+enum CombinerType { and, or }
 
 CombinerType parseCombinerType(Map<String, dynamic> nodeJson) {
   String type = nodeJson['type'];
   switch (type) {
-    case 'fuse':
-      return CombinerType.fuse;
     case 'and':
       return CombinerType.and;
     case 'or':
@@ -89,8 +87,6 @@
 
 String combinerTypeToString(CombinerType type) {
   switch (type) {
-    case CombinerType.fuse:
-      return 'fuse';
     case CombinerType.and:
       return 'and';
     case CombinerType.or:
@@ -151,9 +147,13 @@
   }
 }
 
+/// An [OrderNode] is a [Node] without a name that indicates a temporal
+/// constraint.
+abstract class OrderNode extends Node {}
+
 /// A [RelativeOrderNode] is an unnamed [Node] which defines a relative
 /// load order between two [NamedNode]s.
-class RelativeOrderNode extends Node {
+class RelativeOrderNode extends OrderNode {
   final NamedNode predecessor;
   final NamedNode successor;
 
@@ -165,7 +165,7 @@
   @override
   Map<String, dynamic> toJson() {
     return {
-      'type': 'order',
+      'type': 'relative_order',
       'predecessor': predecessor.name,
       'successor': successor.name
     };
@@ -185,6 +185,35 @@
   }
 }
 
+/// A [FuseNode] is an [OrderNode] with a list of [NamedNode] children.
+/// A [FuseNode] joins its children into a strongly connected component.
+class FuseNode extends OrderNode {
+  final Set<NamedNode> nodes;
+
+  FuseNode(this.nodes);
+
+  @override
+  Map<String, dynamic> toJson() {
+    return {'type': 'fuse', 'nodes': nodes.map((node) => node.name).toList()};
+  }
+
+  static FuseNode fromJson(
+      Map<String, dynamic> nodeJson, Map<String, NamedNode> nameMap) {
+    List<dynamic> referencesJson = _jsonLookup(nodeJson, 'nodes');
+    Set<NamedNode> nodes = {};
+    for (String reference in referencesJson) {
+      nodes.add(nameMap[reference]);
+    }
+    return FuseNode(nodes);
+  }
+
+  @override
+  String toString() {
+    var nodeNames = nodes.map((node) => node.name).join(', ');
+    return 'FuseNode(nodes=$nodeNames)';
+  }
+}
+
 /// A builder class for constructing constraint nodes.
 typedef ReferenceNodeNamer = String Function(UriAndPrefix);
 
@@ -221,6 +250,14 @@
     return namedNodes[nodeName];
   }
 
+  ReferenceNode _lookupReferenceNode(String nodeName) {
+    var node = _lookupNamedNode(nodeName);
+    if (node is! ReferenceNode) {
+      throw 'node $nodeName is not a ReferenceNode.';
+    }
+    return node as ReferenceNode;
+  }
+
   /// Returns a [ReferenceNode] referencing [importUriAndPrefix].
   /// [ReferenceNode]s are typically created in bulk, by mapping over a list of
   /// strings of imports in the form 'uri#prefix'. In further builder calls,
@@ -242,16 +279,8 @@
   /// Creates a [CombinerNode] which can be referenced by [name] in further
   /// calls to the builder.
   CombinerNode combinerNode(String name, Set<String> nodes, CombinerType type) {
-    ReferenceNode _lookup(String nodeName) {
-      var node = _lookupNamedNode(nodeName);
-      if (node is! ReferenceNode) {
-        // TODO(joshualitt): Implement nested combiners.
-        throw '$name references node $nodeName which is not a ReferenceNode.';
-      }
-      return node as ReferenceNode;
-    }
-
-    return _addNamedNode(CombinerNode(name, type, nodes.map(_lookup).toSet()));
+    return _addNamedNode(
+        CombinerNode(name, type, nodes.map(_lookupReferenceNode).toSet()));
   }
 
   /// Creates an 'and' [CombinerNode] which can be referenced by [name] in
@@ -260,10 +289,10 @@
     return combinerNode(name, nodes, CombinerType.and);
   }
 
-  /// Creates a 'fuse' [CombinerNode] which can be referenced by [name] in
-  /// further calls to the builder.
-  CombinerNode fuseNode(String name, Set<String> nodes) {
-    return combinerNode(name, nodes, CombinerType.fuse);
+  /// Creates a [FuseNode], which is a type of [OrderNode] indicating a
+  /// [Set<String>] nodes can always be loaded together.
+  FuseNode fuseNode(Set<String> nodes) {
+    return FuseNode(nodes.map(_lookupNamedNode).toSet());
   }
 
   /// Creates an 'or' [CombinerNode] which can be referenced by [name] in
@@ -277,7 +306,7 @@
 /// program split constraints.
 class ConstraintData {
   final List<NamedNode> named;
-  final List<RelativeOrderNode> ordered;
+  final List<OrderNode> ordered;
 
   ConstraintData(this.named, this.ordered);
 }
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
index 968b07b..e60c182 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
@@ -10,7 +10,7 @@
 /// [ConstraintData] object.
 class Parser {
   final Map<String, NamedNode> nameMap = {};
-  final List<RelativeOrderNode> orderedNodes = [];
+  final List<OrderNode> orderedNodes = [];
 
   void parseReference(Map<String, dynamic> nodeJson) {
     var reference = ReferenceNode.fromJson(nodeJson);
@@ -22,29 +22,36 @@
     nameMap[combinerNode.name] = combinerNode;
   }
 
-  void parseOrder(Map<String, dynamic> nodeJson) {
+  void parseRelativeOrder(Map<String, dynamic> nodeJson) {
     orderedNodes.add(RelativeOrderNode.fromJson(nodeJson, nameMap));
   }
 
+  void parseFuse(Map<String, dynamic> nodeJson) {
+    orderedNodes.add(FuseNode.fromJson(nodeJson, nameMap));
+  }
+
   /// Reads a program split constraints json file string and returns a [Nodes]
   /// object reflecting the parsed constraints.
   ConstraintData read(String programSplitJson) {
     List<dynamic> doc = json.decode(programSplitJson);
     List<Map<String, dynamic>> referenceConstraints = [];
     List<Map<String, dynamic>> combinerConstraints = [];
-    List<Map<String, dynamic>> orderConstraints = [];
+    List<Map<String, dynamic>> fuseConstraints = [];
+    List<Map<String, dynamic>> relativeOrderConstraints = [];
     for (Map<String, dynamic> constraint in doc) {
       switch (constraint['type']) {
         case 'reference':
           referenceConstraints.add(constraint);
           break;
         case 'and':
-        case 'fuse':
         case 'or':
           combinerConstraints.add(constraint);
           break;
-        case 'order':
-          orderConstraints.add(constraint);
+        case 'fuse':
+          fuseConstraints.add(constraint);
+          break;
+        case 'relative_order':
+          relativeOrderConstraints.add(constraint);
           break;
         default:
           throw 'Unrecognized constraint type in $constraint';
@@ -54,7 +61,8 @@
     // Parse references, than combiners, than finally sequences.
     referenceConstraints.forEach(parseReference);
     combinerConstraints.forEach(parseCombiner);
-    orderConstraints.forEach(parseOrder);
+    fuseConstraints.forEach(parseFuse);
+    relativeOrderConstraints.forEach(parseRelativeOrder);
     return ConstraintData(nameMap.values.toList(), orderedNodes);
   }
 }
diff --git a/pkg/compiler/lib/src/environment.dart b/pkg/compiler/lib/src/environment.dart
index 67db9ac..efc2bb0 100644
--- a/pkg/compiler/lib/src/environment.dart
+++ b/pkg/compiler/lib/src/environment.dart
@@ -8,12 +8,6 @@
 /// conditional imports, and from `const String.fromEnvironment` and
 /// other similar constructors.
 abstract class Environment {
-  /// Return the string value of the given key.
-  ///
-  /// Note that `bool.fromEnvironment` and `int.fromEnvironment` are also
-  /// implemented in terms of `String.fromEnvironment`.
-  String valueOf(String key);
-
   /// Returns the full environment as map.
   Map<String, String> toMap();
 }
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 8d2c4b9..b3195a7 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -1111,7 +1111,7 @@
 
   @override
   visitVariableInitialization(js.VariableInitialization node) {
-    visit(node.leftHandSide);
+    visit(node.declaration);
     visit(node.value);
   }
 
diff --git a/pkg/compiler/lib/src/ir/constants.dart b/pkg/compiler/lib/src/ir/constants.dart
index 6994046..d95ffb2 100644
--- a/pkg/compiler/lib/src/ir/constants.dart
+++ b/pkg/compiler/lib/src/ir/constants.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
+import 'package:front_end/src/api_unstable/dart2js.dart' as ir;
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/src/printer.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
-import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
-import 'package:front_end/src/api_unstable/dart2js.dart' as ir;
 
 import '../kernel/dart2js_target.dart';
 
@@ -18,7 +18,7 @@
 
   bool requiresConstant;
 
-  Dart2jsConstantEvaluator(
+  Dart2jsConstantEvaluator(ir.Component component,
       ir.TypeEnvironment typeEnvironment, ReportErrorFunction reportError,
       {Map<String, String> environment = const {},
       bool supportReevaluationForTesting = false,
@@ -26,7 +26,9 @@
       : _supportReevaluationForTesting = supportReevaluationForTesting,
         assert(evaluationMode != null),
         super(
+            const Dart2jsDartLibrarySupport(),
             const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
+            component,
             environment,
             typeEnvironment,
             ErrorReporter(reportError),
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 6a8fecd..ac9131a 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -37,6 +37,7 @@
     bool allowVariableMinification = true,
     List<CodeOutputListener> listeners = const []}) {
   JavaScriptPrintingOptions options = JavaScriptPrintingOptions(
+      utf8: compilerOptions.features.writeUtf8.isEnabled,
       shouldCompressOutput: compilerOptions.enableMinification,
       minifyLocalVariables: allowVariableMinification);
   CodeBuffer outBuffer = CodeBuffer(listeners);
diff --git a/pkg/compiler/lib/src/js/placeholder_safety.dart b/pkg/compiler/lib/src/js/placeholder_safety.dart
index 9f14b58..29fea71 100644
--- a/pkg/compiler/lib/src/js/placeholder_safety.dart
+++ b/pkg/compiler/lib/src/js/placeholder_safety.dart
@@ -192,6 +192,23 @@
   }
 
   @override
+  int visitVariableInitialization(js.VariableInitialization node) {
+    js.Expression left = node.declaration;
+    js.Expression right = node.value;
+
+    visit(left);
+    if (left is js.InterpolatedNode) {
+      // A bare interpolated expression should not be the LHS of an initialized
+      // variable declaration.
+      safe = false;
+    }
+    if (right != null) {
+      return visit(right);
+    }
+    return UNKNOWN_VALUE;
+  }
+
+  @override
   int visitCall(js.Call node) {
     // TODO(sra): Recognize JavaScript built-ins like
     // 'Object.prototype.hasOwnProperty.call'.
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 803221c..0008046 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -2493,7 +2493,7 @@
   @override
   bool visitAssignment(js.Assignment node) {
     bool leftHandSide = visit(node.leftHandSide);
-    bool value = (node.value == null) ? false : visit(node.value);
+    bool value = visit(node.value);
     return leftHandSide || value;
   }
 
@@ -2877,7 +2877,9 @@
 
   @override
   bool visitVariableInitialization(js.VariableInitialization node) {
-    return visitAssignment(node);
+    bool leftHandSide = visit(node.declaration);
+    bool value = (node.value == null) ? false : visit(node.value);
+    return leftHandSide || value;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js/size_estimator.dart b/pkg/compiler/lib/src/js/size_estimator.dart
index 33a45ed..d081f4c0 100644
--- a/pkg/compiler/lib/src/js/size_estimator.dart
+++ b/pkg/compiler/lib/src/js/size_estimator.dart
@@ -556,7 +556,13 @@
 
   @override
   visitVariableInitialization(VariableInitialization initialization) {
-    visitAssignment(initialization);
+    visitNestedExpression(initialization.declaration, CALL,
+        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
+    if (initialization.value != null) {
+      out('=');
+      visitNestedExpression(initialization.value, ASSIGNMENT,
+          newInForInit: inForInit, newAtStatementBegin: false);
+    }
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index ea27263..16c003c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -557,6 +557,9 @@
     js.Program program = js.Program([
       if (isFirst) buildGeneratedBy(),
       if (isFirst) buildDeferredInitializerGlobal(),
+      if (_options.experimentalTrackAllocations)
+        js.js.statement("var allocations = #deferredGlobal['allocations']",
+            {'deferredGlobal': deferredInitializersGlobal}),
       js.js.statement('$deferredInitializersGlobal.current = #', code)
     ]);
 
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index f354388..7aa5677 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -170,6 +170,7 @@
 /// http://matt.might.net/articles/closure-conversion/.
 
 class ClosureDataBuilder {
+  final DiagnosticReporter _reporter;
   final JsToElementMap _elementMap;
   final AnnotationsData _annotationsData;
 
@@ -185,7 +186,7 @@
 
   final Map<MemberEntity, MemberEntity> _enclosingMembers = {};
 
-  ClosureDataBuilder(this._elementMap, this._annotationsData);
+  ClosureDataBuilder(this._reporter, this._elementMap, this._annotationsData);
 
   void _updateScopeBasedOnRtiNeed(KernelScopeInfo scope, ClosureRtiNeed rtiNeed,
       MemberEntity outermostEntity) {
@@ -323,7 +324,7 @@
       Map<MemberEntity, ClosureScopeModel> closureModels,
       ClosureRtiNeed rtiNeed,
       List<FunctionEntity> callMethods) {
-    closureModels.forEach((MemberEntity member, ClosureScopeModel model) {
+    void processModel(MemberEntity member, ClosureScopeModel model) {
       Map<ir.VariableDeclaration, JRecordField> allBoxedVariables =
           _elementMap.makeRecordContainer(model.scopeInfo, member);
       _scopeMap[member] = JsScopeInfo.from(
@@ -381,6 +382,12 @@
         }
         callMethods.add(closureClassInfo.callMethod);
       }
+    }
+
+    closureModels.forEach((MemberEntity member, ClosureScopeModel model) {
+      _reporter.withCurrentElement(member, () {
+        processModel(member, model);
+      });
     });
     return ClosureDataImpl(
         _elementMap,
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 3bb766f..ae9a0a0 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -1164,14 +1164,15 @@
   }
 
   Dart2jsConstantEvaluator get constantEvaluator {
-    return _constantEvaluator ??= Dart2jsConstantEvaluator(typeEnvironment,
-        (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
+    return _constantEvaluator ??=
+        Dart2jsConstantEvaluator(programEnv.mainComponent, typeEnvironment,
+            (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
       reportLocatedMessage(reporter, message, context);
     },
-        environment: _environment.toMap(),
-        evaluationMode: options.useLegacySubtyping
-            ? ir.EvaluationMode.weak
-            : ir.EvaluationMode.strong);
+            environment: _environment.toMap(),
+            evaluationMode: options.useLegacySubtyping
+                ? ir.EvaluationMode.weak
+                : ir.EvaluationMode.strong);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index c6f42f1..bfd0363 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -168,8 +168,8 @@
         strategy.elementMap,
         closedWorld.liveMemberUsage,
         closedWorld.annotationsData);
-    ClosureDataBuilder closureDataBuilder =
-        ClosureDataBuilder(_elementMap, closedWorld.annotationsData);
+    ClosureDataBuilder closureDataBuilder = ClosureDataBuilder(
+        _compiler.reporter, _elementMap, closedWorld.annotationsData);
     JsClosedWorldBuilder closedWorldBuilder = JsClosedWorldBuilder(_elementMap,
         closureDataBuilder, _compiler.options, _compiler.abstractValueStrategy);
     JClosedWorld jClosedWorld = closedWorldBuilder.convertClosedWorld(
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 01f42be..156e7a4 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -221,6 +221,10 @@
   @override
   ConstantsBackend get constantsBackend =>
       const Dart2jsConstantsBackend(supportsUnevaluatedConstants: true);
+
+  @override
+  DartLibrarySupport get dartLibrarySupport =>
+      const Dart2jsDartLibrarySupport();
 }
 
 // TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
@@ -314,3 +318,8 @@
   @override
   NumberSemantics get numberSemantics => NumberSemantics.js;
 }
+
+class Dart2jsDartLibrarySupport extends CustomizedDartLibrarySupport {
+  const Dart2jsDartLibrarySupport()
+      : super(supported: const {'_dart2js_runtime_metrics'});
+}
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index f82c5ef..b4a93af 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -812,14 +812,15 @@
   }
 
   Dart2jsConstantEvaluator get constantEvaluator {
-    return _constantEvaluator ??= Dart2jsConstantEvaluator(typeEnvironment,
-        (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
+    return _constantEvaluator ??=
+        Dart2jsConstantEvaluator(env.mainComponent, typeEnvironment,
+            (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
       reportLocatedMessage(reporter, message, context);
     },
-        environment: _environment.toMap(),
-        evaluationMode: options.useLegacySubtyping
-            ? ir.EvaluationMode.weak
-            : ir.EvaluationMode.strong);
+            environment: _environment.toMap(),
+            evaluationMode: options.useLegacySubtyping
+                ? ir.EvaluationMode.weak
+                : ir.EvaluationMode.strong);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/native/js.dart b/pkg/compiler/lib/src/native/js.dart
index 9c21348..295dd0b 100644
--- a/pkg/compiler/lib/src/native/js.dart
+++ b/pkg/compiler/lib/src/native/js.dart
@@ -213,6 +213,14 @@
   }
 
   @override
+  NativeThrowBehavior visitVariableInitialization(
+      js.VariableInitialization node) {
+    final value = node.value;
+    if (value == null) return NativeThrowBehavior.NEVER;
+    return visit(value);
+  }
+
+  @override
   NativeThrowBehavior visitCall(js.Call node) {
     js.Expression target = node.target;
     if (target is js.PropertyAccess && _isFirstInterpolatedProperty(target)) {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index b0be710..c2efa63 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -76,6 +76,9 @@
   /// Whether to generate code compliant with Content Security Policy.
   FeatureOption useContentSecurityPolicy = FeatureOption('csp');
 
+  /// Whether to emit JavaScript encoded as UTF-8.
+  FeatureOption writeUtf8 = FeatureOption('utf8');
+
   /// [FeatureOption]s which are shipped and cannot be toggled.
   late final List<FeatureOption> shipped = [
     newHolders,
@@ -84,11 +87,13 @@
   /// [FeatureOption]s which default to enabled.
   late final List<FeatureOption> shipping = [
     legacyJavaScript,
-    useContentSecurityPolicy
+    useContentSecurityPolicy,
   ];
 
   /// [FeatureOption]s which default to disabled.
-  late final List<FeatureOption> canary = [];
+  late final List<FeatureOption> canary = [
+    writeUtf8,
+  ];
 
   /// Forces canary feature on. This must run after [Option].parse.
   void forceCanary() {
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index 559d972..b104a00 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -86,7 +86,7 @@
             classHierarchy,
             new StaticTypeCacheImpl()) {
     _constantEvaluator = new Dart2jsConstantEvaluator(
-        typeEnvironment, const ir.SimpleErrorReporter().report,
+        component, typeEnvironment, const ir.SimpleErrorReporter().report,
         evaluationMode: evaluationMode);
   }
 
diff --git a/pkg/compiler/test/custom_split/custom_split_test.dart b/pkg/compiler/test/custom_split/custom_split_test.dart
index f1e4fd4..7f4c4dc 100644
--- a/pkg/compiler/test/custom_split/custom_split_test.dart
+++ b/pkg/compiler/test/custom_split/custom_split_test.dart
@@ -24,6 +24,8 @@
   'diamond_and',
   'diamond_fuse',
   'diamond_or',
+  'fuse_with_and',
+  'fuse_with_or',
   'two_step',
   'two_branch',
 ];
diff --git a/pkg/compiler/test/custom_split/data/diamond/constraints.json b/pkg/compiler/test/custom_split/data/diamond/constraints.json
index 21b8afa..537cf0b 100644
--- a/pkg/compiler/test/custom_split/data/diamond/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond/constraints.json
@@ -20,22 +20,22 @@
     "import": "memory:sdk/tests/web/native/main.dart#step3"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "memory:sdk/tests/web/native/main.dart#step2a"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "memory:sdk/tests/web/native/main.dart#step2b"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step2a",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step2b",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   }
diff --git a/pkg/compiler/test/custom_split/data/diamond_and/constraints.json b/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
index 85344e7..bf91a12 100644
--- a/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_and/constraints.json
@@ -28,12 +28,12 @@
     ]
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "step2"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "step2",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   }
diff --git a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
index 145cbd1..a0fe64f 100644
--- a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
+++ b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.dart
@@ -19,8 +19,8 @@
   var builder = ProgramSplitBuilder();
   return [
     ...imports.map(builder.referenceNode),
-    builder.fuseNode('step2', {step2a, step2b}),
-    builder.orderNode(step1, 'step2'),
-    builder.orderNode('step2', step3),
+    builder.fuseNode({step2a, step2b}),
+    builder.orderNode(step1, step2a),
+    builder.orderNode(step2b, step3),
   ];
 }
diff --git a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
index dccfe20..835bebe 100644
--- a/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_fuse/constraints.json
@@ -21,20 +21,19 @@
   },
   {
     "type": "fuse",
-    "name": "step2",
     "nodes": [
       "memory:sdk/tests/web/native/main.dart#step2a",
       "memory:sdk/tests/web/native/main.dart#step2b"
     ]
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
-    "successor": "step2"
+    "successor": "memory:sdk/tests/web/native/main.dart#step2a"
   },
   {
-    "type": "order",
-    "predecessor": "step2",
+    "type": "relative_order",
+    "predecessor": "memory:sdk/tests/web/native/main.dart#step2b",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   }
 ]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/constraints.json b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
index c4091f4..f4ea01b 100644
--- a/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
+++ b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
@@ -28,12 +28,12 @@
     ]
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "step2"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "step2",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   }
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart
new file mode 100644
index 0000000..12a80ee
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+import 'package:compiler/src/deferred_load/program_split_constraints/nodes.dart';
+import '../../constraint_harness.dart';
+
+void main(List<String> args, SendPort sendPort) {
+  waitForImportsAndInvoke(sendPort, processDeferredImports);
+}
+
+List<Node> processDeferredImports(List<String> imports) {
+  var lib1 = 'memory:sdk/tests/web/native/lib1.dart#b1';
+  var lib2 = 'memory:sdk/tests/web/native/lib2.dart#b2';
+  var lib3 = 'memory:sdk/tests/web/native/lib3.dart#b3';
+  var lib4 = 'memory:sdk/tests/web/native/lib4.dart#b4';
+  var builder = ProgramSplitBuilder();
+  return [
+    ...imports.map(builder.referenceNode),
+    builder.andNode('lib1_and_lib2', {lib1, lib2}),
+    builder.fuseNode({'lib1_and_lib2', lib3}),
+    builder.orderNode(lib3, lib4),
+  ];
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json
new file mode 100644
index 0000000..d95cc50
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/constraints.json
@@ -0,0 +1,42 @@
+[
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib1.dart#b1",
+    "import": "memory:sdk/tests/web/native/lib1.dart#b1"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib2.dart#b2",
+    "import": "memory:sdk/tests/web/native/lib2.dart#b2"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib3.dart#b3",
+    "import": "memory:sdk/tests/web/native/lib3.dart#b3"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib4.dart#b4",
+    "import": "memory:sdk/tests/web/native/lib4.dart#b4"
+  },
+  {
+    "type": "and",
+    "name": "lib1_and_lib2",
+    "nodes": [
+      "memory:sdk/tests/web/native/lib1.dart#b1",
+      "memory:sdk/tests/web/native/lib2.dart#b2"
+    ]
+  },
+  {
+    "type": "fuse",
+    "nodes": [
+      "lib1_and_lib2",
+      "memory:sdk/tests/web/native/lib3.dart#b3"
+    ]
+  },
+  {
+    "type": "relative_order",
+    "predecessor": "memory:sdk/tests/web/native/lib3.dart#b3",
+    "successor": "memory:sdk/tests/web/native/lib4.dart#b4"
+  }
+]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart
new file mode 100644
index 0000000..33e2c05
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib1.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_100_0.dart' deferred as b1;
+
+/*member: entryLib1:member_unit=main{}*/
+entryLib1() async {
+  await b1.loadLibrary();
+  b1.g_100_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart
new file mode 100644
index 0000000..1ad0cd3
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib2.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_010_0.dart' deferred as b2;
+
+/*member: entryLib2:member_unit=main{}*/
+entryLib2() async {
+  await b2.loadLibrary();
+  b2.g_010_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart
new file mode 100644
index 0000000..1d2b9d5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib3.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_001_0.dart' deferred as b3;
+
+/*member: entryLib3:member_unit=main{}*/
+entryLib3() async {
+  await b3.loadLibrary();
+  b3.g_001_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart
new file mode 100644
index 0000000..1eedd87
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib4.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_000_1.dart' deferred as b4;
+
+/*member: entryLib4:member_unit=main{}*/
+entryLib4() async {
+  await b4.loadLibrary();
+  b4.g_000_1();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart
new file mode 100644
index 0000000..d55f632
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/libImport.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+/*member: v:member_unit=1{b1, b2, b3, b4}*/
+void v(Set<String> u, String name, int bit) {
+  Expect.isTrue(u.add(name));
+  Expect.equals(name[bit], '1');
+}
+
+@pragma('dart2js:noInline')
+/*member: f_100_0:member_unit=1{b1, b2, b3, b4}*/
+f_100_0(Set<String> u, int b) => v(u, '1000', b);
+@pragma('dart2js:noInline')
+/*member: f_100_1:member_unit=1{b1, b2, b3, b4}*/
+f_100_1(Set<String> u, int b) => v(u, '1001', b);
+@pragma('dart2js:noInline')
+/*member: f_101_0:member_unit=1{b1, b2, b3, b4}*/
+f_101_0(Set<String> u, int b) => v(u, '1010', b);
+@pragma('dart2js:noInline')
+/*member: f_101_1:member_unit=1{b1, b2, b3, b4}*/
+f_101_1(Set<String> u, int b) => v(u, '1011', b);
+@pragma('dart2js:noInline')
+/*member: f_110_0:member_unit=1{b1, b2, b3, b4}*/
+f_110_0(Set<String> u, int b) => v(u, '1100', b);
+@pragma('dart2js:noInline')
+/*member: f_110_1:member_unit=1{b1, b2, b3, b4}*/
+f_110_1(Set<String> u, int b) => v(u, '1101', b);
+@pragma('dart2js:noInline')
+/*member: f_111_0:member_unit=1{b1, b2, b3, b4}*/
+f_111_0(Set<String> u, int b) => v(u, '1110', b);
+@pragma('dart2js:noInline')
+/*member: f_111_1:member_unit=1{b1, b2, b3, b4}*/
+f_111_1(Set<String> u, int b) => v(u, '1111', b);
+@pragma('dart2js:noInline')
+/*member: f_010_0:member_unit=1{b1, b2, b3, b4}*/
+f_010_0(Set<String> u, int b) => v(u, '0100', b);
+@pragma('dart2js:noInline')
+/*member: f_010_1:member_unit=1{b1, b2, b3, b4}*/
+f_010_1(Set<String> u, int b) => v(u, '0101', b);
+@pragma('dart2js:noInline')
+/*member: f_011_0:member_unit=1{b1, b2, b3, b4}*/
+f_011_0(Set<String> u, int b) => v(u, '0110', b);
+@pragma('dart2js:noInline')
+/*member: f_011_1:member_unit=1{b1, b2, b3, b4}*/
+f_011_1(Set<String> u, int b) => v(u, '0111', b);
+@pragma('dart2js:noInline')
+/*member: f_001_0:member_unit=1{b1, b2, b3, b4}*/
+f_001_0(Set<String> u, int b) => v(u, '0010', b);
+@pragma('dart2js:noInline')
+/*member: f_001_1:member_unit=1{b1, b2, b3, b4}*/
+f_001_1(Set<String> u, int b) => v(u, '0011', b);
+@pragma('dart2js:noInline')
+/*member: f_000_1:member_unit=2{b4}*/
+f_000_1(Set<String> u, int b) => v(u, '0001', b);
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart
new file mode 100644
index 0000000..091a013
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_000_1.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_000_1:member_unit=2{b4}*/
+g_000_1() {
+  Set<String> uniques = {};
+
+  // f_***_1;
+  f_000_1(uniques, 3);
+  f_001_1(uniques, 3);
+  f_010_1(uniques, 3);
+  f_011_1(uniques, 3);
+  f_100_1(uniques, 3);
+  f_101_1(uniques, 3);
+  f_110_1(uniques, 3);
+  f_111_1(uniques, 3);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart
new file mode 100644
index 0000000..19906dd
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_001_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_001_0:member_unit=1{b1, b2, b3, b4}*/
+g_001_0() {
+  Set<String> uniques = {};
+
+  // f_**1_*;
+  f_001_0(uniques, 2);
+  f_001_1(uniques, 2);
+  f_011_0(uniques, 2);
+  f_011_1(uniques, 2);
+  f_101_0(uniques, 2);
+  f_101_1(uniques, 2);
+  f_111_0(uniques, 2);
+  f_111_1(uniques, 2);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart
new file mode 100644
index 0000000..22b05ac
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_010_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_010_0:member_unit=1{b1, b2, b3, b4}*/
+g_010_0() {
+  Set<String> uniques = {};
+
+  // f_*1*_*;
+  f_010_0(uniques, 1);
+  f_010_1(uniques, 1);
+  f_011_0(uniques, 1);
+  f_011_1(uniques, 1);
+  f_110_0(uniques, 1);
+  f_110_1(uniques, 1);
+  f_111_0(uniques, 1);
+  f_111_1(uniques, 1);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart
new file mode 100644
index 0000000..d39141b
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/lib_100_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_100_0:member_unit=1{b1, b2, b3, b4}*/
+g_100_0() {
+  Set<String> uniques = {};
+
+  // f_1**_*;
+  f_100_0(uniques, 0);
+  f_100_1(uniques, 0);
+  f_101_0(uniques, 0);
+  f_101_1(uniques, 0);
+  f_110_0(uniques, 0);
+  f_110_1(uniques, 0);
+  f_111_0(uniques, 0);
+  f_111_1(uniques, 0);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart b/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart
new file mode 100644
index 0000000..f07ccf9
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_and/main.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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: 
+ a_pre_fragments=[
+  p1: {units: [2{b4}], usedBy: [], needs: []},
+  p2: {units: [1{b1, b2, b3, b4}], usedBy: [], needs: []}],
+ b_finalized_fragments=[
+  f1: [2{b4}],
+  f2: [1{b1, b2, b3, b4}]],
+ c_steps=[
+  b1=(f2),
+  b2=(f2),
+  b3=(f2),
+  b4=(f2, f1)]
+*/
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib1.dart';
+import 'lib2.dart';
+import 'lib3.dart';
+import 'lib4.dart';
+
+/*member: main:member_unit=main{}*/
+main() {
+  entryLib1();
+  entryLib2();
+  entryLib3();
+  entryLib4();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart
new file mode 100644
index 0000000..370ca10
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+import 'package:compiler/src/deferred_load/program_split_constraints/nodes.dart';
+import '../../constraint_harness.dart';
+
+void main(List<String> args, SendPort sendPort) {
+  waitForImportsAndInvoke(sendPort, processDeferredImports);
+}
+
+List<Node> processDeferredImports(List<String> imports) {
+  var lib1 = 'memory:sdk/tests/web/native/lib1.dart#b1';
+  var lib2 = 'memory:sdk/tests/web/native/lib2.dart#b2';
+  var lib3 = 'memory:sdk/tests/web/native/lib3.dart#b3';
+  var lib4 = 'memory:sdk/tests/web/native/lib4.dart#b4';
+  var builder = ProgramSplitBuilder();
+  return [
+    ...imports.map(builder.referenceNode),
+    builder.orNode('lib1_or_lib2', {lib1, lib2}),
+    builder.fuseNode({'lib1_or_lib2', lib3}),
+    builder.orderNode(lib3, lib4),
+  ];
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json
new file mode 100644
index 0000000..6d44688
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/constraints.json
@@ -0,0 +1,42 @@
+[
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib1.dart#b1",
+    "import": "memory:sdk/tests/web/native/lib1.dart#b1"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib2.dart#b2",
+    "import": "memory:sdk/tests/web/native/lib2.dart#b2"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib3.dart#b3",
+    "import": "memory:sdk/tests/web/native/lib3.dart#b3"
+  },
+  {
+    "type": "reference",
+    "name": "memory:sdk/tests/web/native/lib4.dart#b4",
+    "import": "memory:sdk/tests/web/native/lib4.dart#b4"
+  },
+  {
+    "type": "or",
+    "name": "lib1_or_lib2",
+    "nodes": [
+      "memory:sdk/tests/web/native/lib1.dart#b1",
+      "memory:sdk/tests/web/native/lib2.dart#b2"
+    ]
+  },
+  {
+    "type": "fuse",
+    "nodes": [
+      "lib1_or_lib2",
+      "memory:sdk/tests/web/native/lib3.dart#b3"
+    ]
+  },
+  {
+    "type": "relative_order",
+    "predecessor": "memory:sdk/tests/web/native/lib3.dart#b3",
+    "successor": "memory:sdk/tests/web/native/lib4.dart#b4"
+  }
+]
\ No newline at end of file
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart
new file mode 100644
index 0000000..33e2c05
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib1.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_100_0.dart' deferred as b1;
+
+/*member: entryLib1:member_unit=main{}*/
+entryLib1() async {
+  await b1.loadLibrary();
+  b1.g_100_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart
new file mode 100644
index 0000000..1ad0cd3
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib2.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_010_0.dart' deferred as b2;
+
+/*member: entryLib2:member_unit=main{}*/
+entryLib2() async {
+  await b2.loadLibrary();
+  b2.g_010_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart
new file mode 100644
index 0000000..1d2b9d5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib3.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_001_0.dart' deferred as b3;
+
+/*member: entryLib3:member_unit=main{}*/
+entryLib3() async {
+  await b3.loadLibrary();
+  b3.g_001_0();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart
new file mode 100644
index 0000000..1eedd87
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib4.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib_000_1.dart' deferred as b4;
+
+/*member: entryLib4:member_unit=main{}*/
+entryLib4() async {
+  await b4.loadLibrary();
+  b4.g_000_1();
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart
new file mode 100644
index 0000000..dd4364a
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/libImport.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+/*member: v:member_unit=2{b1, b2, b3, b4}*/
+void v(Set<String> u, String name, int bit) {
+  Expect.isTrue(u.add(name));
+  Expect.equals(name[bit], '1');
+}
+
+@pragma('dart2js:noInline')
+/*member: f_100_0:member_unit=1{b1}*/
+f_100_0(Set<String> u, int b) => v(u, '1000', b);
+@pragma('dart2js:noInline')
+/*member: f_100_1:member_unit=3{b1, b4}*/
+f_100_1(Set<String> u, int b) => v(u, '1001', b);
+@pragma('dart2js:noInline')
+/*member: f_101_0:member_unit=2{b1, b2, b3, b4}*/
+f_101_0(Set<String> u, int b) => v(u, '1010', b);
+@pragma('dart2js:noInline')
+/*member: f_101_1:member_unit=2{b1, b2, b3, b4}*/
+f_101_1(Set<String> u, int b) => v(u, '1011', b);
+@pragma('dart2js:noInline')
+/*member: f_110_0:member_unit=2{b1, b2, b3, b4}*/
+f_110_0(Set<String> u, int b) => v(u, '1100', b);
+@pragma('dart2js:noInline')
+/*member: f_110_1:member_unit=2{b1, b2, b3, b4}*/
+f_110_1(Set<String> u, int b) => v(u, '1101', b);
+@pragma('dart2js:noInline')
+/*member: f_111_0:member_unit=2{b1, b2, b3, b4}*/
+f_111_0(Set<String> u, int b) => v(u, '1110', b);
+@pragma('dart2js:noInline')
+/*member: f_111_1:member_unit=2{b1, b2, b3, b4}*/
+f_111_1(Set<String> u, int b) => v(u, '1111', b);
+@pragma('dart2js:noInline')
+/*member: f_010_0:member_unit=4{b2}*/
+f_010_0(Set<String> u, int b) => v(u, '0100', b);
+@pragma('dart2js:noInline')
+/*member: f_010_1:member_unit=5{b2, b4}*/
+f_010_1(Set<String> u, int b) => v(u, '0101', b);
+@pragma('dart2js:noInline')
+/*member: f_011_0:member_unit=2{b1, b2, b3, b4}*/
+f_011_0(Set<String> u, int b) => v(u, '0110', b);
+@pragma('dart2js:noInline')
+/*member: f_011_1:member_unit=2{b1, b2, b3, b4}*/
+f_011_1(Set<String> u, int b) => v(u, '0111', b);
+@pragma('dart2js:noInline')
+/*member: f_001_0:member_unit=2{b1, b2, b3, b4}*/
+f_001_0(Set<String> u, int b) => v(u, '0010', b);
+@pragma('dart2js:noInline')
+/*member: f_001_1:member_unit=2{b1, b2, b3, b4}*/
+f_001_1(Set<String> u, int b) => v(u, '0011', b);
+@pragma('dart2js:noInline')
+/*member: f_000_1:member_unit=6{b4}*/
+f_000_1(Set<String> u, int b) => v(u, '0001', b);
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart
new file mode 100644
index 0000000..5407d70
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_000_1.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_000_1:member_unit=6{b4}*/
+g_000_1() {
+  Set<String> uniques = {};
+
+  // f_***_1;
+  f_000_1(uniques, 3);
+  f_001_1(uniques, 3);
+  f_010_1(uniques, 3);
+  f_011_1(uniques, 3);
+  f_100_1(uniques, 3);
+  f_101_1(uniques, 3);
+  f_110_1(uniques, 3);
+  f_111_1(uniques, 3);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart
new file mode 100644
index 0000000..1614e60
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_001_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_001_0:member_unit=2{b1, b2, b3, b4}*/
+g_001_0() {
+  Set<String> uniques = {};
+
+  // f_**1_*;
+  f_001_0(uniques, 2);
+  f_001_1(uniques, 2);
+  f_011_0(uniques, 2);
+  f_011_1(uniques, 2);
+  f_101_0(uniques, 2);
+  f_101_1(uniques, 2);
+  f_111_0(uniques, 2);
+  f_111_1(uniques, 2);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart
new file mode 100644
index 0000000..4cf27c5
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_010_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_010_0:member_unit=4{b2}*/
+g_010_0() {
+  Set<String> uniques = {};
+
+  // f_*1*_*;
+  f_010_0(uniques, 1);
+  f_010_1(uniques, 1);
+  f_011_0(uniques, 1);
+  f_011_1(uniques, 1);
+  f_110_0(uniques, 1);
+  f_110_1(uniques, 1);
+  f_111_0(uniques, 1);
+  f_111_1(uniques, 1);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart
new file mode 100644
index 0000000..0fe7274
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/lib_100_0.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import "package:expect/expect.dart";
+
+import 'libImport.dart';
+
+@pragma('dart2js:noInline')
+/*member: g_100_0:member_unit=1{b1}*/
+g_100_0() {
+  Set<String> uniques = {};
+
+  // f_1**_*;
+  f_100_0(uniques, 0);
+  f_100_1(uniques, 0);
+  f_101_0(uniques, 0);
+  f_101_1(uniques, 0);
+  f_110_0(uniques, 0);
+  f_110_1(uniques, 0);
+  f_111_0(uniques, 0);
+  f_111_1(uniques, 0);
+  Expect.equals(8, uniques.length);
+}
diff --git a/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart b/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart
new file mode 100644
index 0000000..a2531cb
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/fuse_with_or/main.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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: 
+ a_pre_fragments=[
+  p1: {units: [6{b4}], usedBy: [], needs: []},
+  p2: {units: [4{b2}], usedBy: [], needs: []},
+  p3: {units: [1{b1}], usedBy: [], needs: []},
+  p4: {units: [5{b2, b4}], usedBy: [], needs: []},
+  p5: {units: [3{b1, b4}], usedBy: [], needs: []},
+  p6: {units: [2{b1, b2, b3, b4}], usedBy: [], needs: []}],
+ b_finalized_fragments=[
+  f1: [6{b4}],
+  f2: [4{b2}],
+  f3: [1{b1}],
+  f4: [5{b2, b4}],
+  f5: [3{b1, b4}],
+  f6: [2{b1, b2, b3, b4}]],
+ c_steps=[
+  b1=(f6, f5, f3),
+  b2=(f6, f4, f2),
+  b3=(f6),
+  b4=(f6, f5, f4, f1)]
+*/
+
+// This file was autogenerated by the pkg/compiler/tool/graph_isomorphizer.dart.
+import 'lib1.dart';
+import 'lib2.dart';
+import 'lib3.dart';
+import 'lib4.dart';
+
+/*member: main:member_unit=main{}*/
+main() {
+  entryLib1();
+  entryLib2();
+  entryLib3();
+  entryLib4();
+}
diff --git a/pkg/compiler/test/custom_split/data/two_branch/constraints.json b/pkg/compiler/test/custom_split/data/two_branch/constraints.json
index 1a29d7b..9ab73ee 100644
--- a/pkg/compiler/test/custom_split/data/two_branch/constraints.json
+++ b/pkg/compiler/test/custom_split/data/two_branch/constraints.json
@@ -15,12 +15,12 @@
     "import": "memory:sdk/tests/web/native/main.dart#step2b"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "memory:sdk/tests/web/native/main.dart#step2a"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "memory:sdk/tests/web/native/main.dart#step2b"
   }
diff --git a/pkg/compiler/test/custom_split/data/two_step/constraints.json b/pkg/compiler/test/custom_split/data/two_step/constraints.json
index 77a02de..a0e82d6 100644
--- a/pkg/compiler/test/custom_split/data/two_step/constraints.json
+++ b/pkg/compiler/test/custom_split/data/two_step/constraints.json
@@ -15,12 +15,12 @@
     "import": "memory:sdk/tests/web/native/main.dart#step3"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step1",
     "successor": "memory:sdk/tests/web/native/main.dart#step2"
   },
   {
-    "type": "order",
+    "type": "relative_order",
     "predecessor": "memory:sdk/tests/web/native/main.dart#step2",
     "successor": "memory:sdk/tests/web/native/main.dart#step3"
   }
diff --git a/pkg/compiler/test/end_to_end/dill_loader_test.dart b/pkg/compiler/test/end_to_end/dill_loader_test.dart
index 7bf0330..46626f4 100644
--- a/pkg/compiler/test/end_to_end/dill_loader_test.dart
+++ b/pkg/compiler/test/end_to_end/dill_loader_test.dart
@@ -43,7 +43,6 @@
         memorySourceFiles: {'main.dill': kernelBinary},
         diagnosticHandler: diagnostics,
         outputProvider: output);
-    await compiler.setupSdk();
     KernelResult result = await compiler.kernelLoader.load();
     compiler.frontendStrategy.registerLoadedLibraries(result);
 
diff --git a/pkg/compiler/test/end_to_end/library_env_test.dart b/pkg/compiler/test/end_to_end/library_env_test.dart
deleted file mode 100644
index f194f37..0000000
--- a/pkg/compiler/test/end_to_end/library_env_test.dart
+++ /dev/null
@@ -1,146 +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.
-
-// @dart = 2.7
-
-/// Check that 'dart:' libraries have their corresponding dart.library.X
-/// environment variable set.
-
-import 'dart:async';
-
-import '../helpers/memory_compiler.dart';
-import '../helpers/memory_source_file_helper.dart';
-
-import "package:async_helper/async_helper.dart";
-
-import 'package:expect/expect.dart' show Expect;
-
-import 'package:compiler/src/null_compiler_output.dart' show NullCompilerOutput;
-
-import 'package:compiler/src/options.dart' show CompilerOptions;
-
-import 'package:compiler/src/commandline_options.dart';
-
-import 'package:compiler/src/io/source_file.dart' show Binary;
-
-import 'package:compiler/compiler_new.dart'
-    show CompilerInput, CompilerDiagnostics, Input, InputKind;
-
-const String librariesJson = r'''
-{
- "dart2js": {
-   "libraries": {
-    "mock.client": {"uri": "mock1.dart"},
-    "mock.shared": {"uri": "mock3.dart"},
-    "collection": {"uri": "collection/collection.dart"},
-    "html": {"uri": "html/dart2js/html_dart2js.dart"}
-   }
- },
- "dart2js_server": {
-   "libraries": {
-    "mock.server": {"uri": "mock2.dart"},
-    "mock.shared": {"uri": "mock3.dart"},
-    "collection": {"uri": "collection/collection.dart"},
-    "io": {"uri": "io/io.dart"}
-   }
- }
-}
-''';
-
-class DummyCompilerInput implements CompilerInput {
-  const DummyCompilerInput();
-
-  @override
-  Future<Input> readFromUri(Uri uri,
-      {InputKind inputKind: InputKind.UTF8}) async {
-    if (uri.path.endsWith("libraries.json")) {
-      return new Binary(uri, librariesJson.codeUnits);
-    } else {
-      throw "should not be needed $uri";
-    }
-  }
-}
-
-class DummyCompilerDiagnostics implements CompilerDiagnostics {
-  const DummyCompilerDiagnostics();
-
-  @override
-  report(code, uri, begin, end, text, kind) {
-    throw "should not be needed";
-  }
-}
-
-class CustomCompiler extends CompilerImpl {
-  CustomCompiler(List<String> options, Map<String, String> environment)
-      : super(
-            const DummyCompilerInput(),
-            const NullCompilerOutput(),
-            const DummyCompilerDiagnostics(),
-            CompilerOptions.parse(
-                ['--platform-binaries=$sdkPlatformBinariesPath']
-                  ..addAll(options),
-                librariesSpecificationUri: sdkLibrariesSpecificationUri)
-              ..environment = environment);
-}
-
-runTest() async {
-  {
-    final compiler = new CustomCompiler([], {});
-
-    await compiler.setupSdk();
-    final lookup = compiler.environment.valueOf;
-
-    // Core libraries are always present.
-    Expect.equals("true", lookup("dart.library.collection"));
-    // Non-existing entries in the environment return 'null'.
-    Expect.isNull(lookup("not in env"));
-    // Check for client libraries (default if there are no flags to the compiler).
-    Expect.equals("true", lookup("dart.library.mock.client"));
-    Expect.equals("true", lookup("dart.library.html"));
-    // Check for shared libraries..
-    Expect.equals("true", lookup("dart.library.mock.shared"));
-    // Check server libraries are not present.
-    Expect.equals(null, lookup("dart.library.mock.server"));
-    Expect.equals(null, lookup("dart.library.io"));
-  }
-  {
-    final compiler = new CustomCompiler([Flags.serverMode], {});
-
-    await compiler.setupSdk();
-    final lookup = compiler.environment.valueOf;
-
-    // Core libraries are always present.
-    Expect.equals("true", lookup("dart.library.collection"));
-    // Non-existing entries in the environment return 'null'.
-    Expect.isNull(lookup("not in env"));
-    // Check client libraries are not present.
-    Expect.equals(null, lookup("dart.library.mock.client"));
-    Expect.equals(null, lookup("dart.library.html"));
-    // Check for shared libraries..
-    Expect.equals("true", lookup("dart.library.mock.shared"));
-    // Check for server libraries.
-    Expect.equals("true", lookup("dart.library.mock.server"));
-    Expect.equals("true", lookup("dart.library.io"));
-  }
-  {
-    // Check that user-defined env-variables win.
-    final compiler = new CustomCompiler([], {
-      'dart.library.collection': "false",
-      'dart.library.mock.client': "foo"
-    });
-
-    await compiler.setupSdk();
-    final lookup = compiler.environment.valueOf;
-
-    Expect.equals("false", lookup("dart.library.collection"));
-    Expect.equals("foo", lookup("dart.library.mock.client"));
-  }
-}
-
-main() {
-  asyncStart();
-  runTest().then((_) {
-    asyncEnd();
-  });
-}
diff --git a/pkg/compiler/test/end_to_end/modular_loader_test.dart b/pkg/compiler/test/end_to_end/modular_loader_test.dart
index 35c1066..b5819f0 100644
--- a/pkg/compiler/test/end_to_end/modular_loader_test.dart
+++ b/pkg/compiler/test/end_to_end/modular_loader_test.dart
@@ -44,7 +44,6 @@
         memorySourceFiles: {'a.dill': aDill, 'b.dill': bDill, 'c.dill': cDill},
         diagnosticHandler: diagnostics,
         outputProvider: output);
-    await compiler.setupSdk();
     KernelResult result = await compiler.kernelLoader.load();
     compiler.frontendStrategy.registerLoadedLibraries(result);
 
diff --git a/pkg/compiler/test/inference/data/call_site.dart b/pkg/compiler/test/inference/data/call_site.dart
index 6cc8406..16f18e0 100644
--- a/pkg/compiler/test/inference/data/call_site.dart
+++ b/pkg/compiler/test/inference/data/call_site.dart
@@ -112,7 +112,7 @@
 /*member: A8.:[exact=A8]*/
 class A8 {
   /*member: A8.x8:[empty]*/
-  x8(/*Union([exact=JSString], [subclass=JsLinkedHashMap])*/ p) =>
+  x8(/*Union([exact=JSString], [exact=JsLinkedHashMap])*/ p) =>
       /*invoke: [exact=A8]*/ x8("x");
 }
 
@@ -126,7 +126,7 @@
   /*member: A9.x9:[empty]*/ x9(
           /*[exact=JSUInt31]*/ p1,
           /*Union([exact=JSString], [exact=JSUInt31])*/ p2,
-          /*Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ p3) =>
+          /*Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/ p3) =>
       /*invoke: [exact=A9]*/ x9(p1, "x", {});
 }
 
diff --git a/pkg/compiler/test/inference/data/closure2.dart b/pkg/compiler/test/inference/data/closure2.dart
index 793c24c..a3c5e37 100644
--- a/pkg/compiler/test/inference/data/closure2.dart
+++ b/pkg/compiler/test/inference/data/closure2.dart
@@ -14,7 +14,7 @@
   return a;
 }
 
-/*member: returnDyn1:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn1:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
 returnDyn1() {
   dynamic a = 42;
   // ignore: unused_local_variable
@@ -34,7 +34,7 @@
   return a;
 }
 
-/*member: returnDyn2:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn2:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
 returnDyn2() {
   dynamic a = 42;
   // ignore: unused_local_variable
@@ -60,10 +60,10 @@
   return a;
 }
 
-/*member: returnDyn3:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn3:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
 returnDyn3() {
   dynamic a = 42;
-  if (a /*invoke: Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ == 53) {
+  if (a /*invoke: Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/ == 53) {
     // ignore: unused_local_variable
     var f = /*[null]*/ () {
       a = {};
diff --git a/pkg/compiler/test/inference/data/closure_tracer.dart b/pkg/compiler/test/inference/data/closure_tracer.dart
index e689520..6353470 100644
--- a/pkg/compiler/test/inference/data/closure_tracer.dart
+++ b/pkg/compiler/test/inference/data/closure_tracer.dart
@@ -59,11 +59,11 @@
   dynamic b = <dynamic, dynamic>{'foo': 1};
 
   b
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
       ['bar'] = a;
 
   b
-          /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+          /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
           ['bar']
 
       /*Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)*/
diff --git a/pkg/compiler/test/inference/data/dictionary_types.dart b/pkg/compiler/test/inference/data/dictionary_types.dart
index 61c0072..e8a191a 100644
--- a/pkg/compiler/test/inference/data/dictionary_types.dart
+++ b/pkg/compiler/test/inference/data/dictionary_types.dart
@@ -13,7 +13,7 @@
   test5();
 }
 
-/*member: dictionaryA1:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: dictionaryA1:Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
 dynamic dictionaryA1 = {
   'string': "aString",
   'int': 42,
@@ -21,7 +21,7 @@
   'list': []
 };
 
-/*member: dictionaryB1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+/*member: dictionaryB1:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
 dynamic dictionaryB1 = {
   'string': "aString",
   'int': 42,
@@ -29,7 +29,7 @@
   'list': []
 };
 
-/*member: otherDict1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+/*member: otherDict1:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
 dynamic otherDict1 = {'stringTwo': "anotherString", 'intTwo': 84};
 
 /*member: int1:[exact=JSUInt31]*/
@@ -47,26 +47,26 @@
 /*member: test1:[null]*/
 test1() {
   dictionaryA1
-      . /*invoke: Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      . /*invoke: Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
       addAll(otherDict1);
   dictionaryB1
-      . /*invoke: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      . /*invoke: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
       addAll({'stringTwo': "anotherString", 'intTwo': 84});
   int1 = dictionaryB1
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
       ['int'];
   anotherInt1 = otherDict1
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
       ['intTwo'];
   dynamic1 =
-      dictionaryA1 /*Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
+      dictionaryA1 /*Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
           'int'];
   nullOrInt1 = dictionaryB1
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
       ['intTwo'];
 }
 
-/*member: dictionaryA2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionaryA2:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
 dynamic dictionaryA2 = {
   'string': "aString",
   'int': 42,
@@ -74,7 +74,7 @@
   'list': []
 };
 
-/*member: dictionaryB2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionaryB2:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
 dynamic dictionaryB2 = {'string': "aString", 'intTwo': 42, 'list': []};
 
 /*member: nullOrInt2:[null|exact=JSUInt31]*/
@@ -89,22 +89,22 @@
 /*member: test2:[null]*/
 test2() {
   var union = dictionaryA2
-          /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+          /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
           ['foo']
       ? dictionaryA2
       : dictionaryB2;
   nullOrInt2 = union
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
       ['intTwo'];
   aString2 = union
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
       ['string'];
   doubleOrNull2 = union
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
       ['double'];
 }
 
-/*member: dictionary3:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionary3:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
 dynamic dictionary3 = {
   'string': "aString",
   'int': 42,
@@ -125,18 +125,18 @@
 
 /*member: intOrNull3:[null|exact=JSUInt31]*/
 dynamic intOrNull3 = dictionary3
-    /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+    /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
     [keyI3];
 
 /*member: justNull3:[null]*/
 dynamic justNull3 = dictionary3
-    /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+    /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
     [keyN3];
 
 /*member: test3:[null]*/
 test3() {
   knownDouble3 = dictionary3
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
       [keyD3];
   // ignore: unused_local_variable
   var x = [intOrNull3, justNull3];
@@ -147,8 +147,8 @@
   A4();
 /*member: A4.foo4:[exact=JSUInt31]*/
   foo4(
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
-    return value /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+    return value /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
         'anInt'];
   }
 }
@@ -159,7 +159,7 @@
 
 /*member: B4.foo4:[exact=JSUInt31]*/
   foo4(
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
     return 0;
   }
 }
@@ -180,7 +180,7 @@
       2);
 }
 
-/*member: dict5:Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: dict5:Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
 dynamic dict5 = makeMap5([1, 2]);
 
 /*member: notInt5:[null|subclass=Object]*/
@@ -189,7 +189,7 @@
 /*member: alsoNotInt5:[null|subclass=Object]*/
 dynamic alsoNotInt5 = 0;
 
-/*member: makeMap5:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: makeMap5:Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
 makeMap5(
     /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/ values) {
   return {
@@ -205,14 +205,14 @@
 /*member: test5:[null]*/
 test5() {
   dict5
-      /*update: Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      /*update: Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
       ['goo'] = 42;
   var closure =
-      /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      /*Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
       () => dict5;
   notInt5 = closure()['boo'];
   alsoNotInt5 = dict5
-      /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+      /*Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
       ['goo'];
   print("$notInt5 and $alsoNotInt5.");
 }
diff --git a/pkg/compiler/test/inference/data/index.dart b/pkg/compiler/test/inference/data/index.dart
index 4a00271..c05e292 100644
--- a/pkg/compiler/test/inference/data/index.dart
+++ b/pkg/compiler/test/inference/data/index.dart
@@ -60,7 +60,7 @@
 mapLookupSingle() {
   var map = {0: 1};
   return map
-      /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [0];
 }
 
@@ -72,7 +72,7 @@
 mapLookupMultiple() {
   var map = {0: 1, 2: 3, 4: 5};
   return map
-      /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [2];
 }
 
@@ -84,7 +84,7 @@
 mapLookupMissing() {
   var map = {0: 1};
   return map
-      /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [2];
 }
 
@@ -96,7 +96,7 @@
 mapLookupMixedKeys() {
   var map = {0: 1, '': 2};
   return map
-      /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
+      /*Map([exact=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
       [''];
 }
 
@@ -108,7 +108,7 @@
 mapLookupMixedValues() {
   var map = {0: 1, 2: ''};
   return map
-      /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
+      /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
       [2];
 }
 
@@ -120,7 +120,7 @@
 dictionaryLookupSingle() {
   var map = {'foo': 'bar'};
   return map
-      /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
       ['foo'];
 }
 
@@ -132,7 +132,7 @@
 dictionaryLookupMultiple() {
   var map = {'foo': 'bar', 'baz': 'boz'};
   return map
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
       ['baz'];
 }
 
@@ -144,7 +144,7 @@
 dictionaryLookupMissing() {
   var map = {'foo': 'bar', 'baz': 'boz'};
   return map
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
       ['unknown'];
 }
 
@@ -156,7 +156,7 @@
 intDictionaryLookupSingle() {
   var map = {'foo': 0};
   return map
-      /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [exact=JSUInt31]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [exact=JSUInt31]})*/
       ['foo'];
 }
 
diff --git a/pkg/compiler/test/inference/data/index_call.dart b/pkg/compiler/test/inference/data/index_call.dart
index 4454632..d563df2 100644
--- a/pkg/compiler/test/inference/data/index_call.dart
+++ b/pkg/compiler/test/inference/data/index_call.dart
@@ -63,9 +63,9 @@
   var a = {
     'a': {'b': 0}
   };
-  return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]}), map: {a: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})})*/
+  return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]}), map: {a: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})})*/
               ['a']
-          /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})*/
+          /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})*/
           ['b']
       . /*invoke: [exact=JSUInt31]*/
       abs();
@@ -77,9 +77,9 @@
   var a = {
     'a': {'b': closure}
   };
-  return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]}), map: {a: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})})*/
+  return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]}), map: {a: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})})*/
           ['a']
-      /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})*/
       ['b'](d: 0);
 }
 
@@ -89,7 +89,7 @@
   var a = {
     'a': [closure]
   };
-  return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1), map: {a: Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+  return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1), map: {a: Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
           ['a']
       /*Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)*/
       [0](d: 0);
diff --git a/pkg/compiler/test/inference/data/index_set.dart b/pkg/compiler/test/inference/data/index_set.dart
index 883962c..c383f3f 100644
--- a/pkg/compiler/test/inference/data/index_set.dart
+++ b/pkg/compiler/test/inference/data/index_set.dart
@@ -60,7 +60,7 @@
 mapUpdateEmpty() {
   var map = {};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [0] = 42;
 }
 
@@ -72,7 +72,7 @@
 mapUpdateSingle() {
   var map = {0: 1};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [0] = 42;
 }
 
@@ -84,7 +84,7 @@
 mapUpdateMultiple() {
   var map = {0: 1, 2: 3, 4: 5};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [2] = 42;
 }
 
@@ -96,7 +96,7 @@
 mapUpdateMissing() {
   var map = {0: 1};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
       [2] = 42;
 }
 
@@ -108,7 +108,7 @@
 mapUpdateMixedKeys() {
   dynamic map = {'': 2};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
+      /*update: Map([exact=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
       [0] = 42;
 }
 
@@ -120,7 +120,7 @@
 mapUpdateMixedValues() {
   dynamic map = {2: ''};
   return map
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
       [2] = 42;
 }
 
@@ -132,7 +132,7 @@
 dictionaryUpdateEmpty() {
   var map = {};
   return map
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([null|exact=JSString], value: "bar")})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([null|exact=JSString], value: "bar")})*/
       ['foo'] = 'bar';
 }
 
@@ -144,7 +144,7 @@
 dictionaryUpdateSingle() {
   var map = {'foo': 'bar'};
   return map
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSString], map: {foo: [exact=JSString]})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSString], map: {foo: [exact=JSString]})*/
       ['foo'] = 'boz';
 }
 
@@ -156,7 +156,7 @@
 dictionaryReUpdateSingle() {
   var map = {'foo': 'bar'};
   return map
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
       ['foo'] = 'bar';
 }
 
@@ -168,7 +168,7 @@
 dictionaryUpdateMultiple() {
   var map = {'foo': 'bar'};
   return map
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([null|exact=JSString], value: "boz")})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([null|exact=JSString], value: "boz")})*/
       ['baz'] = 'boz';
 }
 
@@ -180,7 +180,7 @@
 intDictionaryUpdateSingle() {
   var map = {};
   return map
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [null|exact=JSUInt31]})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [null|exact=JSUInt31]})*/
       ['foo'] = 0;
 }
 
diff --git a/pkg/compiler/test/inference/data/map_tracer_keys.dart b/pkg/compiler/test/inference/data/map_tracer_keys.dart
index beedfbf..1e70a9e 100644
--- a/pkg/compiler/test/inference/data/map_tracer_keys.dart
+++ b/pkg/compiler/test/inference/data/map_tracer_keys.dart
@@ -29,16 +29,16 @@
 test1() {
   var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
   theMap
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
       ['d'] = 5.5;
   /*iterator: [exact=LinkedHashMapKeyIterable]*/
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
       keys) {
     aDouble1 = theMap
-        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+        /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
@@ -60,16 +60,16 @@
 test2() {
   dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
   theMap
-      /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+      /*update: Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
       [aList2] = 5.5;
   /*iterator: [exact=LinkedHashMapKeyIterable]*/
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+      /*Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
       keys) {
     aDouble2 = theMap
-        /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+        /*Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
@@ -91,16 +91,16 @@
 test3() {
   dynamic theMap = <dynamic, dynamic>{'a': 2.2, 'b': 3.3, 'c': 4.4};
   theMap
-      /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+      /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
       ['d'] = aList3;
   /*iterator: [exact=LinkedHashMapKeyIterable]*/
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
       keys) {
     aDouble3 = theMap
-        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+        /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
@@ -125,10 +125,10 @@
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
       keys) {
     aDouble4 = theMap
-        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
+        /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
@@ -153,10 +153,10 @@
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
+      /*Map([exact=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
       keys) {
     aDouble5 = theMap
-        /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
+        /*Map([exact=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
@@ -180,10 +180,10 @@
   /*current: [exact=LinkedHashMapKeyIterator]*/
   /*moveNext: [exact=LinkedHashMapKeyIterator]*/
   for (var key in theMap.
-      /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+      /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
       keys) {
     aDouble6 = theMap
-        /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+        /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
         [key];
   }
   // We have to reference it somewhere, so that it always gets resolved.
diff --git a/pkg/compiler/test/inference/data/no_such_method4.dart b/pkg/compiler/test/inference/data/no_such_method4.dart
index 0538869..2cd61c1 100644
--- a/pkg/compiler/test/inference/data/no_such_method4.dart
+++ b/pkg/compiler/test/inference/data/no_such_method4.dart
@@ -13,13 +13,13 @@
 
 /*member: B.:[exact=B]*/
 class B extends A {
-  /*member: B.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
+  /*member: B.foo:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
       {};
 }
 
 /*member: C.:[exact=C]*/
 class C extends B {
-  /*member: C.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
+  /*member: C.foo:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
       {};
 }
 
@@ -34,22 +34,22 @@
   return e. /*invoke: [exact=A]*/ foo();
 }
 
-/*member: test2:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test2:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
 test2() => a. /*invoke: [null|subclass=B]*/ foo();
 
-/*member: test3:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test3:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
 test3() => new B(). /*invoke: [exact=B]*/ foo();
 
-/*member: test4:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test4:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
 test4() => new C(). /*invoke: [exact=C]*/ foo();
 
-/*member: test5:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test5:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
 test5() {
   dynamic e = (a ? new A() : new B());
   return e. /*invoke: [subclass=A]*/ foo();
 }
 
-/*member: test6:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test6:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
 test6() => (a ? new B() : new C()). /*invoke: [subclass=B]*/ foo();
 
 /*member: main:[null]*/
diff --git a/pkg/compiler/test/model/cfe_constant_evaluation_test.dart b/pkg/compiler/test/model/cfe_constant_evaluation_test.dart
index b133fd4..24c4a58 100644
--- a/pkg/compiler/test/model/cfe_constant_evaluation_test.dart
+++ b/pkg/compiler/test/model/cfe_constant_evaluation_test.dart
@@ -596,9 +596,9 @@
         expectedResults
             .forEach((Map<String, String> environment, String expectedText) {
           List<String> errors = [];
-          Dart2jsConstantEvaluator evaluator =
-              new Dart2jsConstantEvaluator(elementMap.typeEnvironment,
-                  (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
+          Dart2jsConstantEvaluator evaluator = new Dart2jsConstantEvaluator(
+              elementMap.env.mainComponent, elementMap.typeEnvironment,
+              (ir.LocatedMessage message, List<ir.LocatedMessage> context) {
             // TODO(johnniwinther): Assert that `message.uri != null`. Currently
             // all unevaluated constants have no uri.
             // The actual message is a "constant errors starts here" message,
@@ -606,11 +606,11 @@
             errors.add(context.first.code.name);
             reportLocatedMessage(elementMap.reporter, message, context);
           },
-                  environment: environment,
-                  supportReevaluationForTesting: true,
-                  evaluationMode: compiler.options.useLegacySubtyping
-                      ? ir.EvaluationMode.weak
-                      : ir.EvaluationMode.strong);
+              environment: environment,
+              supportReevaluationForTesting: true,
+              evaluationMode: compiler.options.useLegacySubtyping
+                  ? ir.EvaluationMode.weak
+                  : ir.EvaluationMode.strong);
           ir.Constant evaluatedConstant = evaluator.evaluate(
               new ir.StaticTypeContext(node, typeEnvironment), initializer);
 
diff --git a/pkg/compiler/test/rti/data/map_literal.dart b/pkg/compiler/test/rti/data/map_literal.dart
index 1d91a1b..988f06e 100644
--- a/pkg/compiler/test/rti/data/map_literal.dart
+++ b/pkg/compiler/test/rti/data/map_literal.dart
@@ -11,7 +11,7 @@
 /*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/data/map_to_set.dart b/pkg/compiler/test/rti/data/map_to_set.dart
index 79f0f2a..4c870c3 100644
--- a/pkg/compiler/test/rti/data/map_to_set.dart
+++ b/pkg/compiler/test/rti/data/map_to_set.dart
@@ -11,7 +11,7 @@
 /*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 02aaf4e..50cb925 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -329,8 +329,12 @@
   }
 }
 
-class RtiClassNeedIrComputer extends DataRegistry<String>
-    with ComputeValueMixin, IrMixin, IrDataRegistryMixin<String> {
+class RtiClassNeedIrComputer
+    with
+        DataRegistry<String>,
+        ComputeValueMixin,
+        IrMixin,
+        IrDataRegistryMixin<String> {
   @override
   final Compiler compiler;
   final JsToElementMap _elementMap;
diff --git a/pkg/compiler/tool/graph_isomorphizer.dart b/pkg/compiler/tool/graph_isomorphizer.dart
index 49894bd..74489b8 100644
--- a/pkg/compiler/tool/graph_isomorphizer.dart
+++ b/pkg/compiler/tool/graph_isomorphizer.dart
@@ -142,8 +142,11 @@
   /// A bool to omit the comment block.
   final bool skipCopyright;
 
+  // A bool to generate simple code within test files.
+  final bool simple;
+
   GraphIsomorphizer(this.names, this.maxBit,
-      {this.outDirectory: '.', this.skipCopyright: false});
+      {this.outDirectory: '.', this.skipCopyright: false, this.simple: false});
 
   void noInlineDecorator(StringBuffer out) {
     out.write("@pragma('dart2js:noInline')\n");
@@ -188,90 +191,92 @@
     var nameKeys = names.keys.toList();
     nameKeys.sort();
 
-    // Generate the 'base' classes, mixins, and types which will be combined to
-    // generate hierarchies. Also generate a const instance per class and a closure
-    // to invoke.
     Set<String> uniques = {};
-    for (var bitPosition in nameKeys) {
-      var bitsList = names[bitPosition];
-      for (var bits in bitsList) {
-        var name = generateBitString(bits);
-        if (!uniques.add(name)) continue;
-        String className = 'C$name';
-        String mixinName = 'M$name';
-        String typeName = 'T$name';
-        (classNames[bitPosition] ??= []).add(className);
-        (mixinNames[bitPosition] ??= []).add(mixinName);
-        (typeNames[bitPosition] ??= []).add(typeName);
-        (mixerClassNames[bitPosition] ??= []).add(className);
-        (mixerTypeNames[bitPosition] ??= []).add(typeName);
-        out.write('class $className { const $className(); }\n');
-        out.write('class $mixinName {}\n');
-        out.write('class $typeName {}\n');
-        out.write('const $className i$className = const $className();\n');
-        out.write('closure$className(foo) => ($className unused) ');
-        out.write('=> i$className.toString() == foo.toString();\n');
+    if (!simple) {
+      // Generate the 'base' classes, mixins, and types which will be combined to
+      // generate hierarchies. Also generate a const instance per class and a closure
+      // to invoke.
+      for (var bitPosition in nameKeys) {
+        var bitsList = names[bitPosition];
+        for (var bits in bitsList) {
+          var name = generateBitString(bits);
+          if (!uniques.add(name)) continue;
+          String className = 'C$name';
+          String mixinName = 'M$name';
+          String typeName = 'T$name';
+          (classNames[bitPosition] ??= []).add(className);
+          (mixinNames[bitPosition] ??= []).add(mixinName);
+          (typeNames[bitPosition] ??= []).add(typeName);
+          (mixerClassNames[bitPosition] ??= []).add(className);
+          (mixerTypeNames[bitPosition] ??= []).add(typeName);
+          out.write('class $className { const $className(); }\n');
+          out.write('class $mixinName {}\n');
+          out.write('class $typeName {}\n');
+          out.write('const $className i$className = const $className();\n');
+          out.write('closure$className(foo) => ($className unused) ');
+          out.write('=> i$className.toString() == foo.toString();\n');
+        }
       }
-    }
 
-    // Generate combined classes and types, as well as const instances and
-    // closures.
-    newline(out);
-    uniques = {};
-    for (var bitPosition in nameKeys) {
-      var bitsList = names[bitPosition];
-      for (var bits in bitsList) {
-        var name = generateBitString(bits);
-        var bitCount = bits.reduce((a, b) => a + b);
-        var baseName = 'C$name';
-        if (!uniques.add(baseName)) continue;
-        if (bitCount > 1) {
-          List<String> classes = [];
-          List<String> mixins = [];
-          List<String> types = [];
-          for (int i = 0; i < bits.length; i++) {
-            if (bits[i] == 1) {
-              classes.addAll(classNames[i]);
-              mixins.addAll(mixinNames[i]);
-              types.addAll(typeNames[i]);
-            }
-          }
-          String mixinString = mixins.join(', ');
-          int count = 1;
-          assert(classes.length == types.length);
-          for (int i = 0; i < classes.length; i++) {
-            var cls = classes[i];
-            var type = types[i];
-            List<String> classImpls = [];
-            List<String> typeImpls = [];
-            if (i > 0) {
-              classImpls.addAll(classes.sublist(0, i));
-              typeImpls.addAll(types.sublist(0, i));
-            }
-            if (i < classes.length - 1) {
-              classImpls.addAll(classes.sublist(i + 1));
-              typeImpls.addAll(types.sublist(i + 1));
-            }
-            var classImplementsString = classImpls.join(', ');
-            String className = '${baseName}_class_${count}';
-            out.write('class $className extends $cls with $mixinString ');
-            out.write(
-                'implements $classImplementsString { const $className(); }\n');
-            out.write('const $className i$className = const $className();\n');
-            out.write('closure$className(foo) => ($className unused) ');
-            out.write('=> i$className.toString() == foo.toString();\n');
-
-            var typeImplementsString = typeImpls.join(', ');
-            String typeName = 'T${name}_type__${count}';
-            out.write('class $typeName extends $type with $mixinString ');
-            out.write('implements $typeImplementsString {}\n');
+      // Generate combined classes and types, as well as const instances and
+      // closures.
+      newline(out);
+      uniques = {};
+      for (var bitPosition in nameKeys) {
+        var bitsList = names[bitPosition];
+        for (var bits in bitsList) {
+          var name = generateBitString(bits);
+          var bitCount = bits.reduce((a, b) => a + b);
+          var baseName = 'C$name';
+          if (!uniques.add(baseName)) continue;
+          if (bitCount > 1) {
+            List<String> classes = [];
+            List<String> mixins = [];
+            List<String> types = [];
             for (int i = 0; i < bits.length; i++) {
               if (bits[i] == 1) {
-                mixerClassNames[i].add(className);
-                mixerTypeNames[i].add(typeName);
+                classes.addAll(classNames[i]);
+                mixins.addAll(mixinNames[i]);
+                types.addAll(typeNames[i]);
               }
             }
-            count++;
+            String mixinString = mixins.join(', ');
+            int count = 1;
+            assert(classes.length == types.length);
+            for (int i = 0; i < classes.length; i++) {
+              var cls = classes[i];
+              var type = types[i];
+              List<String> classImpls = [];
+              List<String> typeImpls = [];
+              if (i > 0) {
+                classImpls.addAll(classes.sublist(0, i));
+                typeImpls.addAll(types.sublist(0, i));
+              }
+              if (i < classes.length - 1) {
+                classImpls.addAll(classes.sublist(i + 1));
+                typeImpls.addAll(types.sublist(i + 1));
+              }
+              var classImplementsString = classImpls.join(', ');
+              String className = '${baseName}_class_${count}';
+              out.write('class $className extends $cls with $mixinString ');
+              out.write(
+                  'implements $classImplementsString { const $className(); }\n');
+              out.write('const $className i$className = const $className();\n');
+              out.write('closure$className(foo) => ($className unused) ');
+              out.write('=> i$className.toString() == foo.toString();\n');
+
+              var typeImplementsString = typeImpls.join(', ');
+              String typeName = 'T${name}_type__${count}';
+              out.write('class $typeName extends $type with $mixinString ');
+              out.write('implements $typeImplementsString {}\n');
+              for (int i = 0; i < bits.length; i++) {
+                if (bits[i] == 1) {
+                  mixerClassNames[i].add(className);
+                  mixerTypeNames[i].add(typeName);
+                }
+              }
+              count++;
+            }
           }
         }
       }
@@ -301,35 +306,41 @@
     importExpect(out);
     out.write("import '$import';\n\n");
 
-    // create type test.
-    noInlineDecorator(out);
-    out.write('typeTest(dynamic t) {\n');
-    for (var type in mixerTypeNames[bit]) {
-      out.write('  if (t is $type) { return true; }\n');
+    if (!simple) {
+      // create type test.
+      noInlineDecorator(out);
+      out.write('typeTest(dynamic t) {\n');
+      for (var type in mixerTypeNames[bit]) {
+        out.write('  if (t is $type) { return true; }\n');
+      }
+      out.write('  return false;\n');
+      out.write('}\n\n');
     }
-    out.write('  return false;\n');
-    out.write('}\n\n');
 
     noInlineDecorator(out);
     out.write('g$name() {\n');
-    out.write('  // C${generateCommentName(bits, bit)};\n');
 
-    // Construct new instances of each class and pass them to the typeTest
-    for (var cls in mixerClassNames[bit]) {
-      out.write('  Expect.isFalse(typeTest($cls()));\n');
-    }
-    newline(out);
+    if (!simple) {
+      out.write('  // C${generateCommentName(bits, bit)};\n');
 
-    // Invoke the test closure for each class.
-    for (var cls in mixerClassNames[bit]) {
-      out.write('  Expect.isTrue(closure$cls($cls())($cls()));\n');
-    }
-    newline(out);
+      // Construct new instances of each class and pass them to the typeTest
+      for (var cls in mixerClassNames[bit]) {
+        out.write('  Expect.isFalse(typeTest($cls()));\n');
+      }
+      newline(out);
 
-    // Verify the runtimeTypes of the closures haven't been mangled.
-    for (var cls in mixerClassNames[bit]) {
-      out.write('  Expect.equals(closure$cls($cls()).runtimeType.toString(), ');
-      out.write("'($cls) => bool');\n");
+      // Invoke the test closure for each class.
+      for (var cls in mixerClassNames[bit]) {
+        out.write('  Expect.isTrue(closure$cls($cls())($cls()));\n');
+      }
+      newline(out);
+
+      // Verify the runtimeTypes of the closures haven't been mangled.
+      for (var cls in mixerClassNames[bit]) {
+        out.write(
+            '  Expect.equals(closure$cls($cls()).runtimeType.toString(), ');
+        out.write("'($cls) => bool');\n");
+      }
     }
     newline(out);
 
@@ -466,6 +477,7 @@
 
 /// Creates a GraphIsomorphizer based on the provided args.
 GraphIsomorphizer createGraphIsomorphizer(List<String> args) {
+  bool simple = true;
   int maxBit = 0;
   String graphFile = '';
   String outDirectory = '.';
@@ -480,6 +492,9 @@
     if (arg.startsWith('--out-dir')) {
       outDirectory = arg.substring('--out-dir='.length);
     }
+    if (arg == '--simple') {
+      simple = true;
+    }
   }
 
   // If we don't have a graphFile, then we generate all permutations of bits up
@@ -491,7 +506,8 @@
   } else {
     maxBit = namesFromGraphFile(graphFile, names);
   }
-  return GraphIsomorphizer(names, maxBit, outDirectory: outDirectory);
+  return GraphIsomorphizer(names, maxBit,
+      outDirectory: outDirectory, simple: simple);
 }
 
 void main(List<String> args) {
diff --git a/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
new file mode 100644
index 0000000..577aee6
--- /dev/null
+++ b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Command-line tool presenting combined information from dump-info and
+/// runtime coverage data.
+///
+/// This tool requires two input files an `.info.data` and a
+/// `.coverage.json` file. To produce these files you need to follow these
+/// steps:
+///
+///   * Compile an app with dart2js using --dump-info and save the .info.data
+///     file:
+///
+///      dart2js --dump-info main.dart
+///
+///   * Build the same app with dart2js using --experimental-track-allocations:
+///
+///      dart2js --experimental-track-allocations main.dart
+///
+///     This can be combined with the --dump-info step above.
+///
+///   * Load your app, exercise your code, then extract the runtime code
+///     coverage JSON blob by querying `$__dart_deferred_initializers__.allocations` in the page.
+///
+///   * Finally, run this tool.
+library compiler.tool.runtime_coverage_analysis;
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:args/command_runner.dart';
+import 'package:collection/collection.dart';
+
+import 'package:dart2js_info/info.dart';
+import 'package:dart2js_info/src/io.dart';
+import 'package:dart2js_info/src/util.dart';
+
+import 'usage_exception.dart';
+
+class RuntimeCoverageAnalysisCommand extends Command<void>
+    with PrintUsageException {
+  @override
+  final String name = "runtime_coverage";
+  @override
+  final String description = "Analyze runtime coverage data";
+
+  RuntimeCoverageAnalysisCommand();
+
+  @override
+  void run() async {
+    var args = argResults.rest;
+    if (args.length < 2) {
+      usageException('Missing arguments, expected: info.data coverage.json');
+    }
+    await _runtimeCoverageAnalysis(args[0], args[1]);
+  }
+}
+
+Future<void> _runtimeCoverageAnalysis(infoFile, coverageFile) async {
+  var info = await infoFromFile(infoFile);
+  var coverageRaw = jsonDecode(File(coverageFile).readAsStringSync());
+  var coverage = <String, bool>{};
+  coverageRaw
+      .forEach((k, v) => coverage[k] = coverage[k] ?? false || v as bool);
+
+  int totalProgramSize = info.program.size;
+  int totalLibSize = info.libraries.fold(0, (n, lib) => n + lib.size);
+
+  int totalCode = 0;
+  int usedCode = 0;
+  var unused = PriorityQueue<Info>((a, b) => b.size.compareTo(a.size));
+
+  void tallyCode(Info i) {
+    totalCode += i.size;
+    var name = qualifiedName(i);
+    var used = coverage[name];
+
+    if (used != null) {
+      usedCode += i.size;
+    } else {
+      unused.add(i);
+    }
+  }
+
+  info.classes.forEach(tallyCode);
+  info.closures.forEach(tallyCode);
+
+  _section('Runtime Coverage Summary');
+  _showHeader('', 'bytes', '%');
+  _show('Program size', totalProgramSize, totalProgramSize);
+  _show('Libraries (excluding statics)', totalLibSize, totalProgramSize);
+  _show('Code (classes + closures)', totalCode, totalProgramSize);
+  _show('Used', usedCode, totalProgramSize);
+
+  print('');
+  _showHeader('', 'count', '%');
+  var total = info.classes.length + info.closures.length;
+  _show('Classes + closures', total, total);
+  _show('Used', total - unused.length, total);
+
+  print('');
+  var unusedTotal = totalCode - usedCode;
+  _section('Runtime Coverage Breakdown', size: unusedTotal);
+
+  // TODO(markzipan): support grouping results by package/library.
+  for (int i = 0; i < unused.length; i++) {
+    var item = unused.removeFirst();
+    var percent = (item.size * 100 / unusedTotal).toStringAsFixed(2);
+    print('${qualifiedName(item)}: ${item.size} bytes, $percent%');
+  }
+}
+
+void _section(String title, {int size}) {
+  if (size == null) {
+    print(title);
+  } else {
+    print('$title ($size bytes)');
+  }
+  print('=' * 72);
+}
+
+_showHeader(String msg, String header1, String header2) {
+  print(' ${pad(msg, 30, right: true)} ${pad(header1, 8)} ${pad(header2, 6)}');
+}
+
+_show(String msg, int size, int total) {
+  var percent = (size * 100 / total).toStringAsFixed(2);
+  print(' ${pad(msg, 30, right: true)} ${pad(size, 8)} ${pad(percent, 6)}%');
+}
diff --git a/pkg/dart2js_info/bin/tools.dart b/pkg/dart2js_info/bin/tools.dart
index 9e2cda8..7dc64bd 100644
--- a/pkg/dart2js_info/bin/tools.dart
+++ b/pkg/dart2js_info/bin/tools.dart
@@ -16,6 +16,7 @@
 import 'src/function_size_analysis.dart';
 import 'src/library_size_split.dart';
 import 'src/live_code_size_analysis.dart';
+import 'src/runtime_coverage_analysis.dart';
 import 'src/show_inferred_types.dart';
 import 'src/text_print.dart';
 
@@ -35,6 +36,7 @@
     ..addCommand(FunctionSizeCommand())
     ..addCommand(LibrarySizeCommand())
     ..addCommand(LiveCodeAnalysisCommand())
+    ..addCommand(RuntimeCoverageAnalysisCommand())
     ..addCommand(ShowInferredTypesCommand())
     ..addCommand(ShowCommand());
   commandRunner.run(args);
diff --git a/pkg/dart2js_info/lib/src/util.dart b/pkg/dart2js_info/lib/src/util.dart
index eebb1c7..9ee83cb 100644
--- a/pkg/dart2js_info/lib/src/util.dart
+++ b/pkg/dart2js_info/lib/src/util.dart
@@ -46,6 +46,26 @@
   return graph;
 }
 
+/// Provide a qualified name associated with [info]. Qualified names consist of
+/// the library's canonical URI concatenated with a library-unique kernel name.
+// See: https://github.com/dart-lang/sdk/blob/47eff41cdbfea4a178208dfc3137ba2b6bea0e36/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart#L978
+// TODO(sigmund): guarantee that the name is actually unique.
+String qualifiedName(Info f) {
+  assert(f is ClosureInfo || f is ClassInfo);
+  var element = f;
+  String name;
+  while (element != null) {
+    if (element is LibraryInfo) {
+      name = '${element.uri}:$name';
+      return name;
+    } else {
+      name = name ?? element.name;
+      element = element.parent;
+    }
+  }
+  return '';
+}
+
 /// Provide a unique long name associated with [info].
 // TODO(sigmund): guarantee that the name is actually unique.
 String longName(Info info, {bool useLibraryUri = false, bool forId = false}) {
diff --git a/pkg/dart_internal/CHANGELOG.md b/pkg/dart_internal/CHANGELOG.md
index 8894fed..868e075 100644
--- a/pkg/dart_internal/CHANGELOG.md
+++ b/pkg/dart_internal/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.4
+
+- Support the latest Dart SDK.
+
 ## 0.2.3
 
 - Support the latest Dart SDK.
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 9d5dacc..244171e 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dart_internal
-version: 0.2.3
+version: 0.2.4
 repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart_internal
 description: >-
   This package is not intended for wide use. It provides a temporary API to
@@ -9,4 +9,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.12.0 <2.17.0"
+  sdk: ">=2.12.0 <2.18.0"
diff --git a/pkg/dartdev/bin/dartdev.dart b/pkg/dartdev/bin/dartdev.dart
index c2eee8a..7c096ee 100644
--- a/pkg/dartdev/bin/dartdev.dart
+++ b/pkg/dartdev/bin/dartdev.dart
@@ -7,6 +7,6 @@
 import 'package:dartdev/dartdev.dart';
 
 /// The entry point for dartdev.
-Future<void> main(List<String> args, SendPort port) async {
+Future<void> main(List<String> args, SendPort? port) async {
   await runDartdev(args, port);
 }
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 3e75181..acebbf7 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -11,7 +11,6 @@
 import 'package:args/command_runner.dart';
 import 'package:cli_util/cli_logging.dart';
 import 'package:dart_style/src/cli/format_command.dart';
-import 'package:devtools_server/devtools_server.dart';
 import 'package:meta/meta.dart';
 import 'package:pub/pub.dart';
 import 'package:usage/usage.dart';
@@ -21,6 +20,7 @@
 import 'src/commands/compile.dart';
 import 'src/commands/create.dart';
 import 'src/commands/debug_adapter.dart';
+import 'src/commands/devtools.dart';
 import 'src/commands/doc.dart';
 import 'src/commands/fix.dart';
 import 'src/commands/language_server.dart';
@@ -30,13 +30,12 @@
 import 'src/core.dart';
 import 'src/events.dart';
 import 'src/experiments.dart';
-import 'src/sdk.dart';
 import 'src/utils.dart';
 import 'src/vm_interop_handler.dart';
 
 /// This is typically called from bin/, but given the length of the method and
 /// analytics logic, it has been moved here.
-Future<void> runDartdev(List<String> args, SendPort port) async {
+Future<void> runDartdev(List<String> args, SendPort? port) async {
   VmInteropHandler.initialize(port);
 
   // TODO(sigurdm): Remove when top-level pub is removed.
@@ -62,7 +61,7 @@
   // Finally, call the runner to execute the command; see DartdevRunner.
 
   final runner = DartdevRunner(args);
-  var exitCode = 1;
+  int? exitCode = 1;
   try {
     exitCode = await runner.run(args);
   } on UsageException catch (e) {
@@ -87,7 +86,7 @@
 
   final bool verbose;
 
-  Analytics _analytics;
+  late Analytics _analytics;
 
   DartdevRunner(List<String> args)
       : verbose = args.contains('-v') || args.contains('--verbose'),
@@ -118,7 +117,6 @@
     addCommand(DocCommand(verbose: verbose));
     addCommand(DevToolsCommand(
       verbose: verbose,
-      customDevToolsPath: sdk.devToolsBinaries,
     ));
     addCommand(FixCommand(verbose: verbose));
     addCommand(FormatCommand(verbose: verbose));
@@ -130,6 +128,7 @@
           () => analytics,
           dependencyKindCustomDimensionName: dependencyKindCustomDimensionName,
         ),
+        isVerbose: () => verbose,
       ),
     );
     addCommand(RunCommand(verbose: verbose));
@@ -223,15 +222,15 @@
 
     // The exit code for the dartdev process; null indicates that it has not been
     // set yet. The value is set in the catch and finally blocks below.
-    int exitCode;
+    int? exitCode;
 
     // Any caught non-UsageExceptions when running the sub command.
-    Object exception;
-    StackTrace stackTrace;
+    Object? exception;
+    StackTrace? stackTrace;
     try {
       exitCode = await super.runCommand(topLevelResults);
 
-      if (path != null && analytics.enabled) {
+      if (analytics.enabled) {
         // Send the event to analytics
         unawaited(
           sendUsageEvent(
@@ -244,7 +243,8 @@
                 // value.
                 //
                 // Note that this will also conflate short-options and long-options.
-                command?.options?.where(command.wasParsed)?.toList(),
+                command?.options.where(command.wasParsed).toList() ??
+                    const <String>[],
             specifiedExperiments: topLevelResults.enabledExperiments,
           ),
         );
@@ -265,7 +265,7 @@
       if (analytics.enabled) {
         unawaited(
           analytics.sendTiming(
-            path ?? '',
+            path,
             stopwatch.elapsedMilliseconds,
             category: 'commands',
           ),
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index 1666afc..e8ae525 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -14,7 +14,6 @@
         EditBulkFixesResult,
         ResponseDecoder;
 import 'package:args/args.dart';
-import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
 import 'core.dart';
@@ -23,7 +22,7 @@
 
 /// When set, this function is executed just before the Analysis Server starts.
 void Function(String cmdName, List<FileSystemEntity> analysisRoots,
-    ArgResults argResults) preAnalysisServerStart;
+    ArgResults? argResults)? preAnalysisServerStart;
 
 /// A class to provide an API wrapper around an analysis server process.
 class AnalysisServer {
@@ -32,18 +31,18 @@
     this.sdkPath,
     this.analysisRoots, {
     this.cacheDirectoryPath,
-    @required this.commandName,
-    @required this.argResults,
+    required this.commandName,
+    required this.argResults,
   });
 
-  final String cacheDirectoryPath;
-  final File packagesFile;
+  final String? cacheDirectoryPath;
+  final File? packagesFile;
   final Directory sdkPath;
   final List<FileSystemEntity> analysisRoots;
   final String commandName;
-  final ArgResults argResults;
+  final ArgResults? argResults;
 
-  Process _process;
+  Process? _process;
 
   Completer<bool> _analysisFinished = Completer();
 
@@ -53,8 +52,8 @@
     // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
     return _streamController('server.status')
         .stream
-        .where((event) => event['analysis'] != null)
-        .map((event) => event['analysis']['isAnalyzing'] as bool);
+        .where((event) => event!['analysis'] != null)
+        .map((event) => (event!['analysis']['isAnalyzing']!) as bool);
   }
 
   /// This future completes when we next receive an analysis finished event
@@ -65,7 +64,7 @@
   Stream<FileAnalysisErrors> get onErrors {
     // {"event":"analysis.errors","params":{"file":"/Users/.../lib/main.dart","errors":[]}}
     return _streamController('analysis.errors').stream.map((event) {
-      final file = event['file'] as String;
+      final file = event!['file'] as String;
       final errorsList = event['errors'] as List<dynamic>;
       final errors = errorsList
           .map<Map<String, dynamic>>(castStringKeyedMap)
@@ -76,7 +75,7 @@
     });
   }
 
-  Future<int> get onExit => _process.exitCode;
+  Future<int> get onExit => _process!.exitCode;
 
   final Map<String, StreamController<Map<String, dynamic>>> _streamControllers =
       {};
@@ -94,19 +93,19 @@
       '--sdk',
       sdkPath.path,
       if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath',
-      if (packagesFile != null) '--packages=${packagesFile.path}',
+      if (packagesFile != null) '--packages=${packagesFile!.path}',
     ];
 
     _process = await startDartProcess(sdk, command);
     // This callback hookup can't throw.
-    _process.exitCode.whenComplete(() => _process = null);
+    _process!.exitCode.whenComplete(() => _process = null);
 
-    final Stream<String> errorStream = _process.stderr
+    final Stream<String> errorStream = _process!.stderr
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     errorStream.listen(log.stderr);
 
-    final Stream<String> inStream = _process.stdout
+    final Stream<String> inStream = _process!.stdout
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     inStream.listen(_handleServerResponse);
@@ -125,7 +124,7 @@
     // be passed to the analysis server.
     List<String> analysisRootPaths = analysisRoots.map((root) {
       return trimEnd(
-          root.absolute.resolveSymbolicLinksSync(), path.context.separator);
+          root.absolute.resolveSymbolicLinksSync(), path.context.separator)!;
     }).toList();
 
     onAnalyzing.listen((bool isAnalyzing) {
@@ -138,7 +137,7 @@
       }
     });
 
-    _sendCommand('analysis.setAnalysisRoots', params: <String, dynamic>{
+    await _sendCommand('analysis.setAnalysisRoots', params: <String, dynamic>{
       'included': analysisRootPaths,
       'excluded': <String>[]
     });
@@ -178,7 +177,7 @@
   }
 
   Future<Map<String, dynamic>> _sendCommand(String method,
-      {Map<String, dynamic> params}) {
+      {Map<String, dynamic>? params}) {
     final String id = (++_id).toString();
     final String message = json.encode(<String, dynamic>{
       'id': id,
@@ -187,11 +186,11 @@
     });
 
     _requestCompleters[id] = Completer();
-    _process.stdin.writeln(message);
+    _process!.stdin.writeln(message);
 
     log.trace('==> $message');
 
-    return _requestCompleters[id].future;
+    return _requestCompleters[id]!.future;
   }
 
   void _handleServerResponse(String line) {
@@ -216,27 +215,28 @@
               .remove(id)
               ?.completeError(RequestError.parse(error));
         } else {
-          _requestCompleters.remove(id)?.complete(response['result']);
+          _requestCompleters.remove(id)?.complete(response['result'] ?? {});
         }
       }
     }
   }
 
-  void _handleServerError(Map<String, dynamic> error) {
+  void _handleServerError(Map<String, dynamic>? error) {
+    final err = error!;
     // Fields are 'isFatal', 'message', and 'stackTrace'.
-    log.stderr('Error from the analysis server: ${error['message']}');
-    if (error['stackTrace'] != null) {
-      log.stderr(error['stackTrace'] as String);
+    log.stderr('Error from the analysis server: ${err['message']}');
+    if (err['stackTrace'] != null) {
+      log.stderr(err['stackTrace'] as String);
     }
   }
 
-  StreamController<Map<String, dynamic>> _streamController(String streamId) {
+  StreamController<Map<String, dynamic>?> _streamController(String streamId) {
     return _streamControllers.putIfAbsent(
         streamId, () => StreamController<Map<String, dynamic>>.broadcast());
   }
 
   Future<bool> dispose() async {
-    return _process?.kill();
+    return _process?.kill() ?? true;
   }
 }
 
@@ -262,10 +262,10 @@
   // },"message":"...","hasFix":false}
   Map<String, dynamic> json;
 
-  String get severity => json['severity'] as String;
+  String? get severity => json['severity'] as String?;
 
   _AnalysisSeverity get _severityLevel =>
-      _severityMap[severity] ?? _AnalysisSeverity.none;
+      _severityMap[severity!] ?? _AnalysisSeverity.none;
 
   bool get isInfo => _severityLevel == _AnalysisSeverity.info;
 
@@ -279,26 +279,26 @@
 
   String get code => json['code'] as String;
 
-  String get correction => json['correction'] as String;
+  String? get correction => json['correction'] as String?;
 
-  int get endColumn => json['location']['endColumn'] as int;
+  int? get endColumn => json['location']['endColumn'] as int?;
 
-  int get endLine => json['location']['endLine'] as int;
+  int? get endLine => json['location']['endLine'] as int?;
 
   String get file => json['location']['file'] as String;
 
-  int get startLine => json['location']['startLine'] as int;
+  int? get startLine => json['location']['startLine'] as int?;
 
-  int get startColumn => json['location']['startColumn'] as int;
+  int? get startColumn => json['location']['startColumn'] as int?;
 
   int get offset => json['location']['offset'] as int;
 
   int get length => json['location']['length'] as int;
 
-  String get url => json['url'] as String;
+  String? get url => json['url'] as String?;
 
   List<DiagnosticMessage> get contextMessages {
-    var messages = json['contextMessages'] as List<dynamic>;
+    var messages = json['contextMessages'] as List<dynamic>?;
     if (messages == null) {
       // The field is optional, so we return an empty list as a default value.
       return [];
@@ -326,7 +326,7 @@
   }
 
   @override
-  String toString() => '${severity.toLowerCase()} • '
+  String toString() => '${severity!.toLowerCase()} • '
       '$message • $file:$startLine:$startColumn • '
       '($code)';
 }
@@ -336,11 +336,11 @@
 
   DiagnosticMessage(this.json);
 
-  int get column => json['location']['startColumn'] as int;
+  int? get column => json['location']['startColumn'] as int?;
 
-  int get endColumn => json['location']['endColumn'] as int;
+  int? get endColumn => json['location']['endColumn'] as int?;
 
-  int get endLine => json['location']['endLine'] as int;
+  int? get endLine => json['location']['endLine'] as int?;
 
   String get filePath => json['location']['file'] as String;
 
@@ -373,7 +373,7 @@
   final String message;
   final String stackTrace;
 
-  RequestError(this.code, this.message, {this.stackTrace});
+  RequestError(this.code, this.message, {required this.stackTrace});
 
   @override
   String toString() => '[RequestError code: $code, message: $message]';
diff --git a/pkg/dartdev/lib/src/analytics.dart b/pkg/dartdev/lib/src/analytics.dart
index 3072c34..7b69d8e 100644
--- a/pkg/dartdev/lib/src/analytics.dart
+++ b/pkg/dartdev/lib/src/analytics.dart
@@ -101,7 +101,7 @@
 ///
 /// This can return null under some conditions, including when the user's home
 /// directory does not exist.
-Directory getDartStorageDirectory() {
+Directory? getDartStorageDirectory() {
   var homeDir = Directory(userHomeDir());
   if (!homeDir.existsSync()) {
     return null;
@@ -133,11 +133,11 @@
     }
 
     // If there's no explicit setting (enabled or disabled) then we don't send.
-    return (properties['enabled'] as bool) ?? false;
+    return (properties['enabled'] as bool?) ?? false;
   }
 
   bool get disclosureShownOnTerminal =>
-      (properties['disclosureShown'] as bool) ?? false;
+      (properties['disclosureShown'] as bool?) ?? false;
 
   set disclosureShownOnTerminal(bool value) {
     properties['disclosureShown'] = value;
@@ -171,7 +171,7 @@
   bool get firstRun => false;
 
   @override
-  Future sendScreenView(String viewName, {Map<String, String> parameters}) {
+  Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
     parameters ??= <String, String>{};
     parameters['viewName'] = viewName;
     return _log('screenView', parameters);
@@ -179,7 +179,7 @@
 
   @override
   Future sendEvent(String category, String action,
-      {String label, int value, Map<String, String> parameters}) {
+      {String? label, int? value, Map<String, String>? parameters}) {
     parameters ??= <String, String>{};
     return _log(
         'event',
@@ -193,7 +193,7 @@
 
   @override
   Future sendTiming(String variableName, int time,
-      {String category, String label}) {
+      {String? category, String? label}) {
     return _log('timing', {
       'variableName': variableName,
       'time': time,
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 2c8837b..1112fe8 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -82,12 +82,13 @@
 
   @override
   FutureOr<int> run() async {
+    final args = argResults!;
     // Find targets from the 'rest' params.
     final List<io.FileSystemEntity> targets = [];
-    if (argResults.rest.isEmpty) {
+    if (args.rest.isEmpty) {
       targets.add(io.Directory.current);
     } else {
-      for (String targetPath in argResults.rest) {
+      for (String targetPath in args.rest) {
         if (io.Directory(targetPath).existsSync()) {
           targets.add(io.Directory(targetPath));
         } else if (io.File(targetPath).existsSync()) {
@@ -100,8 +101,8 @@
 
     final List<AnalysisError> errors = <AnalysisError>[];
 
-    final machineFormat = argResults['format'] == 'machine';
-    final jsonFormat = argResults['format'] == 'json';
+    final machineFormat = args['format'] == 'machine';
+    final jsonFormat = args['format'] == 'json';
 
     final targetsNames =
         targets.map((entity) => path.basename(entity.path)).join(', ');
@@ -113,9 +114,9 @@
       _packagesFile(),
       io.Directory(sdk.sdkPath),
       targets,
-      cacheDirectoryPath: argResults['cache'],
+      cacheDirectoryPath: args['cache'],
       commandName: 'analyze',
-      argResults: argResults,
+      argResults: args,
     );
 
     server.onErrors.listen((FileAnalysisErrors fileErrors) {
@@ -160,7 +161,9 @@
       emitDefaultFormat(
         log,
         errors,
-        relativeToDir: relativeTo is io.File ? relativeTo.parent : relativeTo,
+        relativeToDir: relativeTo is io.File
+            ? relativeTo.parent
+            : relativeTo as io.Directory?,
         verbose: verbose,
       );
     }
@@ -181,8 +184,8 @@
       return 3;
     }
 
-    bool fatalWarnings = argResults['fatal-warnings'];
-    bool fatalInfos = argResults['fatal-infos'];
+    bool fatalWarnings = args['fatal-warnings'];
+    bool fatalInfos = args['fatal-infos'];
 
     if (fatalWarnings && hasWarnings) {
       return 2;
@@ -193,8 +196,8 @@
     }
   }
 
-  io.File _packagesFile() {
-    var path = argResults['packages'];
+  io.File? _packagesFile() {
+    var path = argResults!['packages'];
     if (path is String) {
       var file = io.File(path);
       if (!file.existsSync()) {
@@ -210,7 +213,7 @@
   static void emitDefaultFormat(
     Logger log,
     List<AnalysisError> errors, {
-    io.Directory relativeToDir,
+    io.Directory? relativeToDir,
     bool verbose = false,
   }) {
     final ansi = log.ansi;
@@ -220,10 +223,10 @@
 
     final wrapWidth = dartdevUsageLineLength == null
         ? null
-        : (dartdevUsageLineLength - _bodyIndentWidth);
+        : (dartdevUsageLineLength! - _bodyIndentWidth);
 
     for (final AnalysisError error in errors) {
-      var severity = error.severity.toLowerCase().padLeft(_severityWidth);
+      var severity = error.severity!.toLowerCase().padLeft(_severityWidth);
       if (error.isError) {
         severity = ansi.error(severity);
       }
@@ -231,7 +234,7 @@
       var codeRef = error.code;
       // If we're in verbose mode, write any error urls instead of error codes.
       if (error.url != null && verbose) {
-        codeRef = error.url;
+        codeRef = error.url!;
       }
 
       // Emit "file:line:col * Error message. Correction (code)."
@@ -278,7 +281,7 @@
           'range': range,
         };
 
-    Map<String, dynamic> position(int offset, int line, int column) => {
+    Map<String, dynamic> position(int? offset, int? line, int? column) => {
           'offset': offset,
           'line': line,
           'column': column,
@@ -364,8 +367,8 @@
   }
 
   /// Return a relative path if it is a shorter reference than the given dir.
-  static String _relativePath(String givenPath, io.Directory fromDir) {
-    String fromPath = fromDir?.absolute?.resolveSymbolicLinksSync();
+  static String _relativePath(String givenPath, io.Directory? fromDir) {
+    String? fromPath = fromDir?.absolute.resolveSymbolicLinksSync();
     String relative = path.relative(givenPath, from: fromPath);
     return relative.length <= givenPath.length ? relative : givenPath;
   }
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 4198a79..6e3d600 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -21,14 +21,14 @@
 class Option {
   final String flag;
   final String help;
-  final String abbr;
-  final String defaultsTo;
-  final List<String> allowed;
-  final Map<String, String> allowedHelp;
+  final String? abbr;
+  final String? defaultsTo;
+  final List<String>? allowed;
+  final Map<String, String>? allowedHelp;
 
   Option(
-      {this.flag,
-      this.help,
+      {required this.flag,
+      required this.help,
       this.abbr,
       this.defaultsTo,
       this.allowed,
@@ -71,7 +71,7 @@
   @override
   final ArgParser argParser = ArgParser.allowAnything();
 
-  CompileJSCommand({bool verbose})
+  CompileJSCommand({bool verbose = false})
       : super(cmdName, 'Compile Dart to JavaScript.', verbose);
 
   @override
@@ -90,7 +90,8 @@
         [
           '--libraries-spec=$librariesPath',
           '--cfe-invocation-modes=compile',
-          ...argResults.arguments,
+          '--invoker=dart_cli',
+          ...argResults!.arguments,
         ],
         packageConfigOverride: null);
 
@@ -108,25 +109,25 @@
   final String formatName;
 
   CompileSnapshotCommand({
-    this.commandName,
-    this.help,
-    this.fileExt,
-    this.formatName,
-    bool verbose,
+    required this.commandName,
+    required this.help,
+    required this.fileExt,
+    required this.formatName,
+    bool verbose = false,
   }) : super(commandName, 'Compile Dart $help', verbose) {
     argParser
       ..addOption(
-        commonOptions['outputFile'].flag,
-        help: commonOptions['outputFile'].help,
-        abbr: commonOptions['outputFile'].abbr,
+        commonOptions['outputFile']!.flag,
+        help: commonOptions['outputFile']!.help,
+        abbr: commonOptions['outputFile']!.abbr,
       )
       ..addOption(
-        commonOptions['verbosity'].flag,
-        help: commonOptions['verbosity'].help,
-        abbr: commonOptions['verbosity'].abbr,
-        defaultsTo: commonOptions['verbosity'].defaultsTo,
-        allowed: commonOptions['verbosity'].allowed,
-        allowedHelp: commonOptions['verbosity'].allowedHelp,
+        commonOptions['verbosity']!.flag,
+        help: commonOptions['verbosity']!.help,
+        abbr: commonOptions['verbosity']!.abbr,
+        defaultsTo: commonOptions['verbosity']!.defaultsTo,
+        allowed: commonOptions['verbosity']!.allowed,
+        allowedHelp: commonOptions['verbosity']!.allowedHelp,
       );
 
     addExperimentalFlags(argParser, verbose);
@@ -145,20 +146,21 @@
 
   @override
   FutureOr<int> run() async {
-    if (argResults.rest.isEmpty) {
+    final args = argResults!;
+    if (args.rest.isEmpty) {
       // This throws.
       usageException('Missing Dart entry point.');
-    } else if (!isJitSnapshot && argResults.rest.length > 1) {
+    } else if (!isJitSnapshot && args.rest.length > 1) {
       usageException('Unexpected arguments after Dart entry point.');
     }
 
-    final String sourcePath = argResults.rest[0];
+    final String sourcePath = args.rest[0];
     if (!checkFile(sourcePath)) {
       return -1;
     }
 
     // Determine output file name.
-    String outputFile = argResults[commonOptions['outputFile'].flag];
+    String? outputFile = args[commonOptions['outputFile']!.flag];
     if (outputFile == null) {
       final inputWithoutDart = sourcePath.endsWith('.dart')
           ? sourcePath.substring(0, sourcePath.length - 5)
@@ -166,31 +168,31 @@
       outputFile = '$inputWithoutDart.$fileExt';
     }
 
-    final enabledExperiments = argResults.enabledExperiments;
+    final enabledExperiments = args.enabledExperiments;
     // Build arguments.
-    List<String> args = [];
-    args.add('--snapshot-kind=$formatName');
-    args.add('--snapshot=${path.canonicalize(outputFile)}');
+    List<String> buildArgs = [];
+    buildArgs.add('--snapshot-kind=$formatName');
+    buildArgs.add('--snapshot=${path.canonicalize(outputFile)}');
 
-    String verbosity = argResults[commonOptions['verbosity'].flag];
-    args.add('--verbosity=$verbosity');
+    String? verbosity = args[commonOptions['verbosity']!.flag];
+    buildArgs.add('--verbosity=$verbosity');
 
     if (enabledExperiments.isNotEmpty) {
-      args.add("--enable-experiment=${enabledExperiments.join(',')}");
+      buildArgs.add("--enable-experiment=${enabledExperiments.join(',')}");
     }
     if (verbose) {
-      args.add('-v');
+      buildArgs.add('-v');
     }
-    args.add(path.canonicalize(sourcePath));
+    buildArgs.add(path.canonicalize(sourcePath));
 
     // Add the training arguments.
-    if (argResults.rest.length > 1) {
-      args.addAll(argResults.rest.sublist(1));
+    if (args.rest.length > 1) {
+      buildArgs.addAll(args.rest.sublist(1));
     }
 
     log.stdout('Compiling $sourcePath to $commandName file $outputFile.');
     // TODO(bkonyi): perform compilation in same process.
-    final process = await startDartProcess(sdk, args);
+    final process = await startDartProcess(sdk, buildArgs);
     routeToStdout(process);
     return process.exitCode;
   }
@@ -205,24 +207,24 @@
   final String help;
 
   CompileNativeCommand({
-    this.commandName,
-    this.format,
-    this.help,
-    bool verbose,
+    required this.commandName,
+    required this.format,
+    required this.help,
+    bool verbose = false,
   }) : super(commandName, 'Compile Dart $help', verbose) {
     argParser
       ..addOption(
-        commonOptions['outputFile'].flag,
-        help: commonOptions['outputFile'].help,
-        abbr: commonOptions['outputFile'].abbr,
+        commonOptions['outputFile']!.flag,
+        help: commonOptions['outputFile']!.help,
+        abbr: commonOptions['outputFile']!.abbr,
       )
       ..addOption(
-        commonOptions['verbosity'].flag,
-        help: commonOptions['verbosity'].help,
-        abbr: commonOptions['verbosity'].abbr,
-        defaultsTo: commonOptions['verbosity'].defaultsTo,
-        allowed: commonOptions['verbosity'].allowed,
-        allowedHelp: commonOptions['verbosity'].allowedHelp,
+        commonOptions['verbosity']!.flag,
+        help: commonOptions['verbosity']!.help,
+        abbr: commonOptions['verbosity']!.abbr,
+        defaultsTo: commonOptions['verbosity']!.defaultsTo,
+        allowed: commonOptions['verbosity']!.allowed,
+        allowedHelp: commonOptions['verbosity']!.allowedHelp,
       )
       ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
 Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
@@ -268,13 +270,14 @@
           "'dart compile $format' is not supported on x86 architectures");
       return 64;
     }
+    final args = argResults!;
+
     // We expect a single rest argument; the dart entry point.
-    if (argResults.rest.length != 1) {
+    if (args.rest.length != 1) {
       // This throws.
       usageException('Missing Dart entry point.');
     }
-
-    final String sourcePath = argResults.rest[0];
+    final String sourcePath = args.rest[0];
     if (!checkFile(sourcePath)) {
       return -1;
     }
@@ -283,16 +286,16 @@
       await generateNative(
         kind: format,
         sourceFile: sourcePath,
-        outputFile: argResults['output'],
-        defines: argResults['define'],
-        packages: argResults['packages'],
-        enableAsserts: argResults['enable-asserts'],
-        enableExperiment: argResults.enabledExperiments.join(','),
-        soundNullSafety: argResults['sound-null-safety'],
-        debugFile: argResults['save-debugging-info'],
+        outputFile: args['output'],
+        defines: args['define'],
+        packages: args['packages'],
+        enableAsserts: args['enable-asserts'],
+        enableExperiment: args.enabledExperiments.join(','),
+        soundNullSafety: args['sound-null-safety'],
+        debugFile: args['save-debugging-info'],
         verbose: verbose,
-        verbosity: argResults['verbosity'],
-        extraOptions: argResults['extra-gen-snapshot-options'],
+        verbosity: args['verbosity'],
+        extraOptions: args['extra-gen-snapshot-options'],
       );
       return 0;
     } catch (e) {
diff --git a/pkg/dartdev/lib/src/commands/create.dart b/pkg/dartdev/lib/src/commands/create.dart
index 9819614..8d20bee 100644
--- a/pkg/dartdev/lib/src/commands/create.dart
+++ b/pkg/dartdev/lib/src/commands/create.dart
@@ -54,22 +54,23 @@
 
   @override
   FutureOr<int> run() async {
-    if (argResults['list-templates']) {
+    final args = argResults!;
+    if (args['list-templates']) {
       log.stdout(_availableTemplatesJson());
       return 0;
     }
 
-    if (argResults.rest.isEmpty) {
+    if (args.rest.isEmpty) {
       printUsage();
       return 1;
     }
 
-    String templateId = argResults['template'];
+    String templateId = args['template'];
 
-    String dir = argResults.rest.first;
+    String dir = args.rest.first;
     var targetDir = io.Directory(dir).absolute;
     dir = targetDir.path;
-    if (targetDir.existsSync() && !argResults['force']) {
+    if (targetDir.existsSync() && !args['force']) {
       log.stderr(
         "Directory '$dir' already exists "
         "(use '--force' to force project generation).",
@@ -95,13 +96,13 @@
     );
     log.stdout('');
 
-    var generator = getGenerator(templateId);
+    var generator = getGenerator(templateId)!;
     generator.generate(
       projectName,
       DirectoryGeneratorTarget(generator, io.Directory(dir)),
     );
 
-    if (argResults['pub']) {
+    if (args['pub']) {
       log.stdout('');
       var progress = log.progress('Running pub get');
       var process = await startDartProcess(
@@ -137,7 +138,7 @@
     log.stdout('');
     log.stdout(generator.getInstallInstructions(
       dir,
-      projectName,
+      scriptPath: projectName,
     ));
     log.stdout('');
 
@@ -164,7 +165,7 @@
       };
 
       if (generator.entrypoint != null) {
-        m['entrypoint'] = generator.entrypoint.path;
+        m['entrypoint'] = generator.entrypoint!.path;
       }
 
       return m;
diff --git a/pkg/dartdev/lib/src/commands/debug_adapter.dart b/pkg/dartdev/lib/src/commands/debug_adapter.dart
index e1a87b5..817f91b 100644
--- a/pkg/dartdev/lib/src/commands/debug_adapter.dart
+++ b/pkg/dartdev/lib/src/commands/debug_adapter.dart
@@ -53,7 +53,7 @@
 
   @override
   FutureOr<int> run() async {
-    final args = argResults;
+    final args = argResults!;
     final ipv6 = args[argIpv6] as bool;
 
     final server = DapServer(
diff --git a/pkg/dartdev/lib/src/commands/devtools.dart b/pkg/dartdev/lib/src/commands/devtools.dart
new file mode 100644
index 0000000..63ff69c
--- /dev/null
+++ b/pkg/dartdev/lib/src/commands/devtools.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/args.dart';
+import 'package:dds/devtools_server.dart';
+import 'package:dds/src/devtools/utils.dart';
+import 'package:path/path.dart' as path;
+
+import '../core.dart';
+import '../sdk.dart';
+
+class DevToolsCommand extends DartdevCommand {
+  DevToolsCommand({
+    this.customDevToolsPath,
+    bool verbose = false,
+  })  : _argParser = DevToolsServer.buildArgParser(verbose: verbose),
+        super(
+          'devtools',
+          DevToolsServer.commandDescription,
+          verbose,
+        );
+
+  final String? customDevToolsPath;
+
+  @override
+  ArgParser get argParser => _argParser;
+  late final ArgParser _argParser;
+
+  @override
+  String get name => 'devtools';
+
+  @override
+  String get description => DevToolsServer.commandDescription;
+
+  @override
+  String get invocation => '${super.invocation} [service protocol uri]';
+
+  @override
+  Future<int> run() async {
+    final args = argResults!;
+    final bool version = args[DevToolsServer.argVersion];
+    final bool machineMode = args[DevToolsServer.argMachine];
+    // launchBrowser defaults based on machine-mode if not explicitly supplied.
+    final bool launchBrowser = args.wasParsed(DevToolsServer.argLaunchBrowser)
+        ? args[DevToolsServer.argLaunchBrowser]
+        : !machineMode;
+    final bool enableNotifications =
+        args[DevToolsServer.argEnableNotifications];
+    final bool allowEmbedding = args.wasParsed(DevToolsServer.argAllowEmbedding)
+        ? args[DevToolsServer.argAllowEmbedding]
+        : true;
+
+    final port = args[DevToolsServer.argPort] != null
+        ? int.tryParse(args[DevToolsServer.argPort]) ?? 0
+        : 0;
+
+    final bool headlessMode = args[DevToolsServer.argHeadlessMode];
+    final bool debugMode = args[DevToolsServer.argDebugMode];
+
+    final numPortsToTry = args[DevToolsServer.argTryPorts] != null
+        ? int.tryParse(args[DevToolsServer.argTryPorts]) ?? 0
+        : DevToolsServer.defaultTryPorts;
+
+    final bool verboseMode = args[DevToolsServer.argVerbose];
+    final String? hostname = args[DevToolsServer.argHost];
+    final String? appSizeBase = args[DevToolsServer.argAppSizeBase];
+    final String? appSizeTest = args[DevToolsServer.argAppSizeTest];
+
+    final sdkDir = path.dirname(sdk.dart);
+    final fullSdk = sdkDir.endsWith('bin');
+    final devToolsBinaries =
+        fullSdk ? sdk.devToolsBinaries : path.absolute(sdkDir, 'devtools');
+
+    if (version) {
+      final versionStr = await DevToolsUtils.getVersion(devToolsBinaries);
+      DevToolsUtils.printOutput(
+        'Dart DevTools version $versionStr',
+        {
+          'version': versionStr,
+        },
+        machineMode: machineMode,
+      );
+      return 0;
+    }
+
+    // Prefer getting the VM URI from the rest args; fall back on the 'vm-url'
+    // option otherwise.
+    String? serviceProtocolUri;
+    if (args.rest.isNotEmpty) {
+      serviceProtocolUri = args.rest.first;
+    } else if (args.wasParsed(DevToolsServer.argVmUri)) {
+      serviceProtocolUri = args[DevToolsServer.argVmUri];
+    }
+
+    // Support collecting profile data.
+    String? profileFilename;
+    if (args.wasParsed(DevToolsServer.argProfileMemory)) {
+      profileFilename = args[DevToolsServer.argProfileMemory];
+    }
+    if (profileFilename != null && !path.isAbsolute(profileFilename)) {
+      profileFilename = path.absolute(profileFilename);
+    }
+
+    final server = await DevToolsServer().serveDevTools(
+      machineMode: machineMode,
+      debugMode: debugMode,
+      launchBrowser: launchBrowser,
+      enableNotifications: enableNotifications,
+      allowEmbedding: allowEmbedding,
+      port: port,
+      headlessMode: headlessMode,
+      numPortsToTry: numPortsToTry,
+      customDevToolsPath: customDevToolsPath ?? devToolsBinaries,
+      serviceProtocolUri: serviceProtocolUri,
+      profileFilename: profileFilename,
+      verboseMode: verboseMode,
+      hostname: hostname,
+      appSizeBase: appSizeBase,
+      appSizeTest: appSizeTest,
+    );
+
+    return server == null ? -1 : 0;
+  }
+}
diff --git a/pkg/dartdev/lib/src/commands/doc.dart b/pkg/dartdev/lib/src/commands/doc.dart
index d039183..11e1df7 100644
--- a/pkg/dartdev/lib/src/commands/doc.dart
+++ b/pkg/dartdev/lib/src/commands/doc.dart
@@ -12,27 +12,45 @@
 import '../core.dart';
 import '../sdk.dart';
 
-/// A command to create a new project from a set of templates.
+/// A command to generate documentation for a project.
 class DocCommand extends DartdevCommand {
   static const String cmdName = 'doc';
 
-  DocCommand({bool verbose = false})
-      : super(
-          cmdName,
-          'Generate HTML API documentation from Dart documentation comments.',
-          verbose,
-        ) {
+  static const String cmdDescription = '''
+Generate API documentation for Dart projects.
+
+For additional documentation generation options, see the 'dartdoc_options.yaml' file documentation at https://dart.dev/go/dartdoc-options-file.''';
+
+  DocCommand({bool verbose = false}) : super(cmdName, cmdDescription, verbose) {
     argParser.addOption(
-      'output-dir',
+      'output',
       abbr: 'o',
-      defaultsTo: path.join('.', 'doc', 'api'),
-      help: 'Output directory',
+      valueHelp: 'directory',
+      defaultsTo: path.join('doc', 'api'),
+      aliases: [
+        // The CLI option that shipped with Dart 2.16.
+        'output-dir',
+      ],
+      help: 'Configure the output directory.',
     );
     argParser.addFlag(
       'validate-links',
-      negatable: true,
-      help: 'Display context aware warnings for broken links (slow)',
+      negatable: false,
+      help: 'Display warnings for broken links.',
     );
+    argParser.addFlag(
+      'sdk-docs',
+      hide: true,
+      negatable: false,
+      help: 'Generate API docs for the Dart SDK.',
+    );
+    argParser.addFlag(
+      'dry-run',
+      negatable: false,
+      help: 'Try to generate the docs without saving them.',
+    );
+    argParser.addFlag('fatal-warnings',
+        help: 'Treat warning level issues as fatal.', defaultsTo: false);
   }
 
   @override
@@ -40,32 +58,38 @@
 
   @override
   FutureOr<int> run() async {
-    // At least one argument, the input directory, is required.
-    if (argResults.rest.isEmpty) {
-      usageException("Error: Input directory not specified");
-    }
+    final options = <String>[];
+    final args = argResults!;
 
-    // Determine input directory.
-    final dir = io.Directory(argResults.rest[0]);
-    if (!dir.existsSync()) {
-      usageException("Error: Input directory doesn't exist: ${dir.path}");
-    }
-
-    // Parse options.
-    final options = [
-      '--input=${dir.path}',
-      '--output=${argResults['output-dir']}',
-    ];
-    if (argResults['validate-links']) {
-      options.add('--validate-links');
+    if (args['sdk-docs']) {
+      options.add('--sdk-docs');
     } else {
-      options.add('--no-validate-links');
+      // At least one argument, the input directory, is required,
+      // when we're not generating docs for the Dart SDK.
+      if (args.rest.isEmpty) {
+        usageException("Error: Input directory not specified");
+      }
+
+      // Determine input directory.
+      final dir = io.Directory(args.rest[0]);
+      if (!dir.existsSync()) {
+        usageException("Error: Input directory doesn't exist: ${dir.path}");
+      }
+      options.add('--input=${dir.path}');
     }
 
     // Specify where dartdoc resources are located.
     final resourcesPath =
         path.absolute(sdk.sdkPath, 'bin', 'resources', 'dartdoc', 'resources');
-    options.add('--resources-dir=$resourcesPath');
+
+    // Build remaining options.
+    options.addAll([
+      '--output=${args['output']}',
+      '--resources-dir=$resourcesPath',
+      if (args['validate-links']) '--validate-links',
+      if (args['dry-run']) '--no-generate-docs',
+      if (verbose) '--no-quiet',
+    ]);
 
     final config = await parseOptions(pubPackageMetaProvider, options);
     if (config == null) {
@@ -73,9 +97,9 @@
       return 2;
     }
 
-    // Call dartdoc.
+    // Call into package:dartdoc.
     if (verbose) {
-      log.stdout('Calling dartdoc with the following options: $options');
+      log.stdout('Using the following options: $options');
     }
     final packageConfigProvider = PhysicalPackageConfigProvider();
     final packageBuilder = PubPackageBuilder(
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index 1bdb252..8fd6db9 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -6,7 +6,7 @@
 import 'dart:io' as io;
 
 import 'package:analysis_server_client/protocol.dart' hide AnalysisError;
-import 'package:meta/meta.dart';
+import 'package:cli_util/cli_logging.dart' show Progress;
 import 'package:path/path.dart' as path;
 
 import '../analysis_server.dart';
@@ -54,7 +54,7 @@
 
   @override
   String get description {
-    if (log != null && log.ansi.useAnsi) {
+    if (log.ansi.useAnsi) {
       return cmdDescription
           .replaceAll('[', log.ansi.bold)
           .replaceAll(']', log.ansi.none);
@@ -65,15 +65,16 @@
 
   @override
   FutureOr<int> run() async {
-    var dryRun = argResults['dry-run'];
-    var inTestMode = argResults['compare-to-golden'];
-    var apply = argResults['apply'];
+    final args = argResults!;
+    var dryRun = args['dry-run'];
+    var inTestMode = args['compare-to-golden'];
+    var apply = args['apply'];
     if (!apply && !dryRun && !inTestMode) {
       printUsage();
       return 0;
     }
 
-    var arguments = argResults.rest;
+    var arguments = args.rest;
     var argumentCount = arguments.length;
     if (argumentCount > 1) {
       usageException('Only one file or directory is expected.');
@@ -90,7 +91,7 @@
     var modeText = dryRun ? ' (dry run)' : '';
 
     final projectName = path.basename(dirPath);
-    var computeFixesProgress = log.progress(
+    Progress? computeFixesProgress = log.progress(
         'Computing fixes in ${log.ansi.emphasized(projectName)}$modeText');
 
     var server = AnalysisServer(
@@ -131,7 +132,7 @@
     await server.shutdown();
 
     if (computeFixesProgress != null) {
-      computeFixesProgress.finish(showTiming: true);
+      computeFixesProgress!.finish(showTiming: true);
       computeFixesProgress = null;
     }
 
@@ -145,7 +146,8 @@
       var fileCount = detailsMap.length;
       var fixCount = detailsMap.values
           .expand((detail) => detail.fixes)
-          .fold(0, (previousValue, fixes) => previousValue + fixes.occurrences);
+          .fold<int>(0,
+              (int previousValue, fixes) => previousValue + fixes.occurrences);
 
       if (dryRun) {
         log.stdout('');
@@ -221,7 +223,7 @@
         var actualIsOriginal = !fileContentCache.containsKey(filePath);
         var actualCode = actualIsOriginal
             ? originalFile.readAsStringSync()
-            : fileContentCache[filePath];
+            : fileContentCache[filePath]!;
         // Use a whitespace insensitive comparison.
         if (_compressWhitespace(actualCode) !=
             _compressWhitespace(expectedCode)) {
@@ -305,7 +307,7 @@
     modifiedFilePaths
         .sort((first, second) => relative(first).compareTo(relative(second)));
     for (var filePath in modifiedFilePaths) {
-      var detail = detailsMap[filePath];
+      var detail = detailsMap[filePath]!;
       log.stdout(relative(detail.path));
       final fixes = detail.fixes.toList();
       fixes.sort((a, b) => a.code.compareTo(b.code));
@@ -320,7 +322,7 @@
   /// Report that the [actualCode] produced by applying fixes to the content of
   /// [filePath] did not match the [expectedCode].
   void _reportFailure(String filePath, String actualCode, String expectedCode,
-      {@required bool actualIsOriginal}) {
+      {required bool actualIsOriginal}) {
     log.stdout('Failed when applying fixes to $filePath');
     log.stdout('Expected:');
     log.stdout(expectedCode);
diff --git a/pkg/dartdev/lib/src/commands/language_server.dart b/pkg/dartdev/lib/src/commands/language_server.dart
index 6de3df3..65eca06 100644
--- a/pkg/dartdev/lib/src/commands/language_server.dart
+++ b/pkg/dartdev/lib/src/commands/language_server.dart
@@ -40,7 +40,7 @@
   Future<int> run() async {
     final driver = server_driver.Driver();
     driver.start(
-      argResults.arguments,
+      argResults!.arguments,
       defaultToLsp: true,
     );
 
diff --git a/pkg/dartdev/lib/src/commands/migrate.dart b/pkg/dartdev/lib/src/commands/migrate.dart
index cb83e82..5064326 100644
--- a/pkg/dartdev/lib/src/commands/migrate.dart
+++ b/pkg/dartdev/lib/src/commands/migrate.dart
@@ -34,7 +34,7 @@
   FutureOr<int> run() async {
     var cli = MigrationCli(binaryName: 'dart $name');
     try {
-      await cli.decodeCommandLineArgs(argResults, isVerbose: verbose)?.run();
+      await cli.decodeCommandLineArgs(argResults!, isVerbose: verbose)?.run();
     } on MigrationExit catch (migrationExit) {
       return migrationExit.exitCode;
     }
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index a74fa84..ea0ce59 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -20,6 +20,7 @@
 import '../vm_interop_handler.dart';
 
 class RunCommand extends DartdevCommand {
+  static const bool isProductMode = bool.fromEnvironment("dart.vm.product");
   static const String cmdName = 'run';
 
   // kErrorExitCode, as defined in runtime/bin/error_exit.h
@@ -47,97 +48,103 @@
     // the list of flags in Options::ProcessVMDebuggingOptions in
     // runtime/bin/main_options.cc. Failure to do so will result in those VM
     // options being ignored.
-    argParser
-      ..addSeparator(
-        'Debugging options:',
-      )
-      ..addOption(
-        'observe',
-        help: 'The observe flag is a convenience flag used to run a program '
-            'with a set of common options useful for debugging.',
-        valueHelp: '[<port>[/<bind-address>]]',
-      )
-      ..addOption('launch-dds', hide: true, help: 'Launch DDS.')
-      ..addSeparator(
-        'Options implied by --observe are currently:',
-      )
-      ..addOption(
-        'enable-vm-service',
-        help: 'Enables the VM service and listens on the specified port for '
-            'connections (default port number is 8181, default bind address '
-            'is localhost).',
-        valueHelp: '[<port>[/<bind-address>]]',
-      )
-      ..addFlag(
-        'serve-devtools',
-        help: 'Serves an instance of the Dart DevTools debugger and profiler '
-            'via the VM service at <vm-service-uri>/devtools.',
-        defaultsTo: true,
-      )
-      ..addFlag(
-        'pause-isolates-on-exit',
-        help: 'Pause isolates on exit when '
-            'running with --enable-vm-service.',
-      )
-      ..addFlag(
-        'pause-isolates-on-unhandled-exceptions',
-        help: 'Pause isolates when an unhandled exception is encountered '
-            'when running with --enable-vm-service.',
-      )
-      ..addFlag(
-        'warn-on-pause-with-no-debugger',
-        help: 'Print a warning when an isolate pauses with no attached debugger'
-            ' when running with --enable-vm-service.',
-      )
-      ..addSeparator(
-        'Other debugging options:',
-      )
-      ..addFlag(
-        'pause-isolates-on-start',
-        help: 'Pause isolates on start when '
-            'running with --enable-vm-service.',
-      )
-      ..addFlag(
-        'enable-asserts',
-        help: 'Enable assert statements.',
-      )
-      ..addOption(
-        'verbosity',
-        help: 'Sets the verbosity level of the compilation.',
-        defaultsTo: Verbosity.defaultValue,
-        allowed: Verbosity.allowedValues,
-        allowedHelp: Verbosity.allowedValuesHelp,
-      );
+    argParser.addSeparator(
+      'Debugging options:',
+    );
+    if (!isProductMode) {
+      argParser
+        ..addOption(
+          'observe',
+          help: 'The observe flag is a convenience flag used to run a program '
+              'with a set of common options useful for debugging.',
+          valueHelp: '[<port>[/<bind-address>]]',
+        )
+        ..addOption('launch-dds', hide: true, help: 'Launch DDS.')
+        ..addSeparator(
+          'Options implied by --observe are currently:',
+        )
+        ..addOption(
+          'enable-vm-service',
+          help: 'Enables the VM service and listens on the specified port for '
+              'connections (default port number is 8181, default bind address '
+              'is localhost).',
+          valueHelp: '[<port>[/<bind-address>]]',
+        )
+        ..addFlag(
+          'serve-devtools',
+          help: 'Serves an instance of the Dart DevTools debugger and profiler '
+              'via the VM service at <vm-service-uri>/devtools.',
+          defaultsTo: true,
+        )
+        ..addFlag(
+          'pause-isolates-on-exit',
+          help: 'Pause isolates on exit when '
+              'running with --enable-vm-service.',
+        )
+        ..addFlag(
+          'pause-isolates-on-unhandled-exceptions',
+          help: 'Pause isolates when an unhandled exception is encountered '
+              'when running with --enable-vm-service.',
+        )
+        ..addFlag(
+          'warn-on-pause-with-no-debugger',
+          help:
+              'Print a warning when an isolate pauses with no attached debugger'
+              ' when running with --enable-vm-service.',
+        )
+        ..addSeparator(
+          'Other debugging options:',
+        )
+        ..addFlag(
+          'pause-isolates-on-start',
+          help: 'Pause isolates on start when '
+              'running with --enable-vm-service.',
+        )
+        ..addFlag(
+          'enable-asserts',
+          help: 'Enable assert statements.',
+        );
+    }
+    argParser.addOption(
+      'verbosity',
+      help: 'Sets the verbosity level of the compilation.',
+      defaultsTo: Verbosity.defaultValue,
+      allowed: Verbosity.allowedValues,
+      allowedHelp: Verbosity.allowedValuesHelp,
+    );
 
     if (verbose) {
       argParser.addSeparator(
         'Advanced options:',
       );
     }
+    argParser.addMultiOption(
+      'define',
+      abbr: 'D',
+      valueHelp: 'key=value',
+      help: 'Define an environment declaration.',
+    );
+    if (!isProductMode) {
+      argParser
+        ..addFlag(
+          'disable-service-auth-codes',
+          hide: !verbose,
+          negatable: false,
+          help: 'Disables the requirement for an authentication code to '
+              'communicate with the VM service. Authentication codes help '
+              'protect against CSRF attacks, so it is not recommended to '
+              'disable them unless behind a firewall on a secure device.',
+        )
+        ..addFlag(
+          'enable-service-port-fallback',
+          hide: !verbose,
+          negatable: false,
+          help: 'When the VM service is told to bind to a particular port, '
+              'fallback to 0 if it fails to bind instread of failing to '
+              'start.',
+        );
+    }
     argParser
-      ..addMultiOption(
-        'define',
-        abbr: 'D',
-        valueHelp: 'key=value',
-        help: 'Define an environment declaration.',
-      )
-      ..addFlag(
-        'disable-service-auth-codes',
-        hide: !verbose,
-        negatable: false,
-        help: 'Disables the requirement for an authentication code to '
-            'communicate with the VM service. Authentication codes help '
-            'protect against CSRF attacks, so it is not recommended to '
-            'disable them unless behind a firewall on a secure device.',
-      )
-      ..addFlag(
-        'enable-service-port-fallback',
-        hide: !verbose,
-        negatable: false,
-        help: 'When the VM service is told to bind to a particular port, '
-            'fallback to 0 if it fails to bind instread of failing to '
-            'start.',
-      )
       ..addOption(
         'namespace',
         hide: !verbose,
@@ -164,17 +171,22 @@
         hide: !verbose,
         negatable: false,
         help: 'Enables tracing of library and script loading.',
-      )
-      ..addFlag('dds',
-          hide: !verbose,
-          help: 'Use the Dart Development Service (DDS) for enhanced debugging '
-              'functionality. Note: Disabling DDS may break some functionality '
-              'in IDEs and other tooling.',
-          defaultsTo: true)
-      ..addFlag(
-        'debug-dds',
-        hide: true,
       );
+
+    if (!isProductMode) {
+      argParser
+        ..addFlag('dds',
+            hide: !verbose,
+            help:
+                'Use the Dart Development Service (DDS) for enhanced debugging '
+                'functionality. Note: Disabling DDS may break some functionality '
+                'in IDEs and other tooling.',
+            defaultsTo: true)
+        ..addFlag(
+          'debug-dds',
+          hide: true,
+        );
+    }
     addExperimentalFlags(argParser, verbose);
   }
 
@@ -184,47 +196,50 @@
 
   @override
   FutureOr<int> run() async {
+    final args = argResults!;
     var mainCommand = '';
     var runArgs = <String>[];
-    if (argResults.rest.isNotEmpty) {
-      mainCommand = argResults.rest.first;
+    if (args.rest.isNotEmpty) {
+      mainCommand = args.rest.first;
       // The command line arguments after the command name.
-      runArgs = argResults.rest.skip(1).toList();
+      runArgs = args.rest.skip(1).toList();
     }
-    // --launch-dds is provided by the VM if the VM service is to be enabled. In
-    // that case, we need to launch DDS as well.
-    String launchDdsArg = argResults['launch-dds'];
-    String ddsHost = '';
-    String ddsPort = '';
+    if (!isProductMode) {
+      // --launch-dds is provided by the VM if the VM service is to be enabled. In
+      // that case, we need to launch DDS as well.
+      String? launchDdsArg = args['launch-dds'];
+      String ddsHost = '';
+      String ddsPort = '';
 
-    bool launchDevTools = argResults['serve-devtools'];
-    bool launchDds = false;
-    if (launchDdsArg != null) {
-      launchDds = true;
-      final ddsUrl = launchDdsArg.split('\\:');
-      ddsHost = ddsUrl[0];
-      ddsPort = ddsUrl[1];
-    }
-    final bool debugDds = argResults['debug-dds'];
+      bool launchDevTools = args['serve-devtools'] ?? false;
+      bool launchDds = false;
+      if (launchDdsArg != null) {
+        launchDds = true;
+        final ddsUrl = launchDdsArg.split('\\:');
+        ddsHost = ddsUrl[0];
+        ddsPort = ddsUrl[1];
+      }
+      final bool debugDds = args['debug-dds'];
 
-    bool disableServiceAuthCodes = argResults['disable-service-auth-codes'];
+      bool disableServiceAuthCodes = args['disable-service-auth-codes'];
 
-    // If the user wants to start a debugging session we need to do some extra
-    // work and spawn a Dart Development Service (DDS) instance. DDS is a VM
-    // service intermediary which implements the VM service protocol and
-    // provides non-VM specific extensions (e.g., log caching, client
-    // synchronization).
-    _DebuggingSession debugSession;
-    if (launchDds) {
-      debugSession = _DebuggingSession();
-      if (!await debugSession.start(
-        ddsHost,
-        ddsPort,
-        disableServiceAuthCodes,
-        launchDevTools,
-        debugDds,
-      )) {
-        return errorExitCode;
+      // If the user wants to start a debugging session we need to do some extra
+      // work and spawn a Dart Development Service (DDS) instance. DDS is a VM
+      // service intermediary which implements the VM service protocol and
+      // provides non-VM specific extensions (e.g., log caching, client
+      // synchronization).
+      _DebuggingSession debugSession;
+      if (launchDds) {
+        debugSession = _DebuggingSession();
+        if (!await debugSession.start(
+          ddsHost,
+          ddsPort,
+          disableServiceAuthCodes,
+          launchDevTools,
+          debugDds,
+        )) {
+          return errorExitCode;
+        }
       }
     }
 
@@ -295,7 +310,7 @@
     const devToolsMessagePrefix =
         'The Dart DevTools debugger and profiler is available at:';
     if (debugDds) {
-      StreamSubscription stdoutSub;
+      late StreamSubscription stdoutSub;
       stdoutSub = process.stdout.transform(utf8.decoder).listen((event) {
         if (event.startsWith(devToolsMessagePrefix)) {
           final ddsDebuggingUri = event.split(' ').last;
@@ -306,7 +321,7 @@
         }
       });
     }
-    StreamSubscription stderrSub;
+    late StreamSubscription stderrSub;
     stderrSub = process.stderr.transform(utf8.decoder).listen((event) {
       final result = json.decode(event) as Map<String, dynamic>;
       final state = result['state'];
@@ -318,11 +333,16 @@
         stderrSub.cancel();
         completer.complete();
       } else {
+        stderrSub.cancel();
         final error = result['error'] ?? event;
         final stacktrace = result['stacktrace'] ?? '';
-        stderrSub.cancel();
-        completer.completeError(
-            'Could not start Observatory HTTP server:\n$error\n$stacktrace\n');
+        String message = 'Could not start the VM service: ';
+        if (error.contains('Failed to create server socket')) {
+          message += '$host:$port is already in use.\n';
+        } else {
+          message += '$error\n$stacktrace\n';
+        }
+        completer.completeError(message);
       }
     });
     try {
diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart
index 36683af..31d7916 100644
--- a/pkg/dartdev/lib/src/commands/test.dart
+++ b/pkg/dartdev/lib/src/commands/test.dart
@@ -28,11 +28,12 @@
 
   @override
   FutureOr<int> run() async {
+    final args = argResults!;
     try {
       final testExecutable = await getExecutableForCommand('test:test');
-      log.trace('dart $testExecutable ${argResults.rest.join(' ')}');
-      VmInteropHandler.run(testExecutable.executable, argResults.rest,
-          packageConfigOverride: testExecutable.packageConfig);
+      log.trace('dart $testExecutable ${args.rest.join(' ')}');
+      VmInteropHandler.run(testExecutable.executable, args.rest,
+          packageConfigOverride: testExecutable.packageConfig!);
       return 0;
     } on CommandResolutionFailedException catch (e) {
       if (project.hasPubspecFile) {
@@ -45,8 +46,7 @@
         print(
             'No pubspec.yaml file found - run this command in your project folder.');
       }
-      if (argResults.rest.contains('-h') ||
-          argResults.rest.contains('--help')) {
+      if (args.rest.contains('-h') || args.rest.contains('--help')) {
         print('');
         printUsage();
       }
diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart
index 3f4b340..439bdfd 100644
--- a/pkg/dartdev/lib/src/core.dart
+++ b/pkg/dartdev/lib/src/core.dart
@@ -15,19 +15,19 @@
 import 'sdk.dart';
 import 'utils.dart';
 
-Logger log;
+late Logger log;
 bool isDiagnostics = false;
 
 /// When set, this function is executed from the [DartdevCommand] constructor to
 /// contribute additional flags.
-void Function(ArgParser argParser, String cmdName) flagContributor;
+void Function(ArgParser argParser, String cmdName)? flagContributor;
 
 abstract class DartdevCommand extends Command<int> {
   final String _name;
   final String _description;
   final bool _verbose;
 
-  Project _project;
+  Project? _project;
 
   @override
   final bool hidden;
@@ -43,7 +43,7 @@
   @override
   String get description => _description;
 
-  ArgParser _argParser;
+  ArgParser? _argParser;
 
   @override
   ArgParser get argParser => _argParser ??= createArgParser();
@@ -70,16 +70,16 @@
 
 extension DartDevCommand on Command {
   /// Return whether commands should emit verbose output.
-  bool get verbose => globalResults['verbose'];
+  bool get verbose => globalResults!['verbose'];
 
   /// Return whether the tool should emit diagnostic output.
-  bool get diagnosticsEnabled => globalResults['diagnostics'];
+  bool get diagnosticsEnabled => globalResults!['diagnostics'];
 
   /// Return whether any Dart experiments were specified by the user.
   bool get wereExperimentsSpecified =>
       globalResults?.wasParsed(experimentFlagName) ?? false;
 
-  List<String> get specifiedExperiments => globalResults[experimentFlagName];
+  List<String> get specifiedExperiments => globalResults![experimentFlagName];
 }
 
 /// A utility method to start a Dart VM instance with the given arguments and an
@@ -89,7 +89,7 @@
 Future<Process> startDartProcess(
   Sdk sdk,
   List<String> arguments, {
-  String cwd,
+  String? cwd,
 }) {
   log.trace('${sdk.dart} ${arguments.join(' ')}');
   return Process.start(sdk.dart, arguments, workingDirectory: cwd);
@@ -98,7 +98,7 @@
 void routeToStdout(
   Process process, {
   bool logToTrace = false,
-  void Function(String str) listener,
+  void Function(String str)? listener,
 }) {
   if (isDiagnostics) {
     _streamLineTransform(process.stdout, (String line) {
@@ -136,7 +136,7 @@
 class Project {
   final Directory dir;
 
-  PackageConfig _packageConfig;
+  PackageConfig? _packageConfig;
 
   Project() : dir = Directory.current;
 
@@ -147,7 +147,7 @@
 
   bool get hasPackageConfigFile => packageConfig != null;
 
-  PackageConfig get packageConfig {
+  PackageConfig? get packageConfig {
     if (_packageConfig == null) {
       File file =
           File(path.join(dir.path, '.dart_tool', 'package_config.json'));
@@ -170,11 +170,11 @@
 
   PackageConfig(this.contents);
 
-  List<Map<String, dynamic>> get packages {
+  List<Map<String, dynamic>?> get packages {
     List<dynamic> _packages = contents['packages'];
-    return _packages.map<Map<String, dynamic>>(castStringKeyedMap).toList();
+    return _packages.map<Map<String, dynamic>?>(castStringKeyedMap).toList();
   }
 
   bool hasDependency(String packageName) =>
-      packages.any((element) => element['name'] == packageName);
+      packages.any((element) => element!['name'] == packageName);
 }
diff --git a/pkg/dartdev/lib/src/events.dart b/pkg/dartdev/lib/src/events.dart
index 65469c0..d2dad35 100644
--- a/pkg/dartdev/lib/src/events.dart
+++ b/pkg/dartdev/lib/src/events.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:meta/meta.dart';
 import 'package:usage/usage.dart';
 
 /// The [String] identifier `dartdev`, used as the category in the events sent
@@ -54,17 +53,16 @@
 Future<void> sendUsageEvent(
   Analytics analytics,
   String action, {
-  String label,
-  List<String> specifiedExperiments,
-  @required int exitCode,
-  @required List<String> commandFlags,
+  String? label,
+  List<String>? specifiedExperiments,
+  required int? exitCode,
+  required List<String> commandFlags,
 }) {
   /// The category stores the name of this cli tool, 'dartdev'. This matches the
   /// pattern from the flutter cli tool which always passes 'flutter' as the
   /// category.
   final category = _dartdev;
-  commandFlags =
-      commandFlags?.where((e) => e != 'enable-experiment')?.toList() ?? [];
+  commandFlags = commandFlags.where((e) => e != 'enable-experiment').toList();
   specifiedExperiments = specifiedExperiments?.toList() ?? [];
 
   // Sort the flag lists to slightly reduce the explosion of possibilities.
diff --git a/pkg/dartdev/lib/src/experiments.dart b/pkg/dartdev/lib/src/experiments.dart
index 36d4bd8..70acd2a 100644
--- a/pkg/dartdev/lib/src/experiments.dart
+++ b/pkg/dartdev/lib/src/experiments.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:args/args.dart';
+import 'package:collection/collection.dart' show IterableExtension;
 
 const experimentFlagName = 'enable-experiment';
 
@@ -53,9 +54,8 @@
       // look for --enable-experiment=. Currently, this path is only taken for
       // the pub and test commands, as well as when we are trying to send
       // analytics.
-      final String experiments = arguments.firstWhere(
+      final String? experiments = arguments.firstWhereOrNull(
         (e) => e.startsWith('--enable-experiment='),
-        orElse: () => null,
       );
       if (experiments == null) {
         return [];
diff --git a/pkg/dartdev/lib/src/sdk.dart b/pkg/dartdev/lib/src/sdk.dart
index 2f42de6..57b99c6 100644
--- a/pkg/dartdev/lib/src/sdk.dart
+++ b/pkg/dartdev/lib/src/sdk.dart
@@ -108,7 +108,7 @@
   /// The SDK's release channel (`be`, `dev`, `beta`, `stable`).
   ///
   /// May be null if [Platform.version] does not have the expected format.
-  final String /*?*/ channel;
+  final String? channel;
 
   Runtime._(this.version, this.channel);
 
@@ -116,7 +116,7 @@
     var versionString = Platform.version;
     // Exepcted format: "version (channel) ..."
     var version = versionString;
-    String /*?*/ channel;
+    String? channel;
     var versionEnd = versionString.indexOf(' ');
     if (versionEnd > 0) {
       version = versionString.substring(0, versionEnd);
diff --git a/pkg/dartdev/lib/src/templates.dart b/pkg/dartdev/lib/src/templates.dart
index 3d36844..ee1938a 100644
--- a/pkg/dartdev/lib/src/templates.dart
+++ b/pkg/dartdev/lib/src/templates.dart
@@ -4,6 +4,7 @@
 
 import 'dart:convert' show utf8;
 
+import 'package:collection/collection.dart' show IterableExtension;
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as p;
 
@@ -24,8 +25,8 @@
   WebSimpleGenerator(),
 ];
 
-Generator getGenerator(String id) =>
-    generators.firstWhere((g) => g.id == id, orElse: () => null);
+Generator? getGenerator(String id) =>
+    generators.firstWhereOrNull((g) => g.id == id);
 
 /// An abstract class which both defines a template generator and can generate a
 /// user project based on this template.
@@ -36,12 +37,12 @@
   final List<String> categories;
 
   final List<TemplateFile> files = [];
-  TemplateFile _entrypoint;
+  TemplateFile? _entrypoint;
 
   /// Lazily initialized cache for lower-case if [id].
   ///
   /// Used by [compareTo].
-  String /*?*/ _lowerCaseId;
+  String? _lowerCaseId;
 
   Generator(
     this.id,
@@ -54,7 +55,7 @@
 
   /// The entrypoint of the application; the main file for the project, which an
   /// IDE might open after creating the project.
-  TemplateFile get entrypoint => _entrypoint;
+  TemplateFile? get entrypoint => _entrypoint;
 
   TemplateFile addFile(String path, String contents) {
     return addTemplateFile(TemplateFile(path, contents));
@@ -67,22 +68,21 @@
   }
 
   /// Return the template file wih the given [path].
-  TemplateFile getFile(String path) =>
-      files.firstWhere((file) => file.path == path, orElse: () => null);
+  TemplateFile? getFile(String path) =>
+      files.firstWhereOrNull((file) => file.path == path);
 
   /// Set the main entrypoint of this template. This is the 'most important'
   /// file of this template. An IDE might use this information to open this file
   /// after the user's project is generated.
   void setEntrypoint(TemplateFile entrypoint) {
     if (_entrypoint != null) throw StateError('entrypoint already set');
-    if (entrypoint == null) throw StateError('entrypoint is null');
     _entrypoint = entrypoint;
   }
 
   void generate(
     String projectName,
     GeneratorTarget target, {
-    Map<String, String> additionalVars,
+    Map<String, String>? additionalVars,
   }) {
     final vars = {
       'projectName': projectName,
@@ -111,9 +111,9 @@
   /// (e.g., bin/foo.dart) **without** an extension. If null, the implicit run
   /// command will be output by default (e.g., dart run).
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) {
+    String directory, {
+    String? scriptPath,
+  }) {
     final buffer = StringBuffer();
     buffer.writeln('  cd ${p.relative(directory)}');
     if (scriptPath != null) {
@@ -208,5 +208,5 @@
   }
 
   return str.replaceAllMapped(
-      _substituteRegExp, (match) => vars[match[1]] ?? match[0]);
+      _substituteRegExp, (match) => vars[match[1]!] ?? match[0]!);
 }
diff --git a/pkg/dartdev/lib/src/templates/console_full.dart b/pkg/dartdev/lib/src/templates/console_full.dart
index 553ceeb..d4c2965 100644
--- a/pkg/dartdev/lib/src/templates/console_full.dart
+++ b/pkg/dartdev/lib/src/templates/console_full.dart
@@ -25,10 +25,10 @@
 
   @override
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) =>
-      super.getInstallInstructions(directory, null);
+    String directory, {
+    String? scriptPath,
+  }) =>
+      super.getInstallInstructions(directory);
 }
 
 final String _pubspec = '''
diff --git a/pkg/dartdev/lib/src/templates/console_simple.dart b/pkg/dartdev/lib/src/templates/console_simple.dart
index 5c6d381..ed6f793 100644
--- a/pkg/dartdev/lib/src/templates/console_simple.dart
+++ b/pkg/dartdev/lib/src/templates/console_simple.dart
@@ -17,16 +17,16 @@
     addFile('pubspec.yaml', _pubspec);
     addFile('README.md', _readme);
     setEntrypoint(
-      addFile('bin/__projectName__.dart', main),
+      addFile('bin/__projectName__.dart', mainSrc),
     );
   }
 
   @override
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) =>
-      super.getInstallInstructions(directory, null);
+    String directory, {
+    String? scriptPath,
+  }) =>
+      super.getInstallInstructions(directory);
 }
 
 final String _pubspec = '''
@@ -49,7 +49,7 @@
 A simple command-line application.
 ''';
 
-final String main = '''
+final String mainSrc = '''
 void main(List<String> arguments) {
   print('Hello world!');
 }
diff --git a/pkg/dartdev/lib/src/templates/package_simple.dart b/pkg/dartdev/lib/src/templates/package_simple.dart
index 591f110..9827dd7 100644
--- a/pkg/dartdev/lib/src/templates/package_simple.dart
+++ b/pkg/dartdev/lib/src/templates/package_simple.dart
@@ -26,12 +26,12 @@
 
   @override
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) =>
+    String directory, {
+    String? scriptPath,
+  }) =>
       super.getInstallInstructions(
         directory,
-        'example/${scriptPath}_example',
+        scriptPath: 'example/${scriptPath}_example',
       );
 }
 
diff --git a/pkg/dartdev/lib/src/templates/server_shelf.dart b/pkg/dartdev/lib/src/templates/server_shelf.dart
index ed6b730..c075f02 100644
--- a/pkg/dartdev/lib/src/templates/server_shelf.dart
+++ b/pkg/dartdev/lib/src/templates/server_shelf.dart
@@ -26,12 +26,12 @@
 
   @override
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) =>
+    String directory, {
+    String? scriptPath,
+  }) =>
       super.getInstallInstructions(
         directory,
-        'bin/server',
+        scriptPath: 'bin/server',
       );
 }
 
diff --git a/pkg/dartdev/lib/src/templates/web_simple.dart b/pkg/dartdev/lib/src/templates/web_simple.dart
index 6ea2eb1..e22be74 100644
--- a/pkg/dartdev/lib/src/templates/web_simple.dart
+++ b/pkg/dartdev/lib/src/templates/web_simple.dart
@@ -27,9 +27,9 @@
 
   @override
   String getInstallInstructions(
-    String directory,
-    String scriptPath,
-  ) =>
+    String directory, {
+    String? scriptPath,
+  }) =>
       '  cd ${p.relative(directory)}\n'
       '  dart pub global activate webdev\n'
       '  webdev serve';
diff --git a/pkg/dartdev/lib/src/utils.dart b/pkg/dartdev/lib/src/utils.dart
index c36d6fa..f4c5676 100644
--- a/pkg/dartdev/lib/src/utils.dart
+++ b/pkg/dartdev/lib/src/utils.dart
@@ -8,14 +8,14 @@
 
 /// For commands where we are able to initialize the [ArgParser], this value
 /// is used as the usageLineLength.
-int get dartdevUsageLineLength =>
+int? get dartdevUsageLineLength =>
     stdout.hasTerminal ? stdout.terminalColumns : null;
 
 /// Given a data structure which is a Map of String to dynamic values, return
 /// the same structure (`Map<String, dynamic>`) with the correct runtime types.
 Map<String, dynamic> castStringKeyedMap(dynamic untyped) {
-  final Map<dynamic, dynamic> map = untyped as Map<dynamic, dynamic>;
-  return map?.cast<String, dynamic>();
+  final Map<dynamic, dynamic> map = untyped! as Map<dynamic, dynamic>;
+  return map.cast<String, dynamic>();
 }
 
 /// Emit the given word with the correct pluralization.
@@ -31,7 +31,7 @@
 }
 
 /// String utility to trim some suffix from the end of a [String].
-String trimEnd(String s, String suffix) {
+String? trimEnd(String? s, String? suffix) {
   if (s != null && suffix != null && suffix.isNotEmpty && s.endsWith(suffix)) {
     return s.substring(0, s.length - suffix.length);
   }
@@ -45,7 +45,7 @@
 }
 
 /// Wraps [text] to the given [width], if provided.
-String wrapText(String text, {int width}) {
+String wrapText(String text, {int? width}) {
   if (width == null) {
     return text;
   }
diff --git a/pkg/dartdev/lib/src/vm_interop_handler.dart b/pkg/dartdev/lib/src/vm_interop_handler.dart
index 6ff7bfa..0913a93 100644
--- a/pkg/dartdev/lib/src/vm_interop_handler.dart
+++ b/pkg/dartdev/lib/src/vm_interop_handler.dart
@@ -4,13 +4,11 @@
 
 import 'dart:isolate';
 
-import 'package:meta/meta.dart';
-
 /// Contains methods used to communicate DartDev results back to the VM.
 abstract class VmInteropHandler {
   /// Initializes [VmInteropHandler] to utilize [port] to communicate with the
   /// VM.
-  static void initialize(SendPort port) => _port = port;
+  static void initialize(SendPort? port) => _port = port;
 
   /// Notifies the VM to run [script] with [args] upon DartDev exit.
   ///
@@ -18,10 +16,10 @@
   static void run(
     String script,
     List<String> args, {
-    @required String packageConfigOverride,
+    String? packageConfigOverride,
   }) {
-    assert(_port != null);
-    if (_port == null) return;
+    final port = _port;
+    if (port == null) return;
     final message = <dynamic>[
       _kResultRun,
       script,
@@ -29,21 +27,21 @@
       // Copy the list so it doesn't get GC'd underneath us.
       args.toList()
     ];
-    _port.send(message);
+    port.send(message);
   }
 
   /// Notifies the VM that DartDev has completed running. If provided a
   /// non-zero [exitCode], the VM will terminate with the given exit code.
-  static void exit(int exitCode) {
-    assert(_port != null);
-    if (_port == null) return;
+  static void exit(int? exitCode) {
+    final port = _port;
+    if (port == null) return;
     final message = <dynamic>[_kResultExit, exitCode];
-    _port.send(message);
+    port.send(message);
   }
 
   // Note: keep in sync with runtime/bin/dartdev_isolate.h
   static const int _kResultRun = 1;
   static const int _kResultExit = 2;
 
-  static SendPort _port;
+  static SendPort? _port;
 }
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index 9d78178..51e57b2 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -4,7 +4,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.6.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 dependencies:
   analysis_server:
     path: ../analysis_server
@@ -14,13 +14,13 @@
     path: ../analyzer
   args: any
   cli_util: any
+  collection: any
   dart2native:
     path: ../dart2native
   dart_style: any
   dartdoc: any
   dds:
     path: ../dds
-  devtools_server: any
   front_end:
     path: ../front_end
   meta:
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
index 975eb86..bd24aed 100644
--- a/pkg/dartdev/test/analysis_server_test.dart
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -14,14 +14,14 @@
 
 void main() {
   group('AnalysisServer', () {
-    TestProject p;
+    late TestProject p;
 
     setUp(() {
       log = Logger.standard();
       p = project();
     });
 
-    tearDown(() async => await p?.dispose());
+    tearDown(() async => await p.dispose());
 
     test('can start', () async {
       AnalysisServer server = AnalysisServer(
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index 60bbb1a..04fc049 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -172,7 +172,7 @@
 }
 
 void defineAnalyze() {
-  TestProject p;
+  TestProject? p;
 
   setUp(() => p = null);
 
@@ -180,7 +180,7 @@
 
   test('--help', () async {
     p = project();
-    var result = await p.run(['analyze', '--help']);
+    var result = await p!.run(['analyze', '--help']);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -190,7 +190,7 @@
 
   test('--help --verbose', () async {
     p = project();
-    var result = await p.run(['analyze', '--help', '--verbose']);
+    var result = await p!.run(['analyze', '--help', '--verbose']);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -199,14 +199,15 @@
   });
 
   group('multiple items', () {
-    TestProject secondProject;
+    late TestProject secondProject;
 
-    tearDown(() async => await secondProject?.dispose());
+    tearDown(() async => await secondProject.dispose());
 
     test('folder and file', () async {
       p = project(mainSrc: "int get foo => 'str';\n");
       secondProject = project(mainSrc: "int get foo => 'str';\n");
-      var result = await p.run(['analyze', p.dirPath, secondProject.mainPath]);
+      var result =
+          await p!.run(['analyze', p!.dirPath, secondProject.mainPath]);
 
       expect(result.exitCode, 3);
       expect(result.stderr, isEmpty);
@@ -219,7 +220,7 @@
     test('two folders', () async {
       p = project(mainSrc: "int get foo => 'str';\n");
       secondProject = project(mainSrc: "int get foo => 'str';\n");
-      var result = await p.run(['analyze', p.dirPath, secondProject.dirPath]);
+      var result = await p!.run(['analyze', p!.dirPath, secondProject.dirPath]);
 
       expect(result.exitCode, 3);
       expect(result.stderr, isEmpty);
@@ -232,7 +233,7 @@
 
   test('no such directory', () async {
     p = project();
-    var result = await p.run(['analyze', '/no/such/dir1/']);
+    var result = await p!.run(['analyze', '/no/such/dir1/']);
 
     expect(result.exitCode, 64);
     expect(result.stdout, isEmpty);
@@ -244,7 +245,7 @@
   test('current working directory', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
 
-    var result = await p.run(['analyze'], workingDir: p.dirPath);
+    var result = await p!.run(['analyze'], workingDir: p!.dirPath);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -254,7 +255,7 @@
   group('single directory', () {
     test('no errors', () async {
       p = project(mainSrc: 'int get foo => 1;\n');
-      var result = await p.run(['analyze', p.dirPath]);
+      var result = await p!.run(['analyze', p!.dirPath]);
 
       expect(result.exitCode, 0);
       expect(result.stderr, isEmpty);
@@ -263,7 +264,7 @@
 
     test('one error', () async {
       p = project(mainSrc: "int get foo => 'str';\n");
-      var result = await p.run(['analyze', p.dirPath]);
+      var result = await p!.run(['analyze', p!.dirPath]);
 
       expect(result.exitCode, 3);
       expect(result.stderr, isEmpty);
@@ -275,7 +276,7 @@
 
     test('two errors', () async {
       p = project(mainSrc: "int get foo => 'str';\nint get bar => 'str';\n");
-      var result = await p.run(['analyze', p.dirPath]);
+      var result = await p!.run(['analyze', p!.dirPath]);
 
       expect(result.exitCode, 3);
       expect(result.stderr, isEmpty);
@@ -286,7 +287,7 @@
   group('single file', () {
     test('no errors', () async {
       p = project(mainSrc: 'int get foo => 1;\n');
-      var result = await p.run(['analyze', p.mainPath]);
+      var result = await p!.run(['analyze', p!.mainPath]);
 
       expect(result.exitCode, 0);
       expect(result.stderr, isEmpty);
@@ -295,7 +296,7 @@
 
     test('one error', () async {
       p = project(mainSrc: "int get foo => 'str';\n");
-      var result = await p.run(['analyze', p.mainPath]);
+      var result = await p!.run(['analyze', p!.mainPath]);
 
       expect(result.exitCode, 3);
       expect(result.stderr, isEmpty);
@@ -310,7 +311,7 @@
     p = project(
         mainSrc: _unusedImportCodeSnippet,
         analysisOptions: _unusedImportAnalysisOptions);
-    var result = await p.run(['analyze', '--fatal-warnings', p.dirPath]);
+    var result = await p!.run(['analyze', '--fatal-warnings', p!.dirPath]);
 
     expect(result.exitCode, equals(2));
     expect(result.stderr, isEmpty);
@@ -321,7 +322,7 @@
     p = project(
         mainSrc: _unusedImportCodeSnippet,
         analysisOptions: _unusedImportAnalysisOptions);
-    var result = await p.run(['analyze', p.dirPath]);
+    var result = await p!.run(['analyze', p!.dirPath]);
 
     expect(result.exitCode, equals(2));
     expect(result.stderr, isEmpty);
@@ -332,7 +333,7 @@
     p = project(
         mainSrc: _unusedImportCodeSnippet,
         analysisOptions: _unusedImportAnalysisOptions);
-    var result = await p.run(['analyze', '--no-fatal-warnings', p.dirPath]);
+    var result = await p!.run(['analyze', '--no-fatal-warnings', p!.dirPath]);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -341,7 +342,7 @@
 
   test('info implicit no --fatal-infos', () async {
     p = project(mainSrc: dartVersionFilePrefix2_9 + 'String foo() {}');
-    var result = await p.run(['analyze', p.dirPath]);
+    var result = await p!.run(['analyze', p!.dirPath]);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -350,7 +351,7 @@
 
   test('info --fatal-infos', () async {
     p = project(mainSrc: dartVersionFilePrefix2_9 + 'String foo() {}');
-    var result = await p.run(['analyze', '--fatal-infos', p.dirPath]);
+    var result = await p!.run(['analyze', '--fatal-infos', p!.dirPath]);
 
     expect(result.exitCode, 1);
     expect(result.stderr, isEmpty);
@@ -364,7 +365,7 @@
   var one = 1;
   return result;
 }''');
-    var result = await p.run(['analyze', '--verbose', p.dirPath]);
+    var result = await p!.run(['analyze', '--verbose', p!.dirPath]);
 
     expect(result.exitCode, 3);
     expect(result.stderr, isEmpty);
@@ -386,7 +387,7 @@
 void f() {
   my_foo;
 }''');
-      p.file('my_packages.json', '''
+      p!.file('my_packages.json', '''
 {
   "configVersion": 2,
   "packages": [
@@ -399,10 +400,10 @@
   ]
 }
 ''');
-      var result = await p.run([
+      var result = await p!.run([
         'analyze',
-        '--packages=${p.findFile('my_packages.json').path}',
-        p.dirPath,
+        '--packages=${p!.findFile('my_packages.json')!.path}',
+        p!.dirPath,
       ]);
 
       expect(result.exitCode, 0);
@@ -412,10 +413,10 @@
 
     test('not existing', () async {
       p = project();
-      var result = await p.run([
+      var result = await p!.run([
         'analyze',
         '--packages=no.such.file',
-        p.dirPath,
+        p!.dirPath,
       ]);
 
       expect(result.exitCode, 64);
@@ -428,10 +429,10 @@
     var cache = project(name: 'cache');
 
     p = project(mainSrc: 'var v = 0;');
-    var result = await p.run([
+    var result = await p!.run([
       'analyze',
       '--cache=${cache.dirPath}',
-      p.mainPath,
+      p!.mainPath,
     ]);
 
     expect(result.exitCode, 0);
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index 2facc8c..82478e9 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -468,7 +468,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -497,7 +497,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   }, skip: isRunningOnIA32);
@@ -566,7 +566,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -595,7 +595,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   });
@@ -664,7 +664,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -693,7 +693,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   }, skip: isRunningOnIA32);
@@ -720,7 +720,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stdout, contains('Warning: '));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
@@ -747,7 +747,8 @@
     expect(
       result.stderr,
       predicate(
-        (o) => '$o'.contains('Unexpected arguments after Dart entry point.'),
+        (dynamic o) =>
+            '$o'.contains('Unexpected arguments after Dart entry point.'),
       ),
     );
     expect(result.exitCode, 64);
@@ -818,7 +819,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -846,7 +847,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, contains('must be assigned before it can be used'));
     expect(result.exitCode, 254);
   });
@@ -872,7 +873,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, contains('Warning:'));
     expect(result.exitCode, 0);
   });
@@ -941,7 +942,7 @@
       ],
     );
 
-    expect(result.stdout, predicate((o) => '$o'.contains('[foo]')));
+    expect(result.stdout, predicate((dynamic o) => '$o'.contains('[foo]')));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -965,7 +966,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(File(outFile).existsSync(), true,
@@ -993,7 +994,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, contains('must be assigned before it can be used'));
     expect(result.exitCode, 254);
   });
@@ -1019,7 +1020,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, contains('Warning:'));
     expect(result.exitCode, 0);
   });
diff --git a/pkg/dartdev/test/commands/create_integration_test.dart b/pkg/dartdev/test/commands/create_integration_test.dart
index 4856b47..e73a16d 100644
--- a/pkg/dartdev/test/commands/create_integration_test.dart
+++ b/pkg/dartdev/test/commands/create_integration_test.dart
@@ -14,7 +14,7 @@
 }
 
 void defineCreateTests() {
-  TestProject p;
+  TestProject? p;
 
   setUp(() => p = null);
 
@@ -25,7 +25,7 @@
     test(templateId, () async {
       p = project();
 
-      ProcessResult createResult = await p.run([
+      ProcessResult createResult = await p!.run([
         'create',
         '--force',
         '--template',
@@ -37,11 +37,11 @@
       // Validate that the project analyzes cleanly.
       // TODO: Should we use --fatal-infos here?
       ProcessResult analyzeResult =
-          await p.run(['analyze'], workingDir: p.dir.path);
+          await p!.run(['analyze'], workingDir: p!.dir.path);
       expect(analyzeResult.exitCode, 0, reason: analyzeResult.stdout);
 
       // Validate that the code is well formatted.
-      ProcessResult formatResult = await p.run([
+      ProcessResult formatResult = await p!.run([
         'format',
         '--output',
         'none',
diff --git a/pkg/dartdev/test/commands/create_test.dart b/pkg/dartdev/test/commands/create_test.dart
index 899c7b0..872309e 100644
--- a/pkg/dartdev/test/commands/create_test.dart
+++ b/pkg/dartdev/test/commands/create_test.dart
@@ -17,7 +17,7 @@
 }
 
 void defineCreateTests() {
-  TestProject p;
+  TestProject? p;
 
   setUp(() => p = null);
 
@@ -25,7 +25,7 @@
 
   test('--help', () async {
     p = project();
-    var result = await p.run(['create', '--help']);
+    var result = await p!.run(['create', '--help']);
 
     expect(result.stdout, contains('Create a new Dart project.'));
     expect(
@@ -40,7 +40,7 @@
 
   test('--help --verbose', () async {
     p = project();
-    var result = await p.run(['create', '--help', '--verbose']);
+    var result = await p!.run(['create', '--help', '--verbose']);
 
     expect(result.stdout, contains('Create a new Dart project.'));
     expect(
@@ -67,7 +67,7 @@
   test('list templates', () async {
     p = project();
 
-    ProcessResult result = await p.run(['create', '--list-templates']);
+    ProcessResult result = await p!.run(['create', '--list-templates']);
     expect(result.exitCode, 0);
 
     String output = result.stdout.toString();
@@ -81,7 +81,7 @@
   test('no directory given', () async {
     p = project();
 
-    ProcessResult result = await p.run([
+    ProcessResult result = await p!.run([
       'create',
     ]);
     expect(result.exitCode, 1);
@@ -90,15 +90,15 @@
   test('directory already exists', () async {
     p = project();
 
-    ProcessResult result = await p.run(
-        ['create', '--template', CreateCommand.defaultTemplateId, p.dir.path]);
+    ProcessResult result = await p!.run(
+        ['create', '--template', CreateCommand.defaultTemplateId, p!.dir.path]);
     expect(result.exitCode, 73);
   });
 
   test('project in current directory', () async {
     p = project();
     final projectDir = Directory('foo')..createSync();
-    final result = await p.run(
+    final result = await p!.run(
       ['create', '--force', '.'],
       workingDir: projectDir.path,
     );
@@ -109,7 +109,7 @@
 
   test('project with normalized package name', () async {
     p = project();
-    final result = await p.run(['create', 'requires-normalization']);
+    final result = await p!.run(['create', 'requires-normalization']);
     expect(result.stderr, isEmpty);
     expect(
         result.stdout,
@@ -120,7 +120,7 @@
 
   test('project with an invalid package name', () async {
     p = project();
-    final result = await p.run(['create', 'bad-package^name']);
+    final result = await p!.run(['create', 'bad-package^name']);
     expect(
       result.stderr,
       contains(
@@ -134,8 +134,8 @@
   test('bad template id', () async {
     p = project();
 
-    ProcessResult result = await p
-        .run(['create', '--no-pub', '--template', 'foo-bar', p.dir.path]);
+    ProcessResult result = await p!
+        .run(['create', '--no-pub', '--template', 'foo-bar', p!.dir.path]);
     expect(result.exitCode, isNot(0));
   });
 
@@ -144,7 +144,7 @@
     test(templateId, () async {
       p = project();
       const projectName = 'template_project';
-      ProcessResult result = await p.run([
+      ProcessResult result = await p!.run([
         'create',
         '--force',
         '--no-pub',
@@ -154,9 +154,9 @@
       ]);
       expect(result.exitCode, 0);
 
-      String entry = templates.getGenerator(templateId).entrypoint.path;
+      String entry = templates.getGenerator(templateId)!.entrypoint!.path;
       entry = entry.replaceAll('__projectName__', projectName);
-      File entryFile = File(path.join(p.dir.path, projectName, entry));
+      File entryFile = File(path.join(p!.dir.path, projectName, entry));
 
       expect(entryFile.existsSync(), true,
           reason: 'File not found: ${entryFile.path}');
@@ -168,7 +168,7 @@
       const dir = 'foo';
       const projectName = dir;
       final lines = generator
-          .getInstallInstructions(dir, projectName)
+          .getInstallInstructions(dir, scriptPath: projectName)
           .split('\n')
           .map((e) => e.trim())
           .toList();
diff --git a/pkg/dartdev/test/commands/devtools_test.dart b/pkg/dartdev/test/commands/devtools_test.dart
index e14ba0ac..08f1cd0 100644
--- a/pkg/dartdev/test/commands/devtools_test.dart
+++ b/pkg/dartdev/test/commands/devtools_test.dart
@@ -14,9 +14,9 @@
 }
 
 void devtools() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
@@ -37,15 +37,17 @@
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(result.stdout, contains('Open DevTools'));
-    expect(result.stdout,
-        contains('Usage: dart devtools [arguments] [service protocol uri]'));
+    expect(
+        result.stdout,
+        contains(
+            'Usage: dart [vm-options] devtools [arguments] [service protocol uri]'));
 
     // Shows verbose help.
     expect(result.stdout, contains('--try-ports'));
   });
 
   group('integration', () {
-    Process process;
+    Process? process;
 
     tearDown(() {
       process?.kill();
@@ -56,8 +58,8 @@
 
       // start the devtools server
       process = await p.start(['devtools', '--no-launch-browser', '--machine']);
-
-      final Stream<String> inStream = process.stdout
+      process!.stderr.transform(utf8.decoder).listen(print);
+      final Stream<String> inStream = process!.stdout
           .transform<String>(utf8.decoder)
           .transform<String>(const LineSplitter());
 
@@ -87,7 +89,7 @@
       expect(contents, contains('DevTools'));
 
       // kill the process
-      process.kill();
+      process!.kill();
       process = null;
     });
   });
diff --git a/pkg/dartdev/test/commands/doc_test.dart b/pkg/dartdev/test/commands/doc_test.dart
index 9f57108..42ee01b 100644
--- a/pkg/dartdev/test/commands/doc_test.dart
+++ b/pkg/dartdev/test/commands/doc_test.dart
@@ -9,13 +9,13 @@
 const int compileErrorExitCode = 64;
 
 void main() {
-  group('doc', defineCompileTests, timeout: longTimeout);
+  group('doc', defineDocTests, timeout: longTimeout);
 }
 
-void defineCompileTests() {
+void defineDocTests() {
   test('Passing no args fails', () async {
     final p = project();
-    var result = await p.run(['doc']);
+    final result = await p.run(['doc']);
     expect(result.stderr, contains('Input directory not specified'));
     expect(result.exitCode, compileErrorExitCode);
   });
@@ -27,44 +27,70 @@
       result.stdout,
       contains('Usage: dart doc [arguments] <input directory>'),
     );
-
     expect(result.exitCode, 0);
   });
 
   test('Document a library', () async {
-    final source = '''
+    final p = project(mainSrc: 'void main() { print("Hello, World"); }');
+    p.file('lib/foo.dart', '''
 /// This is Foo. It uses [Bar].
 class Foo {
-    Bar bar;
+  Bar bar;
 }
 
 /// Bar is very nice.
 class Bar {
-    _i = 42;
+  _i = 42;
 }
-    ''';
-
-    final p = project(mainSrc: 'void main() { print("Hello, World"); }');
-    p.file('lib/foo.dart', source);
+''');
     final result = await p.run(['doc', '--validate-links', p.dirPath]);
-    print(
-        'exit: ${result.exitCode}, stderr:\n${result.stderr}\nstdout:\n${result.stdout}');
     expect(result.stdout, contains('Documenting dartdev_temp'));
+    expect(result.exitCode, 0);
+  });
+
+  test('Document a library dry-run', () async {
+    final p = project(mainSrc: 'void main() { print("Hello, World"); }');
+    p.file('lib/foo.dart', '''
+/// This is Foo.
+class Foo {
+  int i = 42;
+}
+''');
+    final result = await p.run(['doc', '--dry-run', '--verbose', p.dirPath]);
+    expect(result.stdout, contains('Documenting dartdev_temp'));
+    expect(result.exitCode, 0);
+  });
+
+  test('Errors cause error code', () async {
+    final p = project(mainSrc: 'void main() { print("Hello, World"); }');
+    p.file('lib/foo.dart', '''
+/// This is Foo. It uses [TypeThatIsntDeclared].
+class Foo {
+  int i = 42;
+}
+''');
+    p.file('dartdoc_options.yaml', '''
+dartdoc:
+  errors:
+    - unresolved-doc-reference
+''');
+    final result = await p.run(['doc', p.dirPath]);
+    expect(result.exitCode, 1);
   });
 
   test('Document a library with broken link is flagged', () async {
     final source = '''
 /// This is Foo. It uses [Baz].
 class Foo {
-  //  Bar bar;
+  int i = 42;
 }
-    ''';
+''';
 
     final p = project(mainSrc: 'void main() { print("Hello, World"); }');
     p.file('lib/foo.dart', source);
     final result = await p.run(['doc', '--validate-links', p.dirPath]);
-    print(
-        'exit: ${result.exitCode}, stderr:\n${result.stderr}\nstdout:\n${result.stdout}');
+    // TODO (mit@): Update this test to actually test for the
+    // --validate-links flag.
     expect(result.stdout, contains('Documenting dartdev_temp'));
   });
 }
diff --git a/pkg/dartdev/test/commands/fix_test.dart b/pkg/dartdev/test/commands/fix_test.dart
index c6382f4..2d21669 100644
--- a/pkg/dartdev/test/commands/fix_test.dart
+++ b/pkg/dartdev/test/commands/fix_test.dart
@@ -18,9 +18,9 @@
 const runFromSource = false;
 
 void defineFix() {
-  TestProject p;
+  TestProject? p;
 
-  ProcessResult result;
+  late ProcessResult result;
 
   final bullet = Logger.standard().ansi.bullet;
 
@@ -52,18 +52,18 @@
 ''');
   }
 
-  Future<ProcessResult> runFix(List<String> args, {String workingDir}) async {
+  Future<ProcessResult> runFix(List<String> args, {String? workingDir}) async {
     if (runFromSource) {
       var binary = path.join(Directory.current.path, 'bin', 'dartdev.dart');
-      return await p.run([binary, 'fix', ...?args], workingDir: workingDir);
+      return await p!.run([binary, 'fix', ...args], workingDir: workingDir);
     }
-    return await p.run(['fix', ...args], workingDir: workingDir);
+    return await p!.run(['fix', ...args], workingDir: workingDir);
   }
 
   test('--help', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
 
-    var result = await runFix([p.dirPath, '--help']);
+    var result = await runFix([p!.dirPath, '--help']);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -79,7 +79,7 @@
   test('--help --verbose', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
 
-    var result = await runFix([p.dirPath, '--help', '--verbose']);
+    var result = await runFix([p!.dirPath, '--help', '--verbose']);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -98,7 +98,7 @@
   test('none', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
 
-    var result = await runFix([p.dirPath]);
+    var result = await runFix([p!.dirPath]);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -109,7 +109,7 @@
   test('--apply (none)', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
 
-    var result = await runFix(['--apply', p.dirPath]);
+    var result = await runFix(['--apply', p!.dirPath]);
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
@@ -128,7 +128,7 @@
 ''',
     );
 
-    var result = await runFix(['--apply'], workingDir: p.dirPath);
+    var result = await runFix(['--apply'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(
@@ -158,7 +158,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--dry-run', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--dry-run', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(
@@ -182,7 +182,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--apply', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--apply', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(
@@ -207,7 +207,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--apply', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--apply', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(
@@ -235,7 +235,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--apply', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--apply', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(result.stdout, contains('Nothing to fix!'));
@@ -253,7 +253,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--apply', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--apply', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(result.stdout, contains('Nothing to fix!'));
@@ -272,7 +272,7 @@
     - prefer_single_quotes
 ''',
     );
-    var result = await runFix(['--apply', '.'], workingDir: p.dirPath);
+    var result = await runFix(['--apply', '.'], workingDir: p!.dirPath);
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
     expect(
@@ -305,7 +305,7 @@
     - prefer_single_quotes
 ''',
       );
-      p.file('lib/main.dart.expect', '''
+      p!.file('lib/main.dart.expect', '''
 class A {
   String a() => '';
 }
@@ -315,7 +315,7 @@
 }
 ''');
       result =
-          await runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+          await runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
       assertResult(exitCode: 1);
     });
 
@@ -337,7 +337,7 @@
     - prefer_single_quotes
 ''',
       );
-      p.file('lib/main.dart.expect', '''
+      p!.file('lib/main.dart.expect', '''
 class A {
   String a() => '';
 }
@@ -348,7 +348,7 @@
 }
 ''');
       result =
-          await runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+          await runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
       assertResult();
     });
 
@@ -371,7 +371,7 @@
 ''',
       );
       result =
-          await runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+          await runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
       assertResult(exitCode: 1);
     });
 
@@ -379,14 +379,14 @@
       p = project(mainSrc: '''
 class C {}
 ''');
-      p.file('lib/main.dart.expect', '''
+      p!.file('lib/main.dart.expect', '''
 class C {}
 ''');
-      p.file('lib/secondary.dart.expect', '''
+      p!.file('lib/secondary.dart.expect', '''
 class A {}
 ''');
       result =
-          await runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+          await runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
       assertResult(exitCode: 1);
     });
 
@@ -403,13 +403,13 @@
     - annotate_overrides
 ''',
       );
-      p.file('lib/main.dart.expect', '''
+      p!.file('lib/main.dart.expect', '''
 class A {
   String a() => '';
 }
 ''');
       result =
-          await runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+          await runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
       assertResult(exitCode: 1);
     });
   });
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index 3feab2d..7c4b4fa5 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -11,6 +11,7 @@
 import '../utils.dart';
 
 void main() {
+  initGlobalState();
   group('command', command, timeout: longTimeout);
   group('flag', help, timeout: longTimeout);
 }
@@ -34,30 +35,28 @@
     DartdevRunner(['--no-analytics'])
         .commands
         .forEach((String commandKey, Command command) {
-      if (command.argParser != null) {
-        if (command.name != 'help' &&
-            command.name != 'format' &&
-            command.name != 'pub' &&
-            command.name != 'test') {
-          expect(command.argParser.usageLineLength,
-              stdout.hasTerminal ? stdout.terminalColumns : null);
-        } else if (command.name == 'pub') {
-          // TODO(sigurdm): Avoid special casing here.
-          // https://github.com/dart-lang/pub/issues/2700
-          expect(command.argParser.usageLineLength,
-              stdout.hasTerminal ? stdout.terminalColumns : 80);
-        } else {
-          expect(command.argParser.usageLineLength, isNull);
-        }
+      if (command.name != 'help' &&
+          command.name != 'format' &&
+          command.name != 'pub' &&
+          command.name != 'test') {
+        expect(command.argParser.usageLineLength,
+            stdout.hasTerminal ? stdout.terminalColumns : null);
+      } else if (command.name == 'pub') {
+        // TODO(sigurdm): Avoid special casing here.
+        // https://github.com/dart-lang/pub/issues/2700
+        expect(command.argParser.usageLineLength,
+            stdout.hasTerminal ? stdout.terminalColumns : 80);
+      } else {
+        expect(command.argParser.usageLineLength, isNull);
       }
     });
   });
 }
 
 void help() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index cf82970..2026f3f 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -14,9 +14,9 @@
 }
 
 void format() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/help_test.dart b/pkg/dartdev/test/commands/help_test.dart
index 69f1f27..8aa3d74 100644
--- a/pkg/dartdev/test/commands/help_test.dart
+++ b/pkg/dartdev/test/commands/help_test.dart
@@ -13,9 +13,9 @@
 }
 
 void help() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   /// Commands not tested by the following loop.
   List<String> _commandsNotTested = <String>[
diff --git a/pkg/dartdev/test/commands/language_server_test.dart b/pkg/dartdev/test/commands/language_server_test.dart
index 543aec9..06d75dc 100644
--- a/pkg/dartdev/test/commands/language_server_test.dart
+++ b/pkg/dartdev/test/commands/language_server_test.dart
@@ -21,10 +21,10 @@
 }
 
 void defineLanguageServerTests() {
-  utils.TestProject project;
-  Process process;
+  late utils.TestProject project;
+  Process? process;
 
-  tearDown(() async => await project?.dispose());
+  tearDown(() async => await project.dispose());
 
   Future runWithLsp(List<String> args) async {
     project = utils.project();
@@ -32,7 +32,7 @@
     process = await project.start(args);
 
     final Stream<String> inStream =
-        process.stdout.transform<String>(utf8.decoder);
+        process!.stdout.transform<String>(utf8.decoder);
 
     // Send an LSP init.
     final String message = jsonEncode({
@@ -47,9 +47,9 @@
       },
     });
 
-    process.stdin.write('Content-Length: ${message.length}\r\n');
-    process.stdin.write('\r\n');
-    process.stdin.write(message);
+    process!.stdin.write('Content-Length: ${message.length}\r\n');
+    process!.stdin.write('\r\n');
+    process!.stdin.write(message);
 
     List<String> responses = await inStream.take(2).toList();
     expect(responses, hasLength(2));
@@ -65,7 +65,7 @@
     final serverInfo = result['serverInfo'];
     expect(serverInfo['name'], isNotEmpty);
 
-    process.kill();
+    process!.kill();
     process = null;
   }
 
@@ -82,7 +82,7 @@
 
     process = await project.start(['language-server', '--protocol=analyzer']);
 
-    final Stream<String> inStream = process.stdout
+    final Stream<String> inStream = process!.stdout
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
 
@@ -95,7 +95,7 @@
     expect(params['version'], isNotEmpty);
     expect(params['pid'], isNot(0));
 
-    process.kill();
+    process!.kill();
     process = null;
   });
 }
diff --git a/pkg/dartdev/test/commands/migrate_test.dart b/pkg/dartdev/test/commands/migrate_test.dart
index 0b394ad..24b0614 100644
--- a/pkg/dartdev/test/commands/migrate_test.dart
+++ b/pkg/dartdev/test/commands/migrate_test.dart
@@ -15,9 +15,9 @@
   final runPubGet = contains('Run `dart pub get`');
   final setLowerSdkConstraint = contains('Set the lower SDK constraint');
 
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
diff --git a/pkg/dartdev/test/commands/pub_test.dart b/pkg/dartdev/test/commands/pub_test.dart
index f2486dd..0c11319 100644
--- a/pkg/dartdev/test/commands/pub_test.dart
+++ b/pkg/dartdev/test/commands/pub_test.dart
@@ -13,9 +13,9 @@
 }
 
 void pub() {
-  TestProject p;
+  TestProject p = project();
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   void _assertPubHelpInvoked(ProcessResult result) {
     expect(result, isNotNull);
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index f3174c7..40978d9 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -21,9 +21,9 @@
 }
 
 void run() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
@@ -345,7 +345,7 @@
     );
 
     expect(result.stdout,
-        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+        predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   });
@@ -497,7 +497,7 @@
         final readyCompleter = Completer<void>();
         final completer = Completer<void>();
 
-        StreamSubscription sub;
+        late StreamSubscription sub;
         sub = process.stdout.transform(utf8.decoder).listen((event) async {
           if (event.contains('ready')) {
             readyCompleter.complete();
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index 7f758d3..1005862 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -17,9 +17,9 @@
 }
 
 void defineTest(List<Experiment> experiments) {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('--help', () async {
     p = project();
@@ -152,7 +152,7 @@
   });
 
   group('--enable-experiment', () {
-    Future<ProcessResult> runTestWithExperimentFlag(String flag) async {
+    Future<ProcessResult> runTestWithExperimentFlag(String? flag) async {
       return await p.run([
         if (flag != null) flag,
         'test',
@@ -162,7 +162,7 @@
       ]);
     }
 
-    Future<void> expectSuccess(String flag) async {
+    Future<void> expectSuccess(String? flag) async {
       final result = await runTestWithExperimentFlag(flag);
       expect(result.stdout, contains('feature enabled'),
           reason: 'stderr: ${result.stderr}');
@@ -170,7 +170,7 @@
           reason: 'stdout: ${result.stdout} stderr: ${result.stderr}');
     }
 
-    Future<void> expectFailure(String flag) async {
+    Future<void> expectFailure(String? flag) async {
       final result = await runTestWithExperimentFlag(flag);
       expect(result.exitCode, isNot(0));
     }
diff --git a/pkg/dartdev/test/core_test.dart b/pkg/dartdev/test/core_test.dart
index f9c8e29..e06feef 100644
--- a/pkg/dartdev/test/core_test.dart
+++ b/pkg/dartdev/test/core_test.dart
@@ -18,6 +18,7 @@
 import 'utils.dart';
 
 void main() {
+  initGlobalState();
   group('DartdevCommand', _dartdevCommand);
   group('PackageConfig', _packageConfig);
   group('Project', _project);
@@ -45,29 +46,35 @@
 
   test('compile/js', () {
     _assertDartdevCommandProperties(
-        CompileCommand().subcommands['js'], 'js', 'compile/js');
+        CompileCommand().subcommands['js'] as DartdevCommand,
+        'js',
+        'compile/js');
   });
 
   test('compile/jit-snapshot', () {
     _assertDartdevCommandProperties(
-        CompileCommand().subcommands['jit-snapshot'],
+        CompileCommand().subcommands['jit-snapshot'] as DartdevCommand,
         'jit-snapshot',
         'compile/jit-snapshot');
   });
 
   test('compile/kernel', () {
     _assertDartdevCommandProperties(
-        CompileCommand().subcommands['kernel'], 'kernel', 'compile/kernel');
+        CompileCommand().subcommands['kernel'] as DartdevCommand,
+        'kernel',
+        'compile/kernel');
   });
 
   test('compile/exe', () {
     _assertDartdevCommandProperties(
-        CompileCommand().subcommands['exe'], 'exe', 'compile/exe');
+        CompileCommand().subcommands['exe'] as DartdevCommand,
+        'exe',
+        'compile/exe');
   });
 
   test('compile/aot-snapshot', () {
     _assertDartdevCommandProperties(
-        CompileCommand().subcommands['aot-snapshot'],
+        CompileCommand().subcommands['aot-snapshot'] as DartdevCommand,
         'aot-snapshot',
         'compile/aot-snapshot');
   });
@@ -103,9 +110,9 @@
 }
 
 void _project() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('hasPubspecFile positive', () {
     p = project();
@@ -128,7 +135,7 @@
     Project coreProj = Project.fromDirectory(p.dir);
     expect(coreProj.hasPackageConfigFile, isTrue);
     expect(coreProj.packageConfig, isNotNull);
-    expect(coreProj.packageConfig.packages, isNotEmpty);
+    expect(coreProj.packageConfig!.packages, isNotEmpty);
   });
 
   test('hasPackageConfigFile negative', () {
diff --git a/pkg/dartdev/test/experiment_util.dart b/pkg/dartdev/test/experiment_util.dart
index 0cf98e1..4ad4ae4 100644
--- a/pkg/dartdev/test/experiment_util.dart
+++ b/pkg/dartdev/test/experiment_util.dart
@@ -12,7 +12,7 @@
 /// associated `validation` program.
 Future<List<Experiment>> experimentsWithValidation() async {
   final url = (await Isolate.resolvePackageUri(
-          Uri.parse('package:dartdev/dartdev.dart')))
+          Uri.parse('package:dartdev/dartdev.dart')))!
       .resolve('../../../tools/experimental_features.yaml');
   final experiments =
       yaml.loadYaml(File.fromUri(url).readAsStringSync(), sourceUrl: url);
@@ -28,14 +28,14 @@
   ];
 }
 
-Version tryParseVersion(String version) =>
+Version? tryParseVersion(String? version) =>
     version == null ? null : Version.parse(version);
 
 class Experiment {
   final String name;
   final String validation;
-  final Version enabledIn;
-  final Version experimentalReleaseVersion;
+  final Version? enabledIn;
+  final Version? experimentalReleaseVersion;
   Experiment(
     this.name,
     this.validation,
diff --git a/pkg/dartdev/test/experiments_test.dart b/pkg/dartdev/test/experiments_test.dart
index f9bec0e..5608ac7 100644
--- a/pkg/dartdev/test/experiments_test.dart
+++ b/pkg/dartdev/test/experiments_test.dart
@@ -11,7 +11,7 @@
       expect(experimentalFeatures, isNotEmpty);
       expect(
         experimentalFeatures.map((experiment) => experiment.enableString),
-        contains('non-nullable'),
+        contains('super-parameters'),
       );
     });
   });
diff --git a/pkg/dartdev/test/fix_driver_test.dart b/pkg/dartdev/test/fix_driver_test.dart
index 8b71804..ac9a6e9 100644
--- a/pkg/dartdev/test/fix_driver_test.dart
+++ b/pkg/dartdev/test/fix_driver_test.dart
@@ -18,8 +18,8 @@
 }
 
 void _driver() {
-  TestProject p;
-  tearDown(() async => await p?.dispose());
+  late TestProject p;
+  tearDown(() async => await p.dispose());
 
   test('no fixes', () async {
     p = project(mainSrc: 'int get foo => 1;\n');
@@ -33,7 +33,7 @@
   final FixResult<CapturingLogger> result;
   FixOutput(this.result);
 
-  int get returnCode => result.returnCode;
+  int? get returnCode => result.returnCode;
   String get stderr => result.logger.output.stderr.toString();
   String get stdout => result.logger.output.stdout.toString();
 }
diff --git a/pkg/dartdev/test/load_from_dill_test.dart b/pkg/dartdev/test/load_from_dill_test.dart
index 0412854..1c4542b 100644
--- a/pkg/dartdev/test/load_from_dill_test.dart
+++ b/pkg/dartdev/test/load_from_dill_test.dart
@@ -9,9 +9,9 @@
 import 'utils.dart';
 
 void main() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
       () async {
diff --git a/pkg/dartdev/test/no_such_file_test.dart b/pkg/dartdev/test/no_such_file_test.dart
index bf4eaa3..1208a5e 100644
--- a/pkg/dartdev/test/no_such_file_test.dart
+++ b/pkg/dartdev/test/no_such_file_test.dart
@@ -7,9 +7,9 @@
 import 'utils.dart';
 
 void main() {
-  TestProject p;
+  late TestProject p;
 
-  tearDown(() async => await p?.dispose());
+  tearDown(() async => await p.dispose());
 
   test('Ensure parsing fails after encountering invalid file', () async {
     // Regression test for https://github.com/dart-lang/sdk/issues/43991
@@ -32,7 +32,8 @@
     final result = await p.run(['--snapshot=abc', 'foo.dart']);
     expect(result.stderr, isNotEmpty);
     expect(result.stderr, contains("Error when reading 'foo.dart':"));
-    expect(result.stdout, isEmpty);
+    expect(result.stdout, isNotEmpty);
+    expect(result.stdout, contains("Info: Compiling with sound null safety\n"));
     expect(result.exitCode, 254);
   });
 }
diff --git a/pkg/dartdev/test/smoke/smoke.dart b/pkg/dartdev/test/smoke/smoke.dart
index 003118f..a6a5181 100644
--- a/pkg/dartdev/test/smoke/smoke.dart
+++ b/pkg/dartdev/test/smoke/smoke.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.
 
-// @dart=2.10
-
 void main() {
   print('Smoke test!');
 }
diff --git a/pkg/dartdev/test/smoke/smoke_test.dart b/pkg/dartdev/test/smoke/smoke_test.dart
index 7b1c688..faad483 100644
--- a/pkg/dartdev/test/smoke/smoke_test.dart
+++ b/pkg/dartdev/test/smoke/smoke_test.dart
@@ -51,6 +51,24 @@
         }
       });
 
+      test('dart run --enable-vm-service smoke.dart with used port', () async {
+        final server = await HttpServer.bind(InternetAddress.anyIPv4, 0);
+        final result = await Process.run(
+          Platform.executable,
+          [
+            'run',
+            '--enable-vm-service=${server.port}',
+            script,
+          ],
+        );
+        expect(
+          result.stderr,
+          'Could not start the VM service: localhost:${server.port} is already in use.\n',
+        );
+        expect(result.stdout, isEmpty);
+        server.close();
+      });
+
       // This test verifies that an error isn't thrown when a valid experiment
       // is passed.
       // Experiments are lists here:
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 8f8147a..316c8bc 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -5,6 +5,8 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:cli_util/cli_logging.dart';
+import 'package:dartdev/src/core.dart';
 import 'package:path/path.dart' as path;
 import 'package:pub_semver/pub_semver.dart';
 import 'package:test/test.dart';
@@ -18,13 +20,17 @@
 /// version:
 const String dartVersionFilePrefix2_9 = '// @dart = 2.9\n';
 
+void initGlobalState() {
+  log = Logger.standard();
+}
+
 TestProject project(
-        {String mainSrc,
-        String analysisOptions,
+        {String? mainSrc,
+        String? analysisOptions,
         bool logAnalytics = false,
         String name = TestProject._defaultProjectName,
-        VersionConstraint sdkConstraint,
-        Map<String, dynamic> pubspec}) =>
+        VersionConstraint? sdkConstraint,
+        Map<String, dynamic>? pubspec}) =>
     TestProject(
         mainSrc: mainSrc,
         analysisOptions: analysisOptions,
@@ -35,7 +41,7 @@
 class TestProject {
   static const String _defaultProjectName = 'dartdev_temp';
 
-  Directory dir;
+  late Directory dir;
 
   String get dirPath => dir.path;
 
@@ -47,19 +53,20 @@
 
   final bool logAnalytics;
 
-  final VersionConstraint sdkConstraint;
+  final VersionConstraint? sdkConstraint;
 
-  final Map<String, dynamic> pubspec;
+  final Map<String, dynamic>? pubspec;
 
-  Process _process;
+  Process? _process;
 
   TestProject(
-      {String mainSrc,
-      String analysisOptions,
+      {String? mainSrc,
+      String? analysisOptions,
       this.name = _defaultProjectName,
       this.logAnalytics = false,
       this.sdkConstraint,
       this.pubspec}) {
+    initGlobalState();
     dir = Directory.systemTemp.createTempSync('a');
     file(
         'pubspec.yaml',
@@ -97,14 +104,23 @@
     _process?.kill();
     await _process?.exitCode;
     _process = null;
-    if (dir.existsSync()) {
-      dir.deleteSync(recursive: true);
+    int deleteAttempts = 5;
+    while (dir.existsSync()) {
+      try {
+        dir.deleteSync(recursive: true);
+      } catch (e) {
+        if ((--deleteAttempts) <= 0) {
+          rethrow;
+        }
+        await Future.delayed(Duration(milliseconds: 500));
+        print('Got $e while deleting $dir. Trying again...');
+      }
     }
   }
 
   Future<ProcessResult> run(
     List<String> arguments, {
-    String workingDir,
+    String? workingDir,
   }) async {
     _process = await Process.start(
         Platform.resolvedExecutable,
@@ -114,11 +130,11 @@
         ],
         workingDirectory: workingDir ?? dir.path,
         environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
-    final stdoutContents = _process.stdout.transform(utf8.decoder).join();
-    final stderrContents = _process.stderr.transform(utf8.decoder).join();
-    final code = await _process.exitCode;
+    final stdoutContents = _process!.stdout.transform(utf8.decoder).join();
+    final stderrContents = _process!.stderr.transform(utf8.decoder).join();
+    final code = await _process!.exitCode;
     return ProcessResult(
-      _process.pid,
+      _process!.pid,
       code,
       await stdoutContents,
       await stderrContents,
@@ -127,7 +143,7 @@
 
   Future<Process> start(
     List<String> arguments, {
-    String workingDir,
+    String? workingDir,
   }) {
     return Process.start(
         Platform.resolvedExecutable,
@@ -140,7 +156,7 @@
       ..then((p) => _process = p);
   }
 
-  String _sdkRootPath;
+  String? _sdkRootPath;
 
   /// Return the root of the SDK.
   String get sdkRootPath {
@@ -152,24 +168,24 @@
         if (File(path.join(tryDir, 'pkg', 'dartdev', 'bin', 'dartdev.dart'))
             .existsSync()) {
           _sdkRootPath = tryDir;
-          return _sdkRootPath;
+          return _sdkRootPath!;
         }
         current = tryDir;
       } while (path.dirname(current) != current);
       throw StateError('can not find SDK repository root');
     }
-    return _sdkRootPath;
+    return _sdkRootPath!;
   }
 
   String get absolutePathToDartdevFile =>
       path.join(sdkRootPath, 'pkg', 'dartdev', 'bin', 'dartdev.dart');
 
-  Directory findDirectory(String name) {
+  Directory? findDirectory(String name) {
     var directory = Directory(path.join(dir.path, name));
     return directory.existsSync() ? directory : null;
   }
 
-  File findFile(String name) {
+  File? findFile(String name) {
     var file = File(path.join(dir.path, name));
     return file.existsSync() ? file : null;
   }
diff --git a/pkg/dartdev/test/utils_test.dart b/pkg/dartdev/test/utils_test.dart
index 111326b..83f2567 100644
--- a/pkg/dartdev/test/utils_test.dart
+++ b/pkg/dartdev/test/utils_test.dart
@@ -64,7 +64,8 @@
       List<dynamic> _packages = contents['packages'];
       try {
         // ignore: unused_local_variable
-        List<Map<String, dynamic>> packages = _packages;
+        List<Map<String, dynamic>> packages =
+            _packages as List<Map<String, dynamic>>;
         fail('expected implicit cast to fail');
       } on TypeError {
         // TypeError is expected
diff --git a/pkg/dartdev/tool/fix_driver.dart b/pkg/dartdev/tool/fix_driver.dart
index 17f246a..d2d8723 100644
--- a/pkg/dartdev/tool/fix_driver.dart
+++ b/pkg/dartdev/tool/fix_driver.dart
@@ -8,9 +8,8 @@
 import 'package:dartdev/src/commands/fix.dart';
 import 'package:dartdev/src/core.dart';
 import 'package:dartdev/src/utils.dart';
-import 'package:meta/meta.dart';
 
-Future<void> main(List<String> args) async {
+Future<int?> main(List<String> args) async {
   var runner = FixRunner(logger: Logger.standard());
   var result = await runner.runFix(args);
   return result.returnCode;
@@ -32,7 +31,7 @@
   }
 
   @override
-  void finish({String message, bool showTiming = false}) {
+  void finish({String? message, bool showTiming = false}) {
     // todo (pq): consider capturing / tracking finish display updates.
     finished = true;
   }
@@ -85,7 +84,7 @@
 
 class FixResult<T extends Logger> {
   /// The value returned by [FixCommand.run].
-  final int returnCode;
+  final int? returnCode;
 
   /// The logger used in driving fixes.
   final T logger;
@@ -104,7 +103,7 @@
     allowTrailingOptions: false,
   );
 
-  FixRunner({@required this.logger})
+  FixRunner({required this.logger})
       : super('fix_runner',
             'A command-line utility for testing the `dart fix` command.') {
     addCommand(FixCommand());
@@ -112,14 +111,14 @@
   }
 
   @override
-  Future<int> runCommand(ArgResults topLevelResults) async {
+  Future<int?> runCommand(ArgResults topLevelResults) async {
     var result = await super.runCommand(topLevelResults);
     return result;
   }
 
   Future<FixResult<T>> runFix(List<String> args) async {
     log = logger;
-    var argResults = argParser.parse(['fix', ...?args]);
+    var argResults = argParser.parse(['fix', ...args]);
     var result = await runCommand(argResults);
     return FixResult(logger, result);
   }
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index 3b33fd2..3cb8dd8 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,18 @@
+# 2.2.0
+- Add support for serving DevTools via `package:dds/devtools_server.dart`
+
+# 2.1.7
+- Re-release 2.1.6+1.
+
+# 2.1.6+3
+- Roll back to 2.1.4.
+
+# 2.1.6+2
+- Roll back to 2.1.5.
+
+# 2.1.6+1
+- Fix dependencies.
+
 # 2.1.6
 - Improve performance of CPU sample caching.
 
diff --git a/pkg/dds/analysis_options.yaml b/pkg/dds/analysis_options.yaml
index 1f83658..6b1919a 100644
--- a/pkg/dds/analysis_options.yaml
+++ b/pkg/dds/analysis_options.yaml
@@ -5,3 +5,4 @@
     - depend_on_referenced_packages
     - directives_ordering
     - prefer_generic_function_type_aliases
+    - prefer_relative_imports
diff --git a/pkg/dds/lib/devtools_server.dart b/pkg/dds/lib/devtools_server.dart
new file mode 100644
index 0000000..1462458
--- /dev/null
+++ b/pkg/dds/lib/devtools_server.dart
@@ -0,0 +1,673 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:browser_launcher/browser_launcher.dart';
+import 'package:http_multi_server/http_multi_server.dart';
+import 'package:path/path.dart' as path;
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:shelf/shelf_io.dart' as shelf;
+
+import 'src/devtools/client.dart';
+import 'src/devtools/handler.dart';
+import 'src/devtools/machine_mode_command_handler.dart';
+import 'src/devtools/memory_profile.dart';
+import 'src/devtools/utils.dart';
+import 'src/utils/console.dart';
+
+class DevToolsServer {
+  static const protocolVersion = '1.1.0';
+  static const defaultTryPorts = 10;
+  static const commandDescription =
+      'Open DevTools (optionally connecting to an existing application).';
+
+  static const argHelp = 'help';
+  static const argVmUri = 'vm-uri';
+  static const argEnableNotifications = 'enable-notifications';
+  static const argAllowEmbedding = 'allow-embedding';
+  static const argAppSizeBase = 'appSizeBase';
+  static const argAppSizeTest = 'appSizeTest';
+  static const argHeadlessMode = 'headless';
+  static const argDebugMode = 'debug';
+  static const argLaunchBrowser = 'launch-browser';
+  static const argMachine = 'machine';
+  static const argHost = 'host';
+  static const argPort = 'port';
+  static const argProfileMemory = 'record-memory-profile';
+  static const argTryPorts = 'try-ports';
+  static const argVerbose = 'verbose';
+  static const argVersion = 'version';
+  static const launchDevToolsService = 'launchDevTools';
+
+  MachineModeCommandHandler? _machineModeCommandHandler;
+  late ClientManager clientManager;
+  final bool _isChromeOS = File('/dev/.cros_milestone').existsSync();
+
+  static ArgParser buildArgParser({bool verbose = false}) {
+    final argParser = ArgParser();
+    argParser
+      ..addFlag(
+        argVersion,
+        negatable: false,
+        help: 'Prints the DevTools version.',
+      )
+      ..addFlag(
+        argVerbose,
+        negatable: false,
+        abbr: 'v',
+        help: 'Output more informational messages.',
+      )
+      ..addOption(
+        argHost,
+        valueHelp: 'host',
+        help: 'Hostname to serve DevTools on (defaults to localhost).',
+      )
+      ..addOption(
+        argPort,
+        defaultsTo: '9100',
+        valueHelp: 'port',
+        help: 'Port to serve DevTools on; specify 0 to automatically use any '
+            'available port.',
+      )
+      ..addFlag(
+        argLaunchBrowser,
+        help:
+            'Launches DevTools in a browser immediately at start.\n(defaults to on unless in --machine mode)',
+      )
+      ..addFlag(
+        argMachine,
+        negatable: false,
+        help: 'Sets output format to JSON for consumption in tools.',
+      )
+      ..addSeparator('Memory profiling options:')
+      ..addOption(
+        argProfileMemory,
+        valueHelp: 'file',
+        defaultsTo: 'memory_samples.json',
+        help:
+            'Start devtools headlessly and write memory profiling samples to the '
+            'indicated file.',
+      );
+
+    if (verbose) {
+      argParser.addSeparator('App size options:');
+    }
+
+    // TODO(devoncarew): --appSizeBase and --appSizeTest should be renamed to
+    // something like --app-size-base and --app-size-test; #3146.
+    argParser
+      ..addOption(
+        argAppSizeBase,
+        valueHelp: 'appSizeBase',
+        help: 'Path to the base app size file used for app size debugging.',
+        hide: !verbose,
+      )
+      ..addOption(
+        argAppSizeTest,
+        valueHelp: 'appSizeTest',
+        help:
+            'Path to the test app size file used for app size debugging.\nThis '
+            'file should only be specified if --$argAppSizeBase is also specified.',
+        hide: !verbose,
+      );
+
+    if (verbose) {
+      argParser.addSeparator('Advanced options:');
+    }
+
+    // Args to show for verbose mode.
+    argParser
+      ..addOption(
+        argTryPorts,
+        defaultsTo: DevToolsServer.defaultTryPorts.toString(),
+        valueHelp: 'count',
+        help: 'The number of ascending ports to try binding to before failing '
+            'with an error. ',
+        hide: !verbose,
+      )
+      ..addFlag(
+        argEnableNotifications,
+        negatable: false,
+        help: 'Requests notification permissions immediately when a client '
+            'connects back to the server.',
+        hide: !verbose,
+      )
+      ..addFlag(
+        argAllowEmbedding,
+        help: 'Allow embedding DevTools inside an iframe.',
+        hide: !verbose,
+      )
+      ..addFlag(
+        argHeadlessMode,
+        negatable: false,
+        help: 'Causes the server to spawn Chrome in headless mode for use in '
+            'automated testing.',
+        hide: !verbose,
+      );
+
+    // Deprecated and hidden args.
+    // TODO: Remove this - prefer that clients use the rest arg.
+    argParser
+      ..addOption(
+        argVmUri,
+        defaultsTo: '',
+        help: 'VM Service protocol URI.',
+        hide: true,
+      )
+
+      // Development only args.
+      ..addFlag(
+        argDebugMode,
+        negatable: false,
+        help: 'Run a debug build of the DevTools web frontend.',
+        hide: true,
+      );
+
+    return argParser;
+  }
+
+  /// Serves DevTools.
+  ///
+  /// `handler` is the [shelf.Handler] that the server will use for all requests.
+  /// If null, [defaultHandler] will be used. Defaults to null.
+  ///
+  /// `customDevToolsPath` is a path to a directory containing a pre-built
+  /// DevTools application.
+  ///
+  // Note: this method is used by the Dart CLI and by package:dwds.
+  Future<HttpServer?> serveDevTools({
+    bool enableStdinCommands = true,
+    bool machineMode = false,
+    bool debugMode = false,
+    bool launchBrowser = false,
+    bool enableNotifications = false,
+    bool allowEmbedding = false,
+    bool headlessMode = false,
+    bool verboseMode = false,
+    String? hostname,
+    String? customDevToolsPath,
+    int port = 0,
+    int numPortsToTry = defaultTryPorts,
+    shelf.Handler? handler,
+    String? serviceProtocolUri,
+    String? profileFilename,
+    String? appSizeBase,
+    String? appSizeTest,
+  }) async {
+    hostname ??= 'localhost';
+
+    // Collect profiling information.
+    if (profileFilename != null && serviceProtocolUri != null) {
+      final Uri? vmServiceUri = Uri.tryParse(serviceProtocolUri);
+      if (vmServiceUri != null) {
+        await _hookupMemoryProfiling(
+          vmServiceUri,
+          profileFilename,
+          verboseMode,
+        );
+      }
+      return null;
+    }
+
+    if (machineMode) {
+      assert(
+        enableStdinCommands,
+        'machineMode only works with enableStdinCommands.',
+      );
+    }
+
+    clientManager = ClientManager(
+      requestNotificationPermissions: enableNotifications,
+    );
+    handler ??= await defaultHandler(
+      buildDir: customDevToolsPath!,
+      clientManager: clientManager,
+    );
+
+    HttpServer? server;
+    SocketException? ex;
+    while (server == null && numPortsToTry >= 0) {
+      // If we have tried [numPortsToTry] ports and still have not been able to
+      // connect, try port 0 to find a random available port.
+      if (numPortsToTry == 0) port = 0;
+
+      try {
+        server = await HttpMultiServer.bind(hostname, port);
+      } on SocketException catch (e) {
+        ex = e;
+        numPortsToTry--;
+        port++;
+      }
+    }
+
+    // Re-throw the last exception if we failed to bind.
+    if (server == null && ex != null) {
+      throw ex;
+    }
+
+    final _server = server!;
+    if (allowEmbedding) {
+      _server.defaultResponseHeaders.remove('x-frame-options', 'SAMEORIGIN');
+    }
+
+    // Ensure browsers don't cache older versions of the app.
+    _server.defaultResponseHeaders.add(
+      HttpHeaders.cacheControlHeader,
+      'max-age=900',
+    );
+
+    // Serve requests in an error zone to prevent failures
+    // when running from another error zone.
+    runZonedGuarded(
+      () => shelf.serveRequests(_server, handler!),
+      (e, _) => print('Error serving requests: $e'),
+    );
+
+    final devToolsUrl = 'http://${_server.address.host}:${_server.port}';
+
+    if (launchBrowser) {
+      if (serviceProtocolUri != null) {
+        serviceProtocolUri =
+            _normalizeVmServiceUri(serviceProtocolUri).toString();
+      }
+
+      final queryParameters = {
+        if (serviceProtocolUri != null) 'uri': serviceProtocolUri,
+        if (appSizeBase != null) 'appSizeBase': appSizeBase,
+        if (appSizeTest != null) 'appSizeTest': appSizeTest,
+      };
+      String url = Uri.parse(devToolsUrl)
+          .replace(queryParameters: queryParameters)
+          .toString();
+
+      // If app size parameters are present, open to the standalone `appsize`
+      // page, regardless if there is a vm service uri specified. We only check
+      // for the presence of [appSizeBase] here because [appSizeTest] may or may
+      // not be specified (it should only be present for diffs). If [appSizeTest]
+      // is present without [appSizeBase], we will ignore the parameter.
+      if (appSizeBase != null) {
+        final startQueryParamIndex = url.indexOf('?');
+        if (startQueryParamIndex != -1) {
+          url = '${url.substring(0, startQueryParamIndex)}'
+              '/#/appsize'
+              '${url.substring(startQueryParamIndex)}';
+        }
+      }
+
+      try {
+        await Chrome.start([url]);
+      } catch (e) {
+        print('Unable to launch Chrome: $e\n');
+      }
+    }
+
+    if (enableStdinCommands) {
+      String message = '''Serving DevTools at $devToolsUrl.
+
+          Hit ctrl-c to terminate the server.''';
+      if (!machineMode && debugMode) {
+        // Add bold to help find the correct url to open.
+        message = ConsoleUtils.bold('$message\n');
+      }
+
+      DevToolsUtils.printOutput(
+        message,
+        {
+          'event': 'server.started',
+          // TODO(dantup): Remove this `method` field when we're sure VS Code
+          // users are all on a newer version that uses `event`. We incorrectly
+          // used `method` for the original releases.
+          'method': 'server.started',
+          'params': {
+            'host': _server.address.host,
+            'port': _server.port,
+            'pid': pid,
+            'protocolVersion': protocolVersion,
+          }
+        },
+        machineMode: machineMode,
+      );
+
+      if (machineMode) {
+        _machineModeCommandHandler = MachineModeCommandHandler(server: this);
+        await _machineModeCommandHandler!.initialize(
+          devToolsUrl: devToolsUrl,
+          headlessMode: headlessMode,
+        );
+      }
+    }
+
+    return server;
+  }
+
+  void _printUsage(ArgParser argParser) {
+    print(commandDescription);
+    print('\nUsage: devtools [arguments] [service protocol uri]');
+    print(argParser.usage);
+  }
+
+  /// Wraps [serveDevTools] `arguments` parsed, as from the command line.
+  ///
+  /// For more information on `handler`, see [serveDevTools].
+  // Note: this method is used in google3 as well as by DevTools' main method.
+  Future<HttpServer?> serveDevToolsWithArgs(
+    List<String> arguments, {
+    shelf.Handler? handler,
+    String? customDevToolsPath,
+  }) async {
+    ArgResults args;
+    final verbose = arguments.contains('-v') || arguments.contains('--verbose');
+    final argParser = buildArgParser(verbose: verbose);
+    try {
+      args = argParser.parse(arguments);
+    } on FormatException catch (e) {
+      print(e.message);
+      print('');
+      _printUsage(argParser);
+      return null;
+    }
+
+    return await _serveDevToolsWithArgs(
+      args,
+      verbose,
+      handler: handler,
+      customDevToolsPath: customDevToolsPath,
+    );
+  }
+
+  Future<HttpServer?> _serveDevToolsWithArgs(
+    ArgResults args,
+    bool verbose, {
+    shelf.Handler? handler,
+    String? customDevToolsPath,
+  }) async {
+    final help = args[argHelp];
+    final bool version = args[argVersion];
+    final bool machineMode = args[argMachine];
+    // launchBrowser defaults based on machine-mode if not explicitly supplied.
+    final bool launchBrowser = args.wasParsed(argLaunchBrowser)
+        ? args[argLaunchBrowser]
+        : !machineMode;
+    final bool enableNotifications = args[argEnableNotifications];
+    final bool allowEmbedding =
+        args.wasParsed(argAllowEmbedding) ? args[argAllowEmbedding] : true;
+
+    final port = args[argPort] != null ? int.tryParse(args[argPort]) ?? 0 : 0;
+
+    final bool headlessMode = args[argHeadlessMode];
+    final bool debugMode = args[argDebugMode];
+
+    final numPortsToTry = args[argTryPorts] != null
+        ? int.tryParse(args[argTryPorts]) ?? 0
+        : defaultTryPorts;
+
+    final bool verboseMode = args[argVerbose];
+    final String? hostname = args[argHost];
+    final String? appSizeBase = args[argAppSizeBase];
+    final String? appSizeTest = args[argAppSizeTest];
+
+    if (help) {
+      print(
+          'Dart DevTools version ${await DevToolsUtils.getVersion(customDevToolsPath ?? "")}');
+      print('');
+      _printUsage(buildArgParser(verbose: verbose));
+      return null;
+    }
+
+    if (version) {
+      final versionStr =
+          await DevToolsUtils.getVersion(customDevToolsPath ?? '');
+      DevToolsUtils.printOutput(
+        'Dart DevTools version $versionStr',
+        {
+          'version': versionStr,
+        },
+        machineMode: machineMode,
+      );
+      return null;
+    }
+
+    // Prefer getting the VM URI from the rest args; fall back on the 'vm-url'
+    // option otherwise.
+    String? serviceProtocolUri;
+    if (args.rest.isNotEmpty) {
+      serviceProtocolUri = args.rest.first;
+    } else if (args.wasParsed(argVmUri)) {
+      serviceProtocolUri = args[argVmUri];
+    }
+
+    // Support collecting profile data.
+    String? profileFilename;
+    if (args.wasParsed(argProfileMemory)) {
+      profileFilename = args[argProfileMemory];
+    }
+    if (profileFilename != null && !path.isAbsolute(profileFilename)) {
+      profileFilename = path.absolute(profileFilename);
+    }
+
+    return serveDevTools(
+      machineMode: machineMode,
+      debugMode: debugMode,
+      launchBrowser: launchBrowser,
+      enableNotifications: enableNotifications,
+      allowEmbedding: allowEmbedding,
+      port: port,
+      headlessMode: headlessMode,
+      numPortsToTry: numPortsToTry,
+      handler: handler,
+      customDevToolsPath: customDevToolsPath,
+      serviceProtocolUri: serviceProtocolUri,
+      profileFilename: profileFilename,
+      verboseMode: verboseMode,
+      hostname: hostname,
+      appSizeBase: appSizeBase,
+      appSizeTest: appSizeTest,
+    );
+  }
+
+  Future<Map<String, dynamic>> launchDevTools(
+      Map<String, dynamic> params,
+      Uri vmServiceUri,
+      String devToolsUrl,
+      bool headlessMode,
+      bool machineMode) async {
+    // First see if we have an existing DevTools client open that we can
+    // reuse.
+    final canReuse =
+        params.containsKey('reuseWindows') && params['reuseWindows'] == true;
+    final shouldNotify =
+        params.containsKey('notify') && params['notify'] == true;
+    final page = params['page'];
+    if (canReuse &&
+        _tryReuseExistingDevToolsInstance(
+          vmServiceUri,
+          page,
+          shouldNotify,
+        )) {
+      _emitLaunchEvent(
+          reused: true,
+          notified: shouldNotify,
+          pid: null,
+          machineMode: machineMode);
+      return {
+        'reused': true,
+        'notified': shouldNotify,
+      };
+    }
+
+    final uriParams = <String, dynamic>{};
+
+    // Copy over queryParams passed by the client
+    params['queryParams']?.forEach((key, value) => uriParams[key] = value);
+
+    // Add the URI to the VM service
+    uriParams['uri'] = vmServiceUri.toString();
+
+    final devToolsUri = Uri.parse(devToolsUrl);
+    final uriToLaunch = _buildUriToLaunch(uriParams, page, devToolsUri);
+
+    // TODO(dantup): When ChromeOS has support for tunneling all ports we can
+    // change this to always use the native browser for ChromeOS and may wish to
+    // handle this inside `browser_launcher`; https://crbug.com/848063.
+    final useNativeBrowser = _isChromeOS &&
+        _isAccessibleToChromeOSNativeBrowser(devToolsUri) &&
+        _isAccessibleToChromeOSNativeBrowser(vmServiceUri);
+    int? browserPid;
+    if (useNativeBrowser) {
+      await Process.start('x-www-browser', [uriToLaunch.toString()]);
+    } else {
+      final args = headlessMode
+          ? [
+              '--headless',
+              // When running headless, Chrome will quit immediately after loading
+              // the page unless we have the debug port open.
+              '--remote-debugging-port=9223',
+              '--disable-gpu',
+              '--no-sandbox',
+            ]
+          : <String>[];
+      final proc = await Chrome.start([uriToLaunch.toString()], args: args);
+      browserPid = proc.pid;
+    }
+    _emitLaunchEvent(
+        reused: false,
+        notified: false,
+        pid: browserPid!,
+        machineMode: machineMode);
+    return {
+      'reused': false,
+      'notified': false,
+      'pid': browserPid,
+    };
+  }
+
+  Future<void> _hookupMemoryProfiling(
+    Uri observatoryUri,
+    String profileFile, [
+    bool verboseMode = false,
+  ]) async {
+    final service = await DevToolsUtils.connectToVmService(observatoryUri);
+    if (service == null) {
+      return;
+    }
+
+    final memoryProfiler = MemoryProfile(service, profileFile, verboseMode);
+    memoryProfiler.startPolling();
+
+    print('Writing memory profile samples to $profileFile...');
+  }
+
+  bool _tryReuseExistingDevToolsInstance(
+    Uri vmServiceUri,
+    String page,
+    bool notifyUser,
+  ) {
+    // First try to find a client that's already connected to this VM service,
+    // and just send the user a notification for that one.
+    final existingClient =
+        clientManager.findExistingConnectedReusableClient(vmServiceUri);
+    if (existingClient != null) {
+      try {
+        existingClient.showPage(page);
+        if (notifyUser) {
+          existingClient.notify();
+        }
+        return true;
+      } catch (e) {
+        print('Failed to reuse existing connected DevTools client');
+        print(e);
+      }
+    }
+
+    final reusableClient = clientManager.findReusableClient();
+    if (reusableClient != null) {
+      try {
+        reusableClient.connectToVmService(vmServiceUri, notifyUser);
+        return true;
+      } catch (e) {
+        print('Failed to reuse existing DevTools client');
+        print(e);
+      }
+    }
+    return false;
+  }
+
+  String _buildUriToLaunch(
+    Map<String, dynamic> uriParams,
+    page,
+    Uri devToolsUri,
+  ) {
+    final queryStringNameValues = [];
+    uriParams.forEach((key, value) => queryStringNameValues.add(
+        '${Uri.encodeQueryComponent(key)}=${Uri.encodeQueryComponent(value)}'));
+
+    if (page != null) {
+      queryStringNameValues.add('page=${Uri.encodeQueryComponent(page)}');
+    }
+
+    return devToolsUri
+        .replace(
+            path: '${devToolsUri.path.isEmpty ? '/' : devToolsUri.path}',
+            fragment: '?${queryStringNameValues.join('&')}')
+        .toString();
+  }
+
+  /// Prints a launch event to stdout so consumers of the DevTools server
+  /// can see when clients are being launched/reused.
+  void _emitLaunchEvent(
+      {required bool reused,
+      required bool notified,
+      required int? pid,
+      required bool machineMode}) {
+    DevToolsUtils.printOutput(
+      null,
+      {
+        'event': 'client.launch',
+        'params': {
+          'reused': reused,
+          'notified': notified,
+          'pid': pid,
+        },
+      },
+      machineMode: machineMode,
+    );
+  }
+
+  bool _isAccessibleToChromeOSNativeBrowser(Uri uri) {
+    const tunneledPorts = {
+      8000,
+      8008,
+      8080,
+      8085,
+      8888,
+      9005,
+      3000,
+      4200,
+      5000
+    };
+    return uri.hasPort && tunneledPorts.contains(uri.port);
+  }
+
+  // TODO(https://github.com/flutter/devtools/issues/3571): move to devtools_shared.
+  // Note: please keep this copy of normalizeVmServiceUri() in sync with the one
+  // in devtools_app.
+  Uri? _normalizeVmServiceUri(String value) {
+    value = value.trim();
+
+    // Cleanup encoded urls likely copied from the uri of an existing running
+    // DevTools app.
+    if (value.contains('%3A%2F%2F')) {
+      value = Uri.decodeFull(value);
+    }
+    final uri = Uri.parse(value.trim()).removeFragment();
+    if (!uri.isAbsolute) {
+      return null;
+    }
+    if (uri.path.endsWith('/')) return uri;
+    return uri.replace(path: uri.path);
+  }
+}
diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart
index 7aaeafd..5b3abdc 100644
--- a/pkg/dds/lib/src/client.dart
+++ b/pkg/dds/lib/src/client.dart
@@ -97,7 +97,13 @@
   void _registerJsonRpcMethods() {
     _clientPeer.registerMethod('streamListen', (parameters) async {
       final streamId = parameters['streamId'].asString;
-      await dds.streamManager.streamListen(this, streamId);
+      final includePrivates =
+          parameters['_includePrivateMembers'].asBoolOr(false);
+      await dds.streamManager.streamListen(
+        this,
+        streamId,
+        includePrivates: includePrivates,
+      );
       return RPCResponses.success;
     });
 
diff --git a/pkg/dds/lib/src/cpu_samples_manager.dart b/pkg/dds/lib/src/cpu_samples_manager.dart
index 14b5c22..aafb15d 100644
--- a/pkg/dds/lib/src/cpu_samples_manager.dart
+++ b/pkg/dds/lib/src/cpu_samples_manager.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:dds/src/common/ring_buffer.dart';
 import 'package:vm_service/vm_service.dart';
 
+import 'common/ring_buffer.dart';
 import 'dds_impl.dart';
 
 /// Manages CPU sample caches for an individual [Isolate].
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index 523cadf..83c9d9d 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -21,6 +21,7 @@
 import '../protocol_converter.dart';
 import '../protocol_generated.dart';
 import '../protocol_stream.dart';
+import '../utils.dart';
 
 /// The mime type to send with source responses to the client.
 ///
@@ -382,6 +383,36 @@
   /// VM Service disconnects.
   bool isTerminating = false;
 
+  /// Whether isolates that pause in the PauseExit state should be automatically
+  /// resumed after any in-process log events have completed.
+  ///
+  /// Normally this will be true, but it may be set to false if the user
+  /// also manually passes pause-isolates-on-exit.
+  bool resumeIsolatesAfterPauseExit = true;
+
+  /// A [Future] that completes when the last queued OutputEvent has been sent.
+  ///
+  /// Calls to [SendOutput] will reserve their place in this queue and
+  /// subsequent calls will chain their own sends onto this (and replace it) to
+  /// preserve order.
+  Future? _lastOutputEvent;
+
+  /// Removes any breakpoints or pause behaviour and resumes any paused
+  /// isolates.
+  ///
+  /// This is useful when detaching from a process that was attached to, where
+  /// the user would not expect the script to continue to pause on breakpoints
+  /// the had set while attached.
+  Future<void> preventBreakingAndResume() async {
+    // Remove anything that may cause us to pause again.
+    await Future.wait([
+      _isolateManager.clearAllBreakpoints(),
+      _isolateManager.setExceptionPauseMode('None'),
+    ]);
+    // Once those have completed, it's safe to resume anything paused.
+    await _isolateManager.resumeAll();
+  }
+
   DartDebugAdapter(
     ByteStreamServerChannel channel, {
     this.ipv6 = false,
@@ -887,7 +918,11 @@
   }
 
   /// Sends a [TerminatedEvent] if one has not already been sent.
-  void handleSessionTerminate([String exitSuffix = '']) {
+  ///
+  /// Waits for any in-progress output events to complete first.
+  void handleSessionTerminate([String exitSuffix = '']) async {
+    await _waitForPendingOutputEvents();
+
     if (_hasSentTerminatedEvent) {
       return;
     }
@@ -895,8 +930,9 @@
     isTerminating = true;
     _hasSentTerminatedEvent = true;
     // Always add a leading newline since the last written text might not have
-    // had one.
-    sendOutput('console', '\nExited$exitSuffix.');
+    // had one. Send directly via sendEvent and not sendOutput to ensure no
+    // async since we're about to terminate.
+    sendEvent(OutputEventBody(output: '\nExited$exitSuffix.'));
     sendEvent(TerminatedEventBody());
   }
 
@@ -1084,9 +1120,32 @@
   }
 
   /// Sends an OutputEvent (without a newline, since calls to this method
-  /// may be used by buffered data).
-  void sendOutput(String category, String message) {
-    sendEvent(OutputEventBody(category: category, output: message));
+  /// may be using buffered data that is not split cleanly on newlines).
+  ///
+  /// If [category] is `stderr`, will also look for stack traces and extract
+  /// file/line information to add to the metadata of the event.
+  ///
+  /// To ensure output is sent to the client in the correct order even if
+  /// processing stack frames requires async calls, this function will insert
+  /// output events into a queue and only send them when previous calls have
+  /// been completed.
+  void sendOutput(String category, String message) async {
+    // Reserve our place in the queue be inserting a future that we can complete
+    // after we have sent the output event.
+    final completer = Completer<void>();
+    final _previousEvent = _lastOutputEvent ?? Future.value();
+    _lastOutputEvent = completer.future;
+
+    try {
+      final outputEvents = await _buildOutputEvents(category, message);
+
+      // Chain our sends onto the end of the previous one, and complete our Future
+      // once done so that the next one can go.
+      await _previousEvent;
+      outputEvents.forEach(sendEvent);
+    } finally {
+      completer.complete();
+    }
   }
 
   /// Sends an OutputEvent for [message], prefixed with [prefix] and with [message]
@@ -1561,6 +1620,108 @@
     return uri.replace(path: newPath);
   }
 
+  /// Creates one or more OutputEvents for the provided [message].
+  ///
+  /// Messages that contain stack traces may be split up into seperate events
+  /// for each frame to allow location metadata to be attached.
+  Future<List<OutputEventBody>> _buildOutputEvents(
+    String category,
+    String message,
+  ) async {
+    try {
+      if (category == 'stderr') {
+        return await _buildStdErrOutputEvents(message);
+      } else {
+        return [OutputEventBody(category: category, output: message)];
+      }
+    } catch (e, s) {
+      // Since callers of [sendOutput] may not await it, don't allow unhandled
+      // errors (for example if the VM Service quits while we were trying to
+      // map URIs), just log and return the event without metadata.
+      logger?.call('Failed to build OutputEvent: $e, $s');
+      return [OutputEventBody(category: category, output: message)];
+    }
+  }
+
+  /// Builds OutputEvents for stderr.
+  ///
+  /// If a stack trace can be parsed from [message], file/line information will
+  /// be included in the metadata of the event.
+  Future<List<OutputEventBody>> _buildStdErrOutputEvents(String message) async {
+    final events = <OutputEventBody>[];
+
+    // Extract all the URIs so we can send a batch request for resolving them.
+    final lines = message.split('\n');
+    final frames = lines.map(parseStackFrame).toList();
+    final uris = frames.whereNotNull().map((f) => f.uri).toList();
+
+    // We need an Isolate to resolve package URIs. Since we don't know what
+    // isolate printed an error to stderr, we just have to use the first one and
+    // hope the packages are available. If one is not available (which should
+    // never be the case), we will just skip resolution.
+    final thread = _isolateManager.threads.firstOrNull;
+
+    // Send a batch request. This will cache the results so we can easily use
+    // them in the loop below by calling the method again.
+    if (uris.isNotEmpty) {
+      try {
+        await thread?.resolveUrisToPathsBatch(uris);
+      } catch (e, s) {
+        // Ignore errors that may occur if the VM is shutting down before we got
+        // this request out. In most cases we will have pre-cached the results
+        // when the libraries were loaded (in order to check if they're user code)
+        // so it's likely this won't cause any issues (dart:isolate-patch is an
+        // exception seen that appears in the stack traces but was not previously
+        // seen/cached).
+        logger?.call('Failed to resolve URIs: $e\n$s');
+      }
+    }
+
+    // Convert any URIs to paths.
+    final paths = await Future.wait(frames.map((frame) async {
+      final uri = frame?.uri;
+      if (uri == null) return null;
+      if (uri.isScheme('file')) return uri.toFilePath();
+      if (isResolvableUri(uri)) {
+        try {
+          return await thread?.resolveUriToPath(uri);
+        } catch (e, s) {
+          // Swallow errors for the same reason noted above.
+          logger?.call('Failed to resolve URIs: $e\n$s');
+        }
+      }
+      return null;
+    }));
+
+    for (var i = 0; i < lines.length; i++) {
+      final line = lines[i];
+      final frame = frames[i];
+      final uri = frame?.uri;
+      final path = paths[i];
+      // For the name, we usually use the package URI, but if we only ended up
+      // with a file URI, try to make it relative to cwd so it's not so long.
+      final name = uri != null && path != null
+          ? (uri.isScheme('file')
+              ? _converter.convertToRelativePath(path)
+              : uri.toString())
+          : null;
+      // Because we split on newlines, all items exept the last one need to
+      // have their trailing newlines added back.
+      final output = i == lines.length - 1 ? line : '$line\n';
+      events.add(
+        OutputEventBody(
+          category: 'stderr',
+          output: output,
+          source: path != null ? Source(name: name, path: path) : null,
+          line: frame?.line,
+          column: frame?.column,
+        ),
+      );
+    }
+
+    return events;
+  }
+
   /// Handles evaluation of an expression that is (or begins with)
   /// `threadExceptionExpression` which corresponds to the exception at the top
   /// of [thread].
@@ -1602,6 +1763,18 @@
     await debuggerInitialized;
 
     await _isolateManager.handleEvent(event);
+
+    final eventKind = event.kind;
+    final isolate = event.isolate;
+    // We pause isolates on exit to allow requests for resolving URIs in
+    // stderr call stacks, so when we see an isolate pause, wait for any
+    // pending logs and then resume it (so it exits).
+    if (resumeIsolatesAfterPauseExit &&
+        eventKind == vm.EventKind.kPauseExit &&
+        isolate != null) {
+      await _waitForPendingOutputEvents();
+      await _isolateManager.resumeIsolate(isolate);
+    }
   }
 
   @protected
@@ -1841,6 +2014,20 @@
     return (data) => _withErrorHandling(() => handler(data));
   }
 
+  /// Waits for any pending async output events that might be in progress.
+  ///
+  /// If another output event is queued while waiting, the new event will be
+  /// waited for, until there are no more.
+  Future<void> _waitForPendingOutputEvents() async {
+    // Keep awaiting it as long as it's changing to allow for other
+    // events being queued up while it runs.
+    var lastEvent = _lastOutputEvent;
+    do {
+      lastEvent = _lastOutputEvent;
+      await lastEvent;
+    } while (lastEvent != _lastOutputEvent);
+  }
+
   /// Calls a function with an error handler that handles errors that occur when
   /// the VM Service/DDS shuts down.
   ///
@@ -1899,8 +2086,6 @@
 
   final int? vmServicePort;
 
-  final bool? enableAsserts;
-
   /// Which console to run the program in.
   ///
   /// If "terminal" or "externalTerminal" will cause the program to be run by
@@ -1939,7 +2124,6 @@
     this.toolArgs,
     this.vmAdditionalArgs,
     this.console,
-    this.enableAsserts,
     this.customTool,
     this.customToolReplacesArgs,
     Object? restart,
@@ -1973,7 +2157,6 @@
         vmAdditionalArgs = (obj['vmAdditionalArgs'] as List?)?.cast<String>(),
         vmServicePort = obj['vmServicePort'] as int?,
         console = obj['console'] as String?,
-        enableAsserts = obj['enableAsserts'] as bool?,
         customTool = obj['customTool'] as String?,
         customToolReplacesArgs = obj['customToolReplacesArgs'] as int?,
         super.fromMap(obj);
@@ -1988,7 +2171,6 @@
         if (vmAdditionalArgs != null) 'vmAdditionalArgs': vmAdditionalArgs,
         if (vmServicePort != null) 'vmServicePort': vmServicePort,
         if (console != null) 'console': console,
-        if (enableAsserts != null) 'enableAsserts': enableAsserts,
         if (customTool != null) 'customTool': customTool,
         if (customToolReplacesArgs != null)
           'customToolReplacesArgs': customToolReplacesArgs,
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
index 46e28e3..06def69 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
@@ -67,9 +67,20 @@
   /// Called by [disconnectRequest] to request that we forcefully shut down the
   /// app being run (or in the case of an attach, disconnect).
   Future<void> disconnectImpl() async {
+    if (isAttach) {
+      await preventBreakingAndResume();
+    }
     terminatePids(ProcessSignal.sigkill);
   }
 
+  /// Checks whether [flag] is in [args], allowing for both underscore and
+  /// dash format.
+  bool _containsVmFlag(List<String> args, String flag) {
+    final flagUnderscores = flag.replaceAll('-', '_');
+    final flagDashes = flag.replaceAll('_', '-');
+    return args.contains(flagUnderscores) || args.contains(flagDashes);
+  }
+
   /// Called by [launchRequest] to request that we actually start the app to be
   /// run/debugged.
   ///
@@ -98,11 +109,19 @@
         '-DSILENT_OBSERVATORY=true',
         '--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
       ],
-      // Default to asserts on, this seems like the most useful behaviour for
-      // editor-spawned debug sessions.
-      if (args.enableAsserts ?? true) '--enable-asserts',
     ];
 
+    final toolArgs = args.toolArgs ?? [];
+    if (debug) {
+      // If the user has explicitly set pause-isolates-on-exit we need to
+      // not add it ourselves, and disable auto-resuming.
+      if (_containsVmFlag(toolArgs, '--pause_isolates_on_exit')) {
+        resumeIsolatesAfterPauseExit = false;
+      } else {
+        vmArgs.add('--pause_isolates_on_exit');
+      }
+    }
+
     // Handle customTool and deletion of any arguments for it.
     final executable = args.customTool ?? Platform.resolvedExecutable;
     final removeArgs = args.customToolReplacesArgs;
@@ -112,7 +131,7 @@
 
     final processArgs = [
       ...vmArgs,
-      ...?args.toolArgs,
+      ...toolArgs,
       args.program,
       ...?args.args,
     ];
@@ -150,11 +169,6 @@
         env: args.env,
       );
     }
-
-    // Delay responding until the debugger is connected.
-    if (debug) {
-      await debuggerInitialized;
-    }
   }
 
   /// Called by [attachRequest] to request that we actually connect to the app
@@ -256,6 +270,9 @@
   /// Called by [terminateRequest] to request that we gracefully shut down the
   /// app being run (or in the case of an attach, disconnect).
   Future<void> terminateImpl() async {
+    if (isAttach) {
+      await preventBreakingAndResume();
+    }
     terminatePids(ProcessSignal.sigterm);
     await _process?.exitCode;
   }
diff --git a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
index 0f67af4..716fcfe 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
@@ -93,11 +93,8 @@
         '-DSILENT_OBSERVATORY=true',
         '--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
       ],
-      // Default to asserts on, this seems like the most useful behaviour for
-      // editor-spawned debug sessions.
-      if (args.enableAsserts ?? true) '--enable-asserts',
       // TODO(dantup): This should be changed from "dart run test:test" to
-      // "dart test" once the started-paused flags are working correctly.
+      // "dart test" once the start-paused flags are working correctly.
       // Currently they start paused but do not write the vm-service-info file
       // to give us the VM-service URI.
       // https://github.com/dart-lang/sdk/issues/44200#issuecomment-726869539
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index 9fb0adf..ee48794 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -13,6 +13,7 @@
 import 'adapters/dart.dart';
 import 'exceptions.dart';
 import 'protocol_generated.dart';
+import 'utils.dart';
 
 /// Manages state of Isolates (called Threads by the DAP protocol).
 ///
@@ -215,8 +216,7 @@
     ));
   }
 
-  Future<void> resumeIsolate(vm.IsolateRef isolateRef,
-      [String? resumeType]) async {
+  Future<void> resumeIsolate(vm.IsolateRef isolateRef) async {
     final isolateId = isolateRef.id!;
 
     final thread = _threadsByIsolateId[isolateId];
@@ -283,6 +283,18 @@
         .map((thread) => _sendBreakpoints(thread, uri: uri)));
   }
 
+  /// Clears all breakpoints.
+  Future<void> clearAllBreakpoints() async {
+    // Clear all breakpoints for each URI. Do not remove the items from the map
+    // as that will stop them being tracked/sent by the call below.
+    _clientBreakpointsByUri.updateAll((key, value) => []);
+
+    // Send the breakpoints to all existing threads.
+    await Future.wait(
+      _threadsByThreadId.values.map((thread) => _sendBreakpoints(thread)),
+    );
+  }
+
   /// Records exception pause mode as one of 'None', 'Unhandled' or 'All'. All
   /// existing isolates will be updated to reflect the new setting.
   Future<void> setExceptionPauseMode(String mode) async {
@@ -560,6 +572,14 @@
     }
   }
 
+  /// Resumes any paused isolates.
+  Future<void> resumeAll() async {
+    final pausedThreads = threads.where((thread) => thread.paused).toList();
+    await Future.wait(
+      pausedThreads.map((thread) => resumeThread(thread.threadId)),
+    );
+  }
+
   /// Calls reloadSources for the given isolate.
   Future<void> _reloadSources(vm.IsolateRef isolateRef) async {
     final service = _adapter.vmService;
@@ -803,7 +823,7 @@
   Future<List<String?>> resolveUrisToPathsBatch(List<Uri> uris) async {
     // First find the set of URIs we don't already have results for.
     final requiredUris = uris
-        .where((uri) => !uri.isScheme('file'))
+        .where(isResolvableUri)
         .where((uri) => !_resolvedPaths.containsKey(uri.toString()))
         .toSet() // Take only distinct values.
         .toList();
@@ -817,17 +837,24 @@
       completers.forEach(
         (uri, completer) => _resolvedPaths[uri] = completer.future,
       );
-      final results =
-          await _manager._lookupResolvedPackageUris(isolate, requiredUris);
-      if (results == null) {
-        // If no result, all of the results are null.
-        completers.forEach((uri, completer) => completer.complete(null));
-      } else {
-        // Otherwise, complete each one by index with the corresponding value.
-        results.map(_convertUriToFilePath).forEachIndexed((i, result) {
-          final uri = requiredUris[i].toString();
-          completers[uri]!.complete(result);
-        });
+      try {
+        final results =
+            await _manager._lookupResolvedPackageUris(isolate, requiredUris);
+        if (results == null) {
+          // If no result, all of the results are null.
+          completers.forEach((uri, completer) => completer.complete(null));
+        } else {
+          // Otherwise, complete each one by index with the corresponding value.
+          results.map(_convertUriToFilePath).forEachIndexed((i, result) {
+            final uri = requiredUris[i].toString();
+            completers[uri]!.complete(result);
+          });
+        }
+      } catch (e) {
+        // We can't leave dangling completers here because others may already
+        // be waiting on them, so propogate the error to them.
+        completers.forEach((uri, completer) => completer.completeError(e));
+        rethrow;
       }
     }
 
diff --git a/pkg/dds/lib/src/dap/utils.dart b/pkg/dds/lib/src/dap/utils.dart
new file mode 100644
index 0000000..c455837
--- /dev/null
+++ b/pkg/dds/lib/src/dap/utils.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:stack_trace/stack_trace.dart' as stack;
+
+/// Returns whether this URI has a scheme that can be resolved to a file path
+/// via the VM Service.
+bool isResolvableUri(Uri uri) {
+  return !uri.isScheme('file') &&
+      // Parsed stack frames may have URIs with no scheme and the text
+      // "unparsed" if they looked like stack frames but had no file
+      // information.
+      !uri.isScheme('');
+}
+
+/// Attempts to parse a line as a stack frame in order to read path/line/col
+/// information.
+///
+/// It should not be assumed that if a [stack.Frame] is returned that the input
+/// was necessarily a stack frame or that calling `toString` will return the
+/// original input text.
+stack.Frame? parseStackFrame(String line) {
+  // Because we split on \n, on Windows there may be trailing \r which prevents
+  // package:stack_trace from parsing correctly.
+  line = line.trim();
+
+  /// Helper to try parsing a frame with [parser], returning `null` if it
+  /// fails to parse.
+  stack.Frame? tryParseFrame(stack.Frame Function(String) parser) {
+    final frame = parser(line);
+    return frame is stack.UnparsedFrame ? null : frame;
+  }
+
+  // Try different formats of stack frames.
+  // pkg:stack_trace does not have a generic Frame.parse() and Trace.parse()
+  // doesn't work well when the content includes non-stack-frame lines
+  // (https://github.com/dart-lang/stack_trace/issues/115).
+  return tryParseFrame((line) => stack.Frame.parseVM(line)) ??
+      // TODO(dantup): Tidy up when constructor tear-offs are available.
+      tryParseFrame((line) => stack.Frame.parseV8(line)) ??
+      tryParseFrame((line) => stack.Frame.parseSafari(line)) ??
+      tryParseFrame((line) => stack.Frame.parseFirefox(line)) ??
+      tryParseFrame((line) => stack.Frame.parseIE(line)) ??
+      tryParseFrame((line) => stack.Frame.parseFriendly(line));
+}
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index 7de1b71..000a15b 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -24,7 +24,7 @@
 import 'client.dart';
 import 'client_manager.dart';
 import 'constants.dart';
-import 'devtools/devtools_handler.dart';
+import 'devtools/handler.dart';
 import 'expression_evaluator.dart';
 import 'isolate_manager.dart';
 import 'stream_manager.dart';
@@ -152,14 +152,30 @@
     // Start the DDS server. Run in an error Zone to ensure that asynchronous
     // exceptions encountered during request handling are handled, as exceptions
     // thrown during request handling shouldn't take down the entire service.
-    _server = await runZonedGuarded(
-      () async => await io.serve(handler, host, port),
+    late String errorMessage;
+    final tmpServer = await runZonedGuarded(
+      () async {
+        try {
+          return await io.serve(handler, host, port);
+        } on SocketException catch (e) {
+          errorMessage = e.message;
+          if (e.osError != null) {
+            errorMessage += ' (${e.osError!.message})';
+          }
+          errorMessage += ': ${e.address?.host}:${e.port}';
+          return null;
+        }
+      },
       (error, stack) {
         if (shouldLogRequests) {
           print('Asynchronous error: $error\n$stack');
         }
       },
-    )!;
+    );
+    if (tmpServer == null) {
+      throw DartDevelopmentServiceException.connectionIssue(errorMessage);
+    }
+    _server = tmpServer;
 
     final tmpUri = Uri(
       scheme: 'http',
@@ -297,7 +313,7 @@
       // the VM service.
       final String buildDir =
           _devToolsConfiguration!.customBuildDirectoryPath.toFilePath();
-      return devtoolsHandler(
+      return defaultHandler(
         dds: this,
         buildDir: buildDir,
         notFoundHandler: proxyHandler(remoteVmServiceUri),
diff --git a/pkg/dds/lib/src/devtools/client.dart b/pkg/dds/lib/src/devtools/client.dart
new file mode 100644
index 0000000..af82b55
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/client.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:collection/collection.dart';
+import 'package:devtools_shared/devtools_server.dart';
+import 'package:json_rpc_2/src/peer.dart' as json_rpc;
+import 'package:meta/meta.dart';
+import 'package:sse/src/server/sse_handler.dart';
+import 'package:stream_channel/stream_channel.dart';
+
+class LoggingMiddlewareSink<S> implements StreamSink<S> {
+  LoggingMiddlewareSink(this.sink);
+
+  @override
+  void add(S event) {
+    print('DevTools SSE response: $event');
+    sink.add(event);
+  }
+
+  @override
+  void addError(Object error, [StackTrace? stackTrace]) {
+    print('DevTools SSE error response: $error');
+    sink.addError(error);
+  }
+
+  @override
+  Future addStream(Stream<S> stream) {
+    return sink.addStream(stream);
+  }
+
+  @override
+  Future close() => sink.close();
+
+  @override
+  Future get done => sink.done;
+
+  final StreamSink sink;
+}
+
+/// A connection between a DevTools front-end app and the DevTools server.
+///
+/// see `packages/devtools_app/lib/src/server_connection.dart`.
+class ClientManager {
+  ClientManager({required this.requestNotificationPermissions});
+
+  /// Whether to immediately request notification permissions when a client connects.
+  /// Otherwise permission will be requested only with the first notification.
+  final bool requestNotificationPermissions;
+  final List<DevToolsClient> _clients = [];
+
+  void acceptClient(SseConnection connection, {bool enableLogging = false}) {
+    final client = DevToolsClient.fromSSEConnection(
+      connection,
+      enableLogging,
+    );
+    if (requestNotificationPermissions) {
+      client.enableNotifications();
+    }
+    _clients.add(client);
+    connection.sink.done.then((_) => _clients.remove(client));
+  }
+
+  /// Finds an active DevTools instance that is not already connecting to
+  /// a VM service that we can reuse (for example if a user stopped debugging
+  /// and it disconnected, then started debugging again, we want to reuse
+  /// the open DevTools window).
+  DevToolsClient? findReusableClient() {
+    return _clients.firstWhereOrNull(
+      (c) => !c.hasConnection && !c.embedded,
+    );
+  }
+
+  /// Finds a client that may already be connected to this VM Service.
+  DevToolsClient? findExistingConnectedReusableClient(Uri vmServiceUri) {
+    // Checking the whole URI will fail if DevTools converted it from HTTP to
+    // WS, so just check the host, port and first segment of path (token).
+    return _clients.firstWhereOrNull(
+      (c) =>
+          c.hasConnection &&
+          !c.embedded &&
+          _areSameVmServices(c.vmServiceUri!, vmServiceUri),
+    );
+  }
+
+  @override
+  String toString() {
+    return _clients.map((c) {
+      return '${c.hasConnection.toString().padRight(5)} '
+          '${c.currentPage?.padRight(12)} ${c.vmServiceUri.toString()}';
+    }).join('\n');
+  }
+
+  Map<String, dynamic> toJson(dynamic id) => {
+        'id': id,
+        'result': {
+          'clients': _clients.map((e) => e.toJson()).toList(),
+        }
+      };
+
+  bool _areSameVmServices(Uri uri1, Uri uri2) {
+    return uri1.host == uri2.host &&
+        uri1.port == uri2.port &&
+        uri1.pathSegments.isNotEmpty &&
+        uri2.pathSegments.isNotEmpty &&
+        uri1.pathSegments[0] == uri2.pathSegments[0];
+  }
+}
+
+/// Represents a DevTools client connection to the DevTools server API.
+class DevToolsClient {
+  factory DevToolsClient.fromSSEConnection(
+    SseConnection sse,
+    bool loggingEnabled,
+  ) {
+    Stream<String> stream = sse.stream;
+    StreamSink sink = sse.sink;
+    return DevToolsClient(
+      stream: stream,
+      sink: sink,
+      loggingEnabled: loggingEnabled,
+    );
+  }
+
+  @visibleForTesting
+  DevToolsClient({
+    required Stream<String> stream,
+    required StreamSink sink,
+    bool loggingEnabled = false,
+  }) {
+    if (loggingEnabled) {
+      stream = stream.map<String>((String e) {
+        print('DevTools SSE request: $e');
+        return e;
+      });
+      sink = LoggingMiddlewareSink(sink);
+    }
+
+    _devToolsPeer = json_rpc.Peer(
+      StreamChannel(stream, sink as StreamSink<String>),
+      strictProtocolChecks: false,
+    );
+    _registerJsonRpcMethods();
+    _devToolsPeer.listen();
+  }
+
+  void _registerJsonRpcMethods() {
+    _devToolsPeer.registerMethod('connected', (parameters) {
+      _vmServiceUri = Uri.parse(parameters['uri'].asString);
+    });
+
+    _devToolsPeer.registerMethod('disconnected', (parameters) {
+      _vmServiceUri = null;
+    });
+
+    _devToolsPeer.registerMethod('currentPage', (parameters) {
+      _currentPage = parameters['id'].asString;
+      _embedded = parameters['embedded'].asBool;
+    });
+
+    _devToolsPeer.registerMethod('getPreferenceValue', (parameters) {
+      final key = parameters['key'].asString;
+      final value = ServerApi.devToolsPreferences.properties[key];
+      return value;
+    });
+
+    _devToolsPeer.registerMethod('setPreferenceValue', (parameters) {
+      final key = parameters['key'].asString;
+      final value = parameters['value'].value;
+      ServerApi.devToolsPreferences.properties[key] = value;
+    });
+  }
+
+  /// Notify the DevTools client to connect to a specific VM service instance.
+  void connectToVmService(Uri uri, bool notifyUser) {
+    _devToolsPeer.sendNotification('connectToVm', {
+      'uri': uri.toString(),
+      'notify': notifyUser,
+    });
+  }
+
+  void notify() => _devToolsPeer.sendNotification('notify');
+
+  /// Enable notifications to the user from this DevTools client.
+  void enableNotifications() =>
+      _devToolsPeer.sendNotification('enableNotifications');
+
+  /// Notify the DevTools client to show a specific page.
+  void showPage(String pageId) {
+    _devToolsPeer.sendNotification('showPage', {
+      'page': pageId,
+    });
+  }
+
+  Map<String, dynamic> toJson() => {
+        'hasConnection': hasConnection,
+        'currentPage': currentPage,
+        'embedded': embedded,
+        'vmServiceUri': vmServiceUri?.toString(),
+      };
+
+  /// The current DevTools page displayed by this client.
+  String? get currentPage => _currentPage;
+  String? _currentPage;
+
+  /// Returns true if this DevTools client is embedded.
+  bool get embedded => _embedded;
+  bool _embedded = false;
+
+  /// Returns the VM service URI that the DevTools client is currently
+  /// connected to. Returns null if the client is not connected to a process.
+  Uri? get vmServiceUri => _vmServiceUri;
+  Uri? _vmServiceUri;
+
+  bool get hasConnection => _vmServiceUri != null;
+
+  late json_rpc.Peer _devToolsPeer;
+}
diff --git a/pkg/dds/lib/src/devtools/devtools_client.dart b/pkg/dds/lib/src/devtools/devtools_client.dart
deleted file mode 100644
index e5ec54e..0000000
--- a/pkg/dds/lib/src/devtools/devtools_client.dart
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. 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:devtools_shared/devtools_server.dart';
-import 'package:json_rpc_2/src/server.dart' as json_rpc;
-import 'package:sse/src/server/sse_handler.dart';
-import 'package:stream_channel/stream_channel.dart';
-
-class LoggingMiddlewareSink<S> implements StreamSink<S> {
-  LoggingMiddlewareSink(this.sink);
-
-  @override
-  void add(S event) {
-    print('DevTools SSE response: $event');
-    sink.add(event);
-  }
-
-  @override
-  void addError(Object error, [StackTrace? stackTrace]) {
-    print('DevTools SSE error response: $error');
-    sink.addError(error);
-  }
-
-  @override
-  Future addStream(Stream<S> stream) {
-    return sink.addStream(stream);
-  }
-
-  @override
-  Future close() => sink.close();
-
-  @override
-  Future get done => sink.done;
-
-  final StreamSink sink;
-}
-
-/// Represents a DevTools client connection to the DevTools server API.
-class DevToolsClient {
-  DevToolsClient.fromSSEConnection(
-    SseConnection sse,
-    bool loggingEnabled,
-  ) {
-    Stream<String> stream = sse.stream;
-    StreamSink sink = sse.sink;
-
-    if (loggingEnabled) {
-      stream = stream.map<String>((String e) {
-        print('DevTools SSE request: $e');
-        return e;
-      });
-      sink = LoggingMiddlewareSink(sink);
-    }
-
-    _server = json_rpc.Server(
-      StreamChannel(stream, sink as StreamSink<String>),
-      strictProtocolChecks: false,
-    );
-    _registerJsonRpcMethods();
-    _server.listen();
-  }
-
-  void _registerJsonRpcMethods() {
-    _server.registerMethod('connected', (parameters) {
-      // Nothing to do here.
-    });
-
-    _server.registerMethod('currentPage', (parameters) {
-      // Nothing to do here.
-    });
-
-    _server.registerMethod('disconnected', (parameters) {
-      // Nothing to do here.
-    });
-
-    _server.registerMethod('getPreferenceValue', (parameters) {
-      final key = parameters['key'].asString;
-      final value = ServerApi.devToolsPreferences.properties[key];
-      return value;
-    });
-
-    _server.registerMethod('setPreferenceValue', (parameters) {
-      final key = parameters['key'].asString;
-      final value = parameters['value'].value;
-      ServerApi.devToolsPreferences.properties[key] = value;
-    });
-  }
-
-  late json_rpc.Server _server;
-}
diff --git a/pkg/dds/lib/src/devtools/devtools_handler.dart b/pkg/dds/lib/src/devtools/devtools_handler.dart
deleted file mode 100644
index 3b55bfb..0000000
--- a/pkg/dds/lib/src/devtools/devtools_handler.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. 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:dds/src/constants.dart';
-import 'package:devtools_shared/devtools_server.dart';
-import 'package:shelf/shelf.dart';
-import 'package:shelf_static/shelf_static.dart';
-import 'package:sse/server/sse_handler.dart';
-
-import '../dds_impl.dart';
-import 'devtools_client.dart';
-
-/// Returns a [Handler] which handles serving DevTools and the DevTools server
-/// API under $DDS_URI/devtools/.
-///
-/// [buildDir] is the path to the pre-compiled DevTools instance to be served.
-///
-/// [notFoundHandler] is a [Handler] to which requests that could not be handled
-/// by the DevTools handler are forwarded (e.g., a proxy to the VM service).
-FutureOr<Handler> devtoolsHandler({
-  required DartDevelopmentServiceImpl dds,
-  required String buildDir,
-  required Handler notFoundHandler,
-}) {
-  // Serves the web assets for DevTools.
-  final devtoolsAssetHandler = createStaticHandler(
-    buildDir,
-    defaultDocument: 'index.html',
-  );
-
-  // Support DevTools client-server interface via SSE.
-  // Note: the handler path needs to match the full *original* path, not the
-  // current request URL (we remove '/devtools' in the initial router but we
-  // need to include it here).
-  const devToolsSseHandlerPath = '/devtools/api/sse';
-  final devToolsApiHandler = SseHandler(
-    dds.authCodesEnabled
-        ? Uri.parse('/${dds.authCode}$devToolsSseHandlerPath')
-        : Uri.parse(devToolsSseHandlerPath),
-    keepAlive: sseKeepAlive,
-  );
-
-  devToolsApiHandler.connections.rest.listen(
-    (sseConnection) => DevToolsClient.fromSSEConnection(
-      sseConnection,
-      dds.shouldLogRequests,
-    ),
-  );
-
-  final devtoolsHandler = (Request request) {
-    // If the request isn't of the form api/<method> assume it's a request for
-    // DevTools assets.
-    if (request.url.pathSegments.length < 2 ||
-        request.url.pathSegments.first != 'api') {
-      return devtoolsAssetHandler(request);
-    }
-    final method = request.url.pathSegments[1];
-    if (method == 'ping') {
-      // Note: we have an 'OK' body response, otherwise the response has an
-      // incorrect status code (204 instead of 200).
-      return Response.ok('OK');
-    }
-    if (method == 'sse') {
-      return devToolsApiHandler.handler(request);
-    }
-    if (!ServerApi.canHandle(request)) {
-      return Response.notFound('$method is not a valid API');
-    }
-    return ServerApi.handle(request);
-  };
-
-  return (request) {
-    final pathSegments = request.url.pathSegments;
-    if (pathSegments.isEmpty || pathSegments.first != 'devtools') {
-      return notFoundHandler(request);
-    }
-    // Forward all requests to /devtools/* to the DevTools handler.
-    request = request.change(path: 'devtools');
-    return devtoolsHandler(request);
-  };
-}
diff --git a/pkg/dds/lib/src/devtools/handler.dart b/pkg/dds/lib/src/devtools/handler.dart
new file mode 100644
index 0000000..d323f9d
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/handler.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:devtools_shared/devtools_server.dart';
+import 'package:shelf/shelf.dart';
+import 'package:shelf_static/shelf_static.dart';
+import 'package:sse/server/sse_handler.dart';
+
+import '../constants.dart';
+import '../dds_impl.dart';
+import 'client.dart';
+
+/// Returns a [Handler] which handles serving DevTools and the DevTools server
+/// API.
+///
+/// [buildDir] is the path to the pre-compiled DevTools instance to be served.
+///
+/// [notFoundHandler] is a [Handler] to which requests that could not be handled
+/// by the DevTools handler are forwarded (e.g., a proxy to the VM service).
+///
+/// If [dds] is null, DevTools is not being served by a DDS instance and is
+/// served by a standalone server (see `package:dds/devtools_server.dart`).
+FutureOr<Handler> defaultHandler({
+  DartDevelopmentServiceImpl? dds,
+  required String buildDir,
+  ClientManager? clientManager,
+  Handler? notFoundHandler,
+}) {
+  // Serves the web assets for DevTools.
+  final devtoolsAssetHandler = createStaticHandler(
+    buildDir,
+    defaultDocument: 'index.html',
+  );
+
+  // Support DevTools client-server interface via SSE.
+  // Note: the handler path needs to match the full *original* path, not the
+  // current request URL (we remove '/devtools' in the initial router but we
+  // need to include it here).
+  final devToolsSseHandlerPath = dds != null ? '/devtools/api/sse' : '/api/sse';
+  final devToolsApiHandler = SseHandler(
+    (dds?.authCodesEnabled ?? false)
+        ? Uri.parse('/${dds!.authCode}$devToolsSseHandlerPath')
+        : Uri.parse(devToolsSseHandlerPath),
+    keepAlive: sseKeepAlive,
+  );
+
+  clientManager ??= ClientManager(requestNotificationPermissions: false);
+
+  devToolsApiHandler.connections.rest.listen(
+    (sseConnection) => clientManager!.acceptClient(
+      sseConnection,
+      enableLogging: dds?.shouldLogRequests ?? false,
+    ),
+  );
+
+  final devtoolsHandler = (Request request) {
+    // If the request isn't of the form api/<method> assume it's a request for
+    // DevTools assets.
+    if (request.url.pathSegments.length < 2 ||
+        request.url.pathSegments.first != 'api') {
+      return devtoolsAssetHandler(request);
+    }
+    final method = request.url.pathSegments[1];
+    if (method == 'ping') {
+      // Note: we have an 'OK' body response, otherwise the response has an
+      // incorrect status code (204 instead of 200).
+      return Response.ok('OK');
+    }
+    if (method == 'sse') {
+      return devToolsApiHandler.handler(request);
+    }
+    if (!ServerApi.canHandle(request)) {
+      return Response.notFound('$method is not a valid API');
+    }
+    return ServerApi.handle(request);
+  };
+
+  return (request) {
+    if (notFoundHandler != null) {
+      final pathSegments = request.url.pathSegments;
+      if (pathSegments.isEmpty || pathSegments.first != 'devtools') {
+        return notFoundHandler(request);
+      }
+      // Forward all requests to /devtools/* to the DevTools handler.
+      request = request.change(path: 'devtools');
+    }
+    return devtoolsHandler(request);
+  };
+}
diff --git a/pkg/dds/lib/src/devtools/machine_mode_command_handler.dart b/pkg/dds/lib/src/devtools/machine_mode_command_handler.dart
new file mode 100644
index 0000000..5b65d4c
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/machine_mode_command_handler.dart
@@ -0,0 +1,429 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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(https://github.com/dart-lang/sdk/issues/48161): investigate whether or
+// not machine mode is still relevant.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:devtools_shared/devtools_server.dart';
+import 'package:devtools_shared/devtools_shared.dart';
+import 'package:vm_service/vm_service.dart';
+
+import '../../devtools_server.dart';
+import 'utils.dart';
+
+class MachineModeCommandHandler {
+  static const launchDevToolsService = 'launchDevTools';
+  static const copyAndCreateDevToolsFile = 'copyAndCreateDevToolsFile';
+  static const restoreDevToolsFile = 'restoreDevToolsFiles';
+  static const errorLaunchingBrowserCode = 500;
+  static const bool machineMode = true;
+
+  MachineModeCommandHandler({required this.server});
+
+  /// The server instance associated with this client.
+  final DevToolsServer server;
+
+  // Only used for testing DevToolsUsage (used by survey).
+  DevToolsUsage? _devToolsUsage;
+
+  File? _devToolsBackup;
+
+  static bool _isValidVmServiceUri(Uri? uri) {
+    // Lots of things are considered valid URIs (including empty strings and
+    // single letters) since they can be relative, so we need to do some extra
+    // checks.
+    return uri != null &&
+        uri.isAbsolute &&
+        (uri.isScheme('ws') ||
+            uri.isScheme('wss') ||
+            uri.isScheme('http') ||
+            uri.isScheme('https'));
+  }
+
+  Future<void> initialize({
+    required String devToolsUrl,
+    required bool headlessMode,
+  }) async {
+    final Stream<Map<String, dynamic>> _stdinCommandStream = stdin
+        .transform<String>(utf8.decoder)
+        .transform<String>(const LineSplitter())
+        .where((String line) => line.startsWith('{') && line.endsWith('}'))
+        .map<Map<String, dynamic>>((String line) {
+      return json.decode(line) as Map<String, dynamic>;
+    });
+
+    // Example input:
+    // {
+    //   "id":0,
+    //   "method":"vm.register",
+    //   "params":{
+    //     "uri":"<vm-service-uri-here>",
+    //   }
+    // }
+    _stdinCommandStream.listen((Map<String, dynamic> json) async {
+      // ID can be String, int or null
+      final dynamic id = json['id'];
+      final Map<String, dynamic> params = json['params'];
+      final method = json['method'];
+      switch (method) {
+        case 'vm.register':
+          await _handleVmRegister(id, params, headlessMode, devToolsUrl);
+          break;
+        case 'devTools.launch':
+          await _handleDevToolsLaunch(id, params, headlessMode, devToolsUrl);
+          break;
+        case 'client.list':
+          _handleClientsList(id, params);
+          break;
+        case 'devTools.survey':
+          _handleDevToolsSurvey(id, params);
+          break;
+        default:
+          DevToolsUtils.printOutput(
+            'Unknown method $method',
+            {
+              'id': id,
+              'error': 'Unknown method $method',
+            },
+            machineMode: machineMode,
+          );
+      }
+    });
+  }
+
+  Future<void> _handleVmRegister(
+    dynamic id,
+    Map<String, dynamic> params,
+    bool headlessMode,
+    String devToolsUrl,
+  ) async {
+    if (!params.containsKey('uri')) {
+      DevToolsUtils.printOutput(
+        'Invalid input: $params does not contain the key \'uri\'',
+        {
+          'id': id,
+          'error': 'Invalid input: $params does not contain the key \'uri\'',
+        },
+        machineMode: machineMode,
+      );
+    }
+
+    // params['uri'] should contain a vm service uri.
+    final uri = Uri.tryParse(params['uri']);
+
+    if (_isValidVmServiceUri(uri)) {
+      await registerLaunchDevToolsService(
+        uri!,
+        id,
+        devToolsUrl,
+        headlessMode,
+      );
+    } else {
+      DevToolsUtils.printOutput(
+        'Uri must be absolute with a http, https, ws or wss scheme',
+        {
+          'id': id,
+          'error': 'Uri must be absolute with a http, https, ws or wss scheme',
+        },
+        machineMode: machineMode,
+      );
+    }
+  }
+
+  Future<void> _handleDevToolsLaunch(
+    dynamic id,
+    Map<String, dynamic> params,
+    bool headlessMode,
+    String devToolsUrl,
+  ) async {
+    if (!params.containsKey('vmServiceUri')) {
+      DevToolsUtils.printOutput(
+        "Invalid input: $params does not contain the key 'vmServiceUri'",
+        {
+          'id': id,
+          'error':
+              "Invalid input: $params does not contain the key e'vmServiceUri'",
+        },
+        machineMode: machineMode,
+      );
+    }
+
+    // params['vmServiceUri'] should contain a vm service uri.
+    final vmServiceUri = Uri.tryParse(params['vmServiceUri'])!;
+
+    if (_isValidVmServiceUri(vmServiceUri)) {
+      try {
+        final result = await server.launchDevTools(
+          params,
+          vmServiceUri,
+          devToolsUrl,
+          headlessMode,
+          machineMode,
+        );
+        DevToolsUtils.printOutput(
+          'DevTools launched',
+          {'id': id, 'result': result},
+          machineMode: machineMode,
+        );
+      } catch (e, s) {
+        DevToolsUtils.printOutput(
+          'Failed to launch browser: $e\n$s',
+          {'id': id, 'error': 'Failed to launch browser: $e\n$s'},
+          machineMode: machineMode,
+        );
+      }
+    } else {
+      DevToolsUtils.printOutput(
+        'VM Service URI must be absolute with a http, https, ws or wss scheme',
+        {
+          'id': id,
+          'error':
+              'VM Service Uri must be absolute with a http, https, ws or wss scheme',
+        },
+        machineMode: machineMode,
+      );
+    }
+  }
+
+  void _handleClientsList(dynamic id, Map<String, dynamic> params) {
+    DevToolsUtils.printOutput(
+      server.clientManager.toString(),
+      server.clientManager.toJson(id),
+      machineMode: machineMode,
+    );
+  }
+
+  void _handleDevToolsSurvey(dynamic id, Map<String, dynamic> params) {
+    _devToolsUsage ??= DevToolsUsage();
+    final String surveyRequest = params['surveyRequest'];
+    final String value = params['value'];
+
+    switch (surveyRequest) {
+      case copyAndCreateDevToolsFile:
+        // Backup and delete ~/.devtools file.
+        if (backupAndCreateDevToolsStore()) {
+          _devToolsUsage = null;
+          DevToolsUtils.printOutput(
+            'DevTools Survey',
+            {
+              'id': id,
+              'result': {
+                // TODO(bkonyi): fix incorrect spelling of "success" here and
+                // below once we figure out the impact of changing this key.
+                'success': true,
+              },
+            },
+            machineMode: machineMode,
+          );
+        }
+        break;
+      case restoreDevToolsFile:
+        _devToolsUsage = null;
+        final content = restoreDevToolsStore();
+        if (content != null) {
+          DevToolsUtils.printOutput(
+            'DevTools Survey',
+            {
+              'id': id,
+              'result': {
+                'success': true,
+                'content': content,
+              },
+            },
+            machineMode: machineMode,
+          );
+
+          _devToolsUsage = null;
+        }
+        break;
+      case apiSetActiveSurvey:
+        _devToolsUsage!.activeSurvey = value;
+        DevToolsUtils.printOutput(
+          'DevTools Survey',
+          {
+            'id': id,
+            'result': {
+              'success': _devToolsUsage!.activeSurvey == value,
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+            },
+          },
+          machineMode: machineMode,
+        );
+        break;
+      case apiGetSurveyActionTaken:
+        DevToolsUtils.printOutput(
+          'DevTools Survey',
+          {
+            'id': id,
+            'result': {
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
+            },
+          },
+          machineMode: machineMode,
+        );
+        break;
+      case apiSetSurveyActionTaken:
+        _devToolsUsage!.surveyActionTaken = jsonDecode(value);
+        DevToolsUtils.printOutput(
+          'DevTools Survey',
+          {
+            'id': id,
+            'result': {
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
+            },
+          },
+          machineMode: machineMode,
+        );
+        break;
+      case apiGetSurveyShownCount:
+        DevToolsUtils.printOutput(
+          'DevTools Survey',
+          {
+            'id': id,
+            'result': {
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+              'surveyShownCount': _devToolsUsage!.surveyShownCount,
+            },
+          },
+          machineMode: machineMode,
+        );
+        break;
+      case apiIncrementSurveyShownCount:
+        _devToolsUsage!.incrementSurveyShownCount();
+        DevToolsUtils.printOutput(
+          'DevTools Survey',
+          {
+            'id': id,
+            'result': {
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+              'surveyShownCount': _devToolsUsage!.surveyShownCount,
+            },
+          },
+          machineMode: machineMode,
+        );
+        break;
+      default:
+        DevToolsUtils.printOutput(
+          'Unknown DevTools Survey Request $surveyRequest',
+          {
+            'id': id,
+            'result': {
+              'activeSurvey': _devToolsUsage!.activeSurvey,
+              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
+              'surveyShownCount': _devToolsUsage!.surveyShownCount,
+            },
+          },
+          machineMode: machineMode,
+        );
+    }
+  }
+
+  bool backupAndCreateDevToolsStore() {
+    assert(_devToolsBackup == null);
+    final devToolsStore = File(
+      LocalFileSystem.devToolsStoreLocation(),
+    );
+    if (devToolsStore.existsSync()) {
+      _devToolsBackup = devToolsStore
+          .copySync('${LocalFileSystem.devToolsDir()}/.devtools_backup_test');
+      devToolsStore.deleteSync();
+    }
+    return true;
+  }
+
+  String? restoreDevToolsStore() {
+    if (_devToolsBackup != null) {
+      // Read the current ~/.devtools file
+      LocalFileSystem.maybeMoveLegacyDevToolsStore();
+
+      final devToolsStore = File(LocalFileSystem.devToolsStoreLocation());
+      final content = devToolsStore.readAsStringSync();
+
+      // Delete the temporary ~/.devtools file
+      devToolsStore.deleteSync();
+      if (_devToolsBackup!.existsSync()) {
+        // Restore the backup ~/.devtools file we created in
+        // backupAndCreateDevToolsStore.
+        _devToolsBackup!.copySync(LocalFileSystem.devToolsStoreLocation());
+        _devToolsBackup!.deleteSync();
+        _devToolsBackup = null;
+      }
+      return content;
+    }
+    return null;
+  }
+
+  Future<void> registerLaunchDevToolsService(
+    Uri vmServiceUri,
+    dynamic id,
+    String devToolsUrl,
+    bool headlessMode,
+  ) async {
+    try {
+      // Connect to the vm service and register a method to launch DevTools in
+      // chrome.
+      final service = await DevToolsUtils.connectToVmService(vmServiceUri);
+      if (service == null) return;
+
+      service.registerServiceCallback(
+        launchDevToolsService,
+        (params) async {
+          try {
+            await server.launchDevTools(
+              params,
+              vmServiceUri,
+              devToolsUrl,
+              headlessMode,
+              machineMode,
+            );
+            return {
+              'result': Success().toJson(),
+            };
+          } catch (e, s) {
+            // Note: It's critical that we return responses in exactly the right format
+            // or the VM will unregister the service. The objects must match JSON-RPC
+            // however a successful response must also have a "type" field in its result.
+            // Otherwise, we can return an error object (instead of result) that includes
+            // code + message.
+            return {
+              'error': {
+                'code': errorLaunchingBrowserCode,
+                'message': 'Failed to launch browser: $e\n$s',
+              },
+            };
+          }
+        },
+      );
+
+      final registerServiceMethodName = 'registerService';
+      await service.callMethod(registerServiceMethodName, args: {
+        'service': launchDevToolsService,
+        'alias': 'DevTools Server',
+      });
+
+      DevToolsUtils.printOutput(
+        'Successfully registered launchDevTools service',
+        {
+          'id': id,
+          'result': {'success': true},
+        },
+        machineMode: machineMode,
+      );
+    } catch (e) {
+      DevToolsUtils.printOutput(
+        'Unable to connect to VM service at $vmServiceUri: $e',
+        {
+          'id': id,
+          'error': 'Unable to connect to VM service at $vmServiceUri: $e',
+        },
+        machineMode: machineMode,
+      );
+    }
+  }
+}
diff --git a/pkg/dds/lib/src/devtools/memory_profile.dart b/pkg/dds/lib/src/devtools/memory_profile.dart
new file mode 100644
index 0000000..f99caf4
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/memory_profile.dart
@@ -0,0 +1,399 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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(https://github.com/dart-lang/sdk/issues/48161) investigate whether we
+// can delete this file or not.
+
+import 'dart:async';
+import 'dart:io' as io;
+
+import 'package:devtools_shared/devtools_shared.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'service_registrations.dart' as service_registrations;
+
+class MemoryProfile {
+  MemoryProfile(this.service, String profileFilename, this._verboseMode) {
+    onConnectionClosed.listen(_handleConnectionStop);
+
+    service!.onEvent('Service').listen(handleServiceEvent);
+
+    _jsonFile = MemoryJsonFile.create(profileFilename);
+
+    _hookUpEvents();
+  }
+
+  late MemoryJsonFile _jsonFile;
+
+  final bool _verboseMode;
+
+  void _hookUpEvents() async {
+    final streamIds = [
+      EventStreams.kExtension,
+      EventStreams.kGC,
+      EventStreams.kIsolate,
+      EventStreams.kLogging,
+      EventStreams.kStderr,
+      EventStreams.kStdout,
+      // TODO(Kenzi): Collect timeline data too.
+      // EventStreams.kTimeline,
+      EventStreams.kVM,
+      EventStreams.kService,
+    ];
+
+    await Future.wait(streamIds.map((String id) async {
+      try {
+        await service!.streamListen(id);
+      } catch (e) {
+        if (id.endsWith('Logging')) {
+          // Don't complain about '_Logging' or 'Logging' events (new VMs don't
+          // have the private names, and older ones don't have the public ones).
+        } else {
+          print("Service client stream not supported: '$id'\n  $e");
+        }
+      }
+    }));
+  }
+
+  bool get hasConnection => service != null;
+
+  void handleServiceEvent(Event e) {
+    if (e.kind == EventKind.kServiceRegistered) {
+      final serviceName = e.service!;
+      _registeredMethodsForService
+          .putIfAbsent(serviceName, () => [])
+          .add(e.method!);
+    }
+
+    if (e.kind == EventKind.kServiceUnregistered) {
+      final serviceName = e.service!;
+      _registeredMethodsForService.remove(serviceName);
+    }
+  }
+
+  late IsolateRef _selectedIsolate;
+
+  Future<Response?> getAdbMemoryInfo() async {
+    return await callService(
+      service_registrations.flutterMemory.service,
+      isolateId: _selectedIsolate.id,
+    );
+  }
+
+  /// Call a service that is registered by exactly one client.
+  Future<Response?> callService(
+    String name, {
+    String? isolateId,
+    Map<String, dynamic>? args,
+  }) async {
+    final registered = _registeredMethodsForService[name] ?? const [];
+    if (registered.isEmpty) {
+      throw Exception('There are no registered methods for service "$name"');
+    }
+    return service!.callMethod(
+      registered.first,
+      isolateId: isolateId,
+      args: args,
+    );
+  }
+
+  Map<String, List<String>> get registeredMethodsForService =>
+      _registeredMethodsForService;
+  final _registeredMethodsForService = <String, List<String>>{};
+
+  static const Duration updateDelay = Duration(milliseconds: 500);
+
+  VmService? service;
+
+  late Timer _pollingTimer;
+
+  /// Polled VM current RSS.
+  int? processRss;
+
+  final Map<String, List<HeapSpace>> isolateHeaps = <String, List<HeapSpace>>{};
+
+  final List<HeapSample> samples = <HeapSample>[];
+
+  AdbMemoryInfo? adbMemoryInfo;
+
+  late EventSample eventSample;
+
+  RasterCache? rasterCache;
+
+  late int heapMax;
+
+  Stream<void> get onConnectionClosed => _connectionClosedController.stream;
+  final _connectionClosedController = StreamController<void>.broadcast();
+
+  void _handleConnectionStop(dynamic event) {
+    // TODO(terry): Gracefully handle connection loss.
+  }
+
+  // TODO(terry): Investigate moving code from this point through end of class to devtools_shared.
+  void startPolling() {
+    _pollingTimer = Timer(updateDelay, _pollMemory);
+    service!.onGCEvent.listen(_handleGCEvent);
+  }
+
+  void _handleGCEvent(Event event) {
+    //final bool ignore = event.json['reason'] == 'compact';
+    final json = event.json!;
+    final List<HeapSpace> heaps = <HeapSpace>[
+      HeapSpace.parse(json['new'])!,
+      HeapSpace.parse(json['old'])!
+    ];
+    _updateGCEvent(event.isolate!.id!, heaps);
+    // TODO(terry): expose when GC occured as markers in memory timeline.
+  }
+
+  void stopPolling() {
+    _pollingTimer.cancel();
+    service = null;
+  }
+
+  Future<void> _pollMemory() async {
+    final service = this.service!;
+    final VM vm = await service.getVM();
+
+    // TODO(terry): Need to handle a possible Sentinel being returned.
+    final List<Isolate?> isolates =
+        await Future.wait(vm.isolates!.map((IsolateRef ref) async {
+      try {
+        return await service.getIsolate(ref.id!);
+      } catch (e) {
+        // TODO(terry): Seem to sometimes get a sentinel not sure how? VM issue?
+        // Unhandled Exception: type 'Sentinel' is not a subtype of type 'FutureOr<Isolate>'
+        print('Error [MEMORY_PROTOCOL]: $e');
+        return Future<Isolate?>.value();
+      }
+    }));
+
+    // Polls for current Android meminfo using:
+    //    > adb shell dumpsys meminfo -d <package_name>
+    final isolate = isolates[0]!;
+    _selectedIsolate = IsolateRef(
+      id: isolate.id,
+      name: isolate.name,
+      number: isolate.number,
+      isSystemIsolate: isolate.isSystemIsolate,
+    );
+
+    if (hasConnection && vm.operatingSystem == 'android') {
+      // Poll ADB meminfo
+      adbMemoryInfo = await _fetchAdbInfo();
+    } else {
+      // TODO(terry): TBD alternative for iOS memory info - all values zero.
+      adbMemoryInfo = AdbMemoryInfo.empty();
+    }
+
+    // Query the engine's rasterCache estimate.
+    rasterCache = await _fetchRasterCacheInfo(_selectedIsolate);
+
+    // TODO(terry): There are no user interactions.  However, might be nice to
+    //              record VM GC's on the timeline.
+    eventSample = EventSample.empty();
+
+    // Polls for current RSS size.
+    _update(vm, isolates);
+
+    _pollingTimer = Timer(updateDelay, _pollMemory);
+  }
+
+  /// Poll ADB meminfo
+  Future<AdbMemoryInfo?> _fetchAdbInfo() async {
+    final adbMemInfo = await getAdbMemoryInfo();
+    if (adbMemInfo?.json != null) {
+      return AdbMemoryInfo.fromJsonInKB(adbMemInfo!.json!);
+    }
+    return null;
+  }
+
+  /// Poll Fultter engine's Raster Cache metrics.
+  /// @returns engine's rasterCache estimates or null.
+  Future<RasterCache?> _fetchRasterCacheInfo(IsolateRef selectedIsolate) async {
+    final response = await getRasterCacheMetrics(selectedIsolate);
+    return RasterCache.parse(response?.json);
+  }
+
+  /// @returns view id of selected isolate's 'FlutterView'.
+  /// @throws Exception if no 'FlutterView'.
+  Future<String?> getFlutterViewId(IsolateRef selectedIsolate) async {
+    final flutterViewListResponse = await service!.callServiceExtension(
+      service_registrations.flutterListViews,
+      isolateId: selectedIsolate.id,
+    );
+    final List<dynamic> views =
+        flutterViewListResponse.json!['views'].cast<Map<String, dynamic>>();
+
+    // Each isolate should only have one FlutterView.
+    final flutterView = views.firstWhere(
+      (view) => view['type'] == 'FlutterView',
+      orElse: () => null,
+    );
+
+    if (flutterView == null) {
+      final message =
+          'No Flutter Views to query: ${flutterViewListResponse.json}';
+      print('ERROR: $message');
+      throw Exception(message);
+    }
+
+    final String flutterViewId = flutterView['id']!;
+    return flutterViewId;
+  }
+
+  /// Flutter engine returns estimate how much memory is used by layer/picture raster
+  /// cache entries in bytes.
+  ///
+  /// Call to returns JSON payload 'EstimateRasterCacheMemory' with two entries:
+  ///   layerBytes - layer raster cache entries in bytes
+  ///   pictureBytes - picture raster cache entries in bytes
+  Future<Response?> getRasterCacheMetrics(IsolateRef selectedIsolate) async {
+    final viewId = await getFlutterViewId(selectedIsolate);
+
+    return await service!.callServiceExtension(
+      service_registrations.flutterEngineRasterCache,
+      args: {'viewId': viewId},
+      isolateId: selectedIsolate.id,
+    );
+  }
+
+  void _update(VM vm, List<Isolate?> isolates) {
+    processRss = vm.json!['_currentRSS'];
+
+    isolateHeaps.clear();
+
+    for (Isolate? isolate in isolates) {
+      if (isolate != null) {
+        isolateHeaps[isolate.id!] = getHeaps(isolate);
+      }
+    }
+
+    _recalculate();
+  }
+
+  void _updateGCEvent(String id, List<HeapSpace> heaps) {
+    isolateHeaps[id] = heaps;
+    _recalculate(true);
+  }
+
+  void _recalculate([bool fromGC = false]) {
+    int total = 0;
+
+    int used = 0;
+    int capacity = 0;
+    int external = 0;
+    for (List<HeapSpace> heaps in isolateHeaps.values) {
+      used += heaps.fold<int>(0, (i, heap) => i + heap.used!);
+      capacity += heaps.fold<int>(0, (i, heap) => i + heap.capacity!);
+      external += heaps.fold<int>(0, (i, heap) => i + heap.external!);
+
+      capacity += external;
+
+      total +=
+          heaps.fold<int>(0, (i, heap) => i + heap.capacity! + heap.external!);
+    }
+
+    heapMax = total;
+
+    final time = DateTime.now().millisecondsSinceEpoch;
+    final sample = HeapSample(
+      time,
+      processRss ?? -1,
+      capacity,
+      used,
+      external,
+      fromGC,
+      adbMemoryInfo,
+      eventSample,
+      rasterCache,
+    );
+
+    if (_verboseMode) {
+      final timeCollected = _formatTime(
+        DateTime.fromMillisecondsSinceEpoch(time),
+      );
+
+      print(' Collected Sample: [$timeCollected] capacity=$capacity, '
+          'ADB MemoryInfo total=${adbMemoryInfo!.total}${fromGC ? ' [GC]' : ''}');
+    }
+
+    _jsonFile.writeSample(sample);
+  }
+
+  static List<HeapSpace> getHeaps(Isolate isolate) {
+    final Map<String, dynamic> heaps = isolate.json!['_heaps'];
+    final heapList = <HeapSpace>[];
+    for (final heapJson in heaps.values) {
+      final heap = HeapSpace.parse(heapJson);
+      if (heap != null) {
+        heapList.add(heap);
+      }
+    }
+    return heapList;
+  }
+
+  static String _formatTime(DateTime value) {
+    String toStringLength(int value, int length) {
+      final result = '$value';
+      assert(length >= result.length);
+      return '0' * (length - result.length) + result;
+    }
+
+    return toStringLength(value.hour, 2) +
+        ':' +
+        toStringLength(value.minute, 2) +
+        ':' +
+        toStringLength(value.second, 2) +
+        '.' +
+        toStringLength(value.millisecond, 3);
+  }
+}
+
+class MemoryJsonFile {
+  MemoryJsonFile.create(this._absoluteFileName) {
+    _open();
+  }
+
+  final String _absoluteFileName;
+  late io.File _fs;
+  late io.RandomAccessFile _raFile;
+  bool _multipleSamples = false;
+
+  void _open() {
+    _fs = io.File(_absoluteFileName);
+    _raFile = _fs.openSync(mode: io.FileMode.writeOnly);
+
+    _populateJsonHeader();
+  }
+
+  void _populateJsonHeader() {
+    final payload = '${SamplesMemoryJson.header}${MemoryJson.trailer}';
+    _raFile.writeStringSync(payload);
+    _raFile.flushSync();
+  }
+
+  void _setPositionToWriteSample() {
+    // Set the file position to the data array field contents - inside of [].
+    final filePosition = _raFile.positionSync();
+    _raFile.setPositionSync(filePosition - MemoryJson.trailer.length);
+  }
+
+  void writeSample(HeapSample sample) {
+    _setPositionToWriteSample();
+
+    String encodedSample;
+    if (_multipleSamples) {
+      encodedSample = SamplesMemoryJson().encodeAnother(sample);
+    } else {
+      encodedSample = SamplesMemoryJson().encode(sample);
+    }
+
+    _raFile.writeStringSync('$encodedSample${MemoryJson.trailer}');
+
+    _raFile.flushSync();
+
+    _multipleSamples = true;
+  }
+}
diff --git a/pkg/dds/lib/src/devtools/service_registrations.dart b/pkg/dds/lib/src/devtools/service_registrations.dart
new file mode 100644
index 0000000..10b35ea
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/service_registrations.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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(https://github.com/flutter/devtools/issues/3571): move to devtools_shared.
+class RegisteredServiceDescription {
+  const RegisteredServiceDescription._({
+    required this.service,
+    required this.title,
+  });
+
+  final String service;
+  final String title;
+}
+
+/// Flutter memory service registered by Flutter Tools.
+///
+/// We call this service to get version information about the Flutter Android memory info
+/// using Android's ADB.
+const flutterMemory = RegisteredServiceDescription._(
+  service: 'flutterMemoryInfo',
+  title: 'Flutter Memory Info',
+);
+
+const flutterListViews = '_flutter.listViews';
+
+/// Flutter engine returns estimate how much memory is used by layer/picture raster
+/// cache entries in bytes.
+const flutterEngineRasterCache = '_flutter.estimateRasterCacheMemory';
diff --git a/pkg/dds/lib/src/devtools/utils.dart b/pkg/dds/lib/src/devtools/utils.dart
new file mode 100644
index 0000000..b4c732e
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/utils.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:vm_service/utils.dart';
+import 'package:vm_service/vm_service.dart';
+
+abstract class DevToolsUtils {
+  static void printOutput(
+    String? message,
+    Object json, {
+    required bool machineMode,
+  }) {
+    final output = machineMode ? jsonEncode(json) : message;
+    if (output != null) {
+      print(output);
+    }
+  }
+
+  static Future<VmService?> connectToVmService(Uri theUri) async {
+    // Fix up the various acceptable URI formats into a WebSocket URI to connect.
+    final uri = convertToWebSocketUrl(serviceProtocolUrl: theUri);
+
+    try {
+      final WebSocket ws = await WebSocket.connect(uri.toString());
+
+      final VmService service = VmService(
+        ws.asBroadcastStream(),
+        (String message) => ws.add(message),
+      );
+
+      return service;
+    } catch (_) {
+      print('ERROR: Unable to connect to VMService $theUri');
+      return null;
+    }
+  }
+
+  static Future<String> getVersion(String devToolsDir) async {
+    try {
+      final versionFile = File(path.join(devToolsDir, 'version.json'));
+      final decoded = jsonDecode(await versionFile.readAsString());
+      return decoded['version'] ?? 'unknown';
+    } on FileSystemException {
+      return 'unknown';
+    }
+  }
+}
diff --git a/pkg/dds/lib/src/stream_manager.dart b/pkg/dds/lib/src/stream_manager.dart
index ee0bc49..cde830a 100644
--- a/pkg/dds/lib/src/stream_manager.dart
+++ b/pkg/dds/lib/src/stream_manager.dart
@@ -170,16 +170,19 @@
   /// `streamListen` request for `stream` to the VM service.
   Future<void> streamListen(
     DartDevelopmentServiceClient? client,
-    String stream,
-  ) async {
+    String stream, {
+    bool? includePrivates,
+  }) async {
     await _streamSubscriptionMutex.runGuarded(
       () async {
         assert(stream.isNotEmpty);
+        bool streamNewlySubscribed = false;
         if (!streamListeners.containsKey(stream)) {
           // Initialize the list of clients for the new stream before we do
           // anything else to ensure multiple clients registering for the same
           // stream in quick succession doesn't result in multiple streamListen
           // requests being sent to the VM service.
+          streamNewlySubscribed = true;
           streamListeners[stream] = <DartDevelopmentServiceClient>[];
           if ((stream == kDebugStream && client == null) ||
               stream != kDebugStream) {
@@ -188,12 +191,28 @@
             final result =
                 await dds.vmServiceClient.sendRequest('streamListen', {
               'streamId': stream,
+              if (includePrivates != null)
+                '_includePrivateMembers': includePrivates,
             });
             assert(result['type'] == 'Success');
           }
         }
         if (streamListeners[stream]!.contains(client)) {
           throw kStreamAlreadySubscribedException;
+        } else if (!streamNewlySubscribed && includePrivates != null) {
+          try {
+            await dds.vmServiceClient.sendRequest(
+                '_setStreamIncludePrivateMembers',
+                {'streamId': stream, 'includePrivateMembers': includePrivates});
+          } on json_rpc.RpcException catch (e) {
+            // This private RPC might not be present. If it's not, we're communicating with an older
+            // VM that doesn't support filtering private members, so they will always be included in
+            // responses. Handle the method not found exception so the streamListen call doesn't
+            // fail for older VMs.
+            if (e.code != RpcErrorCodes.kMethodNotFound) {
+              rethrow;
+            }
+          }
         }
         if (client != null) {
           streamListeners[stream]!.add(client);
diff --git a/pkg/dds/lib/src/utils/console.dart b/pkg/dds/lib/src/utils/console.dart
new file mode 100644
index 0000000..10c302b
--- /dev/null
+++ b/pkg/dds/lib/src/utils/console.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class ConsoleUtils {
+  /// Make [contents] bold when printed to the terminal.
+  ///
+  /// This is a no-op on Windows.
+  static String bold(String contents) {
+    return '\u001b[1m$contents\u001b[0m';
+  }
+}
diff --git a/pkg/dds/lib/vm_service_extensions.dart b/pkg/dds/lib/vm_service_extensions.dart
index 536fa57..7c9a031 100644
--- a/pkg/dds/lib/vm_service_extensions.dart
+++ b/pkg/dds/lib/vm_service_extensions.dart
@@ -2,275 +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 'dart:async';
-import 'dart:collection';
+@Deprecated("Use 'package:dds_service_extensions' instead")
+library vm_service_extensions;
 
-import 'package:async/async.dart';
-import 'package:pedantic/pedantic.dart';
-import 'package:vm_service/src/vm_service.dart';
-
-extension DdsExtension on VmService {
-  static bool _factoriesRegistered = false;
-  static Version? _ddsVersion;
-
-  /// The [getDartDevelopmentServiceVersion] RPC is used to determine what version of
-  /// the Dart Development Service Protocol is served by a DDS instance.
-  ///
-  /// The result of this call is cached for subsequent invocations.
-  Future<Version> getDartDevelopmentServiceVersion() async {
-    if (_ddsVersion == null) {
-      _ddsVersion = await _callHelper<Version>(
-        'getDartDevelopmentServiceVersion',
-      );
-    }
-    return _ddsVersion!;
-  }
-
-  /// The [getCachedCpuSamples] RPC is used to retrieve a cache of CPU samples
-  /// collected under a [UserTag] with name `userTag`.
-  Future<CachedCpuSamples> getCachedCpuSamples(
-      String isolateId, String userTag) async {
-    if (!(await _versionCheck(1, 3))) {
-      throw UnimplementedError('getCachedCpuSamples requires DDS version 1.3');
-    }
-    return _callHelper<CachedCpuSamples>('getCachedCpuSamples', args: {
-      'isolateId': isolateId,
-      'userTag': userTag,
-    });
-  }
-
-  /// The [getAvailableCachedCpuSamples] RPC is used to determine which caches of CPU samples
-  /// are available. Caches are associated with individual [UserTag] names and are specified
-  /// when DDS is started via the `cachedUserTags` parameter.
-  Future<AvailableCachedCpuSamples> getAvailableCachedCpuSamples() async {
-    if (!(await _versionCheck(1, 3))) {
-      throw UnimplementedError(
-        'getAvailableCachedCpuSamples requires DDS version 1.3',
-      );
-    }
-    return _callHelper<AvailableCachedCpuSamples>(
-      'getAvailableCachedCpuSamples',
-    );
-  }
-
-  /// Retrieve the event history for `stream`.
-  ///
-  /// If `stream` does not have event history collected, a parameter error is
-  /// returned.
-  Future<StreamHistory> getStreamHistory(String stream) async {
-    if (!(await _versionCheck(1, 2))) {
-      throw UnimplementedError('getStreamHistory requires DDS version 1.2');
-    }
-    return _callHelper<StreamHistory>('getStreamHistory', args: {
-      'stream': stream,
-    });
-  }
-
-  /// Returns the stream for a given stream id which includes historical
-  /// events.
-  ///
-  /// If `stream` does not have event history collected, a parameter error is
-  /// sent over the returned [Stream].
-  Stream<Event> onEventWithHistory(String stream) {
-    late StreamController<Event> controller;
-    late StreamQueue<Event> streamEvents;
-
-    controller = StreamController<Event>(onListen: () async {
-      streamEvents = StreamQueue<Event>(onEvent(stream));
-      final history = (await getStreamHistory(stream)).history;
-      Event? firstStreamEvent;
-      unawaited(streamEvents.peek.then((e) {
-        firstStreamEvent = e;
-      }));
-      for (final event in history) {
-        if (firstStreamEvent != null &&
-            event.timestamp! > firstStreamEvent!.timestamp!) {
-          break;
-        }
-        controller.sink.add(event);
-      }
-      unawaited(controller.sink.addStream(streamEvents.rest));
-    }, onCancel: () {
-      try {
-        streamEvents.cancel();
-      } on StateError {
-        // Underlying stream may have already been cancelled.
-      }
-    });
-
-    return controller.stream;
-  }
-
-  /// Returns a new [Stream<Event>] of `Logging` events which outputs
-  /// historical events before streaming real-time events.
-  ///
-  /// Note: unlike [onLoggingEvent], the returned stream is a single
-  /// subscription stream and a new stream is created for each invocation of
-  /// this getter.
-  Stream<Event> get onLoggingEventWithHistory => onEventWithHistory('Logging');
-
-  /// Returns a new [Stream<Event>] of `Stdout` events which outputs
-  /// historical events before streaming real-time events.
-  ///
-  /// Note: unlike [onStdoutEvent], the returned stream is a single
-  /// subscription stream and a new stream is created for each invocation of
-  /// this getter.
-  Stream<Event> get onStdoutEventWithHistory => onEventWithHistory('Stdout');
-
-  /// Returns a new [Stream<Event>] of `Stderr` events which outputs
-  /// historical events before streaming real-time events.
-  ///
-  /// Note: unlike [onStderrEvent], the returned stream is a single
-  /// subscription stream and a new stream is created for each invocation of
-  /// this getter.
-  Stream<Event> get onStderrEventWithHistory => onEventWithHistory('Stderr');
-
-  /// Returns a new [Stream<Event>] of `Extension` events which outputs
-  /// historical events before streaming real-time events.
-  ///
-  /// Note: unlike [onExtensionEvent], the returned stream is a single
-  /// subscription stream and a new stream is created for each invocation of
-  /// this getter.
-  Stream<Event> get onExtensionEventWithHistory =>
-      onEventWithHistory('Extension');
-
-  Future<bool> _versionCheck(int major, int minor) async {
-    if (_ddsVersion == null) {
-      _ddsVersion = await getDartDevelopmentServiceVersion();
-    }
-    return ((_ddsVersion!.major == major && _ddsVersion!.minor! >= minor) ||
-        (_ddsVersion!.major! > major));
-  }
-
-  Future<T> _callHelper<T>(String method,
-      {String? isolateId, Map args = const {}}) {
-    if (!_factoriesRegistered) {
-      _registerFactories();
-    }
-    return callMethod(
-      method,
-      args: {
-        if (isolateId != null) 'isolateId': isolateId,
-        ...args,
-      },
-    ).then((e) => e as T);
-  }
-
-  static void _registerFactories() {
-    addTypeFactory('StreamHistory', StreamHistory.parse);
-    addTypeFactory(
-      'AvailableCachedCpuSamples',
-      AvailableCachedCpuSamples.parse,
-    );
-    addTypeFactory('CachedCpuSamples', CachedCpuSamples.parse);
-    _factoriesRegistered = true;
-  }
-}
-
-/// A collection of historical [Event]s from some stream.
-class StreamHistory extends Response {
-  static StreamHistory? parse(Map<String, dynamic>? json) =>
-      json == null ? null : StreamHistory._fromJson(json);
-
-  StreamHistory({required List<Event> history}) : _history = history;
-
-  StreamHistory._fromJson(Map<String, dynamic> json)
-      : _history = json['history']
-            .map(
-              (e) => Event.parse(e),
-            )
-            .toList()
-            .cast<Event>() {
-    this.json = json;
-  }
-
-  @override
-  String get type => 'StreamHistory';
-
-  /// Historical [Event]s for a stream.
-  List<Event> get history => UnmodifiableListView(_history);
-  final List<Event> _history;
-}
-
-/// An extension of [CpuSamples] which represents a set of cached samples,
-/// associated with a particular [UserTag] name.
-class CachedCpuSamples extends CpuSamples {
-  static CachedCpuSamples? parse(Map<String, dynamic>? json) =>
-      json == null ? null : CachedCpuSamples._fromJson(json);
-
-  CachedCpuSamples({
-    required this.userTag,
-    this.truncated,
-    required int? samplePeriod,
-    required int? maxStackDepth,
-    required int? sampleCount,
-    required int? timeSpan,
-    required int? timeOriginMicros,
-    required int? timeExtentMicros,
-    required int? pid,
-    required List<ProfileFunction>? functions,
-    required List<CpuSample>? samples,
-  }) : super(
-          samplePeriod: samplePeriod,
-          maxStackDepth: maxStackDepth,
-          sampleCount: sampleCount,
-          timeSpan: timeSpan,
-          timeOriginMicros: timeOriginMicros,
-          timeExtentMicros: timeExtentMicros,
-          pid: pid,
-          functions: functions,
-          samples: samples,
-        );
-
-  CachedCpuSamples._fromJson(Map<String, dynamic> json)
-      : userTag = json['userTag']!,
-        truncated = json['truncated'],
-        super(
-          samplePeriod: json['samplePeriod'] ?? -1,
-          maxStackDepth: json['maxStackDepth'] ?? -1,
-          sampleCount: json['sampleCount'] ?? -1,
-          timeSpan: json['timeSpan'] ?? -1,
-          timeOriginMicros: json['timeOriginMicros'] ?? -1,
-          timeExtentMicros: json['timeExtentMicros'] ?? -1,
-          pid: json['pid'] ?? -1,
-          functions: List<ProfileFunction>.from(
-            createServiceObject(json['functions'], const ['ProfileFunction'])
-                    as List? ??
-                [],
-          ),
-          samples: List<CpuSample>.from(
-            createServiceObject(json['samples'], const ['CpuSample'])
-                    as List? ??
-                [],
-          ),
-        );
-
-  @override
-  String get type => 'CachedCpuSamples';
-
-  /// The name of the [UserTag] associated with this cache of [CpuSamples].
-  final String userTag;
-
-  /// Provided if the CPU sample cache has filled and older samples have been
-  /// dropped.
-  final bool? truncated;
-}
-
-/// A collection of [UserTag] names associated with caches of CPU samples.
-class AvailableCachedCpuSamples extends Response {
-  static AvailableCachedCpuSamples? parse(Map<String, dynamic>? json) =>
-      json == null ? null : AvailableCachedCpuSamples._fromJson(json);
-
-  AvailableCachedCpuSamples({
-    required this.cacheNames,
-  });
-
-  AvailableCachedCpuSamples._fromJson(Map<String, dynamic> json)
-      : cacheNames = List<String>.from(json['cacheNames']);
-
-  @override
-  String get type => 'AvailableCachedUserTagCpuSamples';
-
-  /// A [List] of [UserTag] names associated with CPU sample caches.
-  final List<String> cacheNames;
-}
+export 'package:dds_service_extensions/dds_service_extensions.dart';
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index bc3e130..cb3837e 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,7 +3,7 @@
   A library used to spawn the Dart Developer Service, used to communicate with
   a Dart VM Service instance.
 
-version: 2.1.6
+version: 2.2.0
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
@@ -11,9 +11,13 @@
   sdk: '>=2.13.0 <3.0.0'
 
 dependencies:
+  args: ^2.0.0
   async: ^2.4.1
+  browser_launcher: ^1.0.0
   collection: ^1.15.0
+  dds_service_extensions: ^1.3.0
   devtools_shared: ^2.3.0
+  http_multi_server: ^3.0.0
   json_rpc_2: ^3.0.0
   meta: ^1.1.8
   path: ^1.8.0
@@ -22,13 +26,13 @@
   shelf_proxy: ^1.0.0
   shelf_static: ^1.0.0
   shelf_web_socket: ^1.0.0
+  stack_trace: ^1.10.0
   sse: ^4.0.0
   stream_channel: ^2.0.0
-  vm_service: ^7.5.0
+  vm_service: ^8.1.0
   web_socket_channel: ^2.0.0
 
 dev_dependencies:
-  args: ^2.0.0
   http: ^0.13.0
   test: ^1.0.0
   webdriver: ^3.0.0
diff --git a/pkg/dds/test/dap/dart_cli_test.dart b/pkg/dds/test/dap/dart_cli_test.dart
index d07dc37..57f2297 100644
--- a/pkg/dds/test/dap/dart_cli_test.dart
+++ b/pkg/dds/test/dap/dart_cli_test.dart
@@ -79,7 +79,6 @@
           program: 'foo.dart',
           customTool: '/custom/dart',
           noDebug: true,
-          enableAsserts: true, // to check args are still passed through
         );
 
         await adapter.configurationDoneRequest(request, null, () {});
@@ -87,8 +86,8 @@
         await responseCompleter.future;
 
         expect(adapter.executable, equals('/custom/dart'));
-        // args should be in-tact
-        expect(adapter.processArgs, contains('--enable-asserts'));
+        // a standard built-in arg should be present.
+        expect(adapter.processArgs, contains('--disable-dart-dev'));
       });
 
       test('with all args replaced', () async {
@@ -100,7 +99,6 @@
           customTool: '/custom/dart',
           customToolReplacesArgs: 9999, // replaces all built-in args
           noDebug: true,
-          enableAsserts: true, // should not be in args
           toolArgs: ['tool_args'], // should still be in args
         );
 
@@ -111,7 +109,7 @@
         expect(adapter.executable, equals('/custom/dart'));
         // normal built-in args are replaced by customToolReplacesArgs, but
         // user-provided toolArgs are not.
-        expect(adapter.processArgs, isNot(contains('--enable-asserts')));
+        expect(adapter.processArgs, isNot(contains('--disable-dart-dev')));
         expect(adapter.processArgs, contains('tool_args'));
       });
     });
diff --git a/pkg/dds/test/dap/integration/debug_attach_test.dart b/pkg/dds/test/dap/integration/debug_attach_test.dart
index 3df0fc9..810a15f 100644
--- a/pkg/dds/test/dap/integration/debug_attach_test.dart
+++ b/pkg/dds/test/dap/integration/debug_attach_test.dart
@@ -116,6 +116,45 @@
         'Exited.',
       ]);
     });
+
+    test('removes breakpoints/pause and resumes on detach', () async {
+      final testFile = dap.createTestFile(simpleBreakpointAndThrowProgram);
+
+      final proc = await startDartProcessPaused(
+        testFile.path,
+        [],
+        cwd: dap.testAppDir.path,
+      );
+      final vmServiceUri = await waitForStdoutVmServiceBanner(proc);
+
+      // Attach to the paused script without resuming and wait for the startup
+      // pause event.
+      await Future.wait([
+        dap.client.expectStop('entry'),
+        dap.client.start(
+          launch: () => dap.client.attach(
+            vmServiceUri: vmServiceUri.toString(),
+            autoResume: false,
+            cwd: dap.testAppDir.path,
+          ),
+        ),
+      ]);
+
+      // Set a breakpoint that we expect not to be hit, as detach should disable
+      // it and resume.
+      final breakpointLine = lineWith(testFile, breakpointMarker);
+      await dap.client.setBreakpoint(testFile, breakpointLine);
+
+      // Detach using terminateRequest. Despite the name, terminateRequest is
+      // the request for a graceful detach (and disconnectRequest is the
+      // forceful shutdown).
+      await dap.client.terminate();
+
+      // Expect the process terminates (and hasn't got stuck on the breakpoint
+      // or exception).
+      await proc.exitCode;
+    });
+
     // These tests can be slow due to starting up the external server process.
   }, timeout: Timeout.none);
 }
diff --git a/pkg/dds/test/dap/integration/debug_exceptions_test.dart b/pkg/dds/test/dap/integration/debug_exceptions_test.dart
index 752ce5f..157f136 100644
--- a/pkg/dds/test/dap/integration/debug_exceptions_test.dart
+++ b/pkg/dds/test/dap/integration/debug_exceptions_test.dart
@@ -70,6 +70,25 @@
         exceptionPauseMode: 'All',
       );
     });
+
+    test('parses line/column information from stack traces', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleThrowingProgram);
+      final exceptionLine = lineWith(testFile, 'throw');
+      final outputEvents = await client.collectOutput(file: testFile);
+
+      // Find the output event for the top of the printed stack trace.
+      // It should look something like:
+      // #0      main (file:///var/folders/[...]/app3JZLvu/test_file.dart:2:5)
+      final mainStackFrameEvent = outputEvents
+          .firstWhere((event) => event.output.startsWith('#0      main'));
+
+      // Expect that there is metadata attached that matches the file/location we
+      // expect.
+      expect(mainStackFrameEvent.source?.path, testFile.path);
+      expect(mainStackFrameEvent.line, exceptionLine);
+      expect(mainStackFrameEvent.column, 5);
+    });
     // These tests can be slow due to starting up the external server process.
   }, timeout: Timeout.none);
 }
diff --git a/pkg/dds/test/dap/integration/debug_services.dart b/pkg/dds/test/dap/integration/debug_services_test.dart
similarity index 100%
rename from pkg/dds/test/dap/integration/debug_services.dart
rename to pkg/dds/test/dap/integration/debug_services_test.dart
diff --git a/pkg/dds/test/dap/integration/debug_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
index 6655b58..974692f 100644
--- a/pkg/dds/test/dap/integration/debug_test.dart
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -94,6 +94,76 @@
       expect(proc!.exitCode, completes);
     });
 
+    test('does not resume isolates if user passes --pause-isolates-on-exit',
+        () async {
+      // Internally we always pass --pause-isolates-on-exit and resume the
+      // isolates after waiting for any output events to complete (in case they
+      // need to resolve URIs that involve API calls on an Isolate).
+      //
+      // However if a user passes this flag explicitly, we should not
+      // auto-resume because they might be trying to debug something.
+      final testFile = dap.createTestFile(simpleArgPrintingProgram);
+
+      // Run the script, expecting a Stopped event.
+      final stop = dap.client.expectStop('pause');
+      await Future.wait([
+        stop,
+        dap.client.initialize(),
+        dap.client
+            .launch(testFile.path, toolArgs: ["--pause-isolates-on-exit"]),
+      ], eagerError: true);
+
+      // Resume and expect termination.
+      await await Future.wait([
+        dap.client.event('terminated'),
+        dap.client.continue_((await stop).threadId!),
+      ], eagerError: true);
+    });
+
+    test('sends output events in the correct order', () async {
+      // Output events that have their URIs mapped will be processed slowly due
+      // the async requests for resolving the package URI. This should not cause
+      // them to appear out-of-order with other lines that do not require this
+      // work.
+      //
+      // Use a sample program that prints output to stderr that includes:
+      // - non stack frame lines
+      // - stack frames with file:// URIs
+      // - stack frames with package URIs (that need asynchronously resolving)
+      final fileUri = Uri.file(dap.createTestFile('').path);
+      final packageUri = await dap.createFooPackage();
+      final testFile =
+          dap.createTestFile(stderrPrintingProgram(fileUri, packageUri));
+
+      var outputEvents = await dap.client.collectOutput(
+        launch: () => dap.client.launch(testFile.path),
+      );
+      outputEvents = outputEvents.where((e) => e.category == 'stderr').toList();
+
+      // Verify the order of the stderr output events.
+      final output = outputEvents
+          .map((e) => '${e.output.trim()}')
+          .where((output) => output.isNotEmpty)
+          .join('\n');
+      expectLines(output, [
+        'Start',
+        '#0      main ($fileUri:1:2)',
+        '#1      main2 ($packageUri:1:2)',
+        'End',
+      ]);
+
+      // As a sanity check, verify we did actually do the async path mapping and
+      // got both frames with paths in our test folder.
+      final stackFramesWithPaths = outputEvents.where((e) =>
+          e.source?.path != null &&
+          path.isWithin(dap.testDir.path, e.source!.path!));
+      expect(
+        stackFramesWithPaths,
+        hasLength(2),
+        reason: 'Expected two frames within path ${dap.testDir.path}',
+      );
+    });
+
     test('provides a list of threads', () async {
       final client = dap.client;
       final testFile = dap.createTestFile(simpleBreakpointProgram);
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index d960bec..8ce631d 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -104,7 +104,7 @@
 
     // When attaching, the paused VM will not be automatically unpaused, but
     // instead send a Stopped(reason: 'entry') event. Respond to this by
-    // resuming.
+    // resuming (if requested).
     final resumeFuture = autoResume
         ? expectStop('entry').then((event) => continue_(event.threadId!))
         : null;
@@ -224,6 +224,7 @@
   Future<Response> launch(
     String program, {
     List<String>? args,
+    List<String>? toolArgs,
     String? cwd,
     bool? noDebug,
     List<String>? additionalProjectPaths,
@@ -240,6 +241,7 @@
         program: program,
         cwd: cwd,
         args: args,
+        toolArgs: toolArgs,
         additionalProjectPaths: additionalProjectPaths,
         console: console,
         debugSdkLibraries: debugSdkLibraries,
@@ -499,18 +501,23 @@
 
     await Future.wait([
       initialize(),
-      sendRequest(
-        SetBreakpointsArguments(
-          source: Source(path: file.path),
-          breakpoints: [SourceBreakpoint(line: line, condition: condition)],
-        ),
-      ),
+      setBreakpoint(file, line, condition: condition),
       launch?.call() ?? this.launch(entryFile.path, cwd: cwd, args: args),
     ], eagerError: true);
 
     return stop;
   }
 
+  /// Sets a breakpoint at [line] in [file].
+  Future<void> setBreakpoint(File file, int line, {String? condition}) async {
+    await sendRequest(
+      SetBreakpointsArguments(
+        source: Source(path: file.path),
+        breakpoints: [SourceBreakpoint(line: line, condition: condition)],
+      ),
+    );
+  }
+
   /// Sets the exception pause mode to [pauseMode] and expects to pause after
   /// running the script.
   ///
diff --git a/pkg/dds/test/dap/integration/test_scripts.dart b/pkg/dds/test/dap/integration/test_scripts.dart
index 59bc718..84eea06 100644
--- a/pkg/dds/test/dap/integration/test_scripts.dart
+++ b/pkg/dds/test/dap/integration/test_scripts.dart
@@ -55,6 +55,24 @@
   }
 ''';
 
+/// A simple Dart script that prints to stderr without throwing/terminating.
+///
+/// The output will contain stack traces include both the supplied file and
+/// package URIs.
+String stderrPrintingProgram(Uri fileUri, Uri packageUri) {
+  return '''
+  import 'dart:io';
+  import '$packageUri';
+
+  void main(List<String> args) async {
+    stderr.writeln('Start');
+    stderr.writeln('#0      main ($fileUri:1:2)');
+    stderr.writeln('#1      main2 ($packageUri:1:2)');
+    stderr.write('End');
+  }
+''';
+}
+
 /// Returns a simple Dart script that prints the provided string repeatedly.
 String stringPrintingProgram(String text) {
   // jsonEncode the string to get it into a quoted/escaped form that can be
@@ -109,6 +127,16 @@
   }
 ''';
 
+/// A simple Dart script that has a breakpoint and an exception used for
+/// testing whether breakpoints and exceptions are being paused on (for example
+/// during detach where they should not).
+const simpleBreakpointAndThrowProgram = '''
+  void main(List<String> args) async {
+    print('Hello!'); $breakpointMarker
+    throw 'error';
+  }
+''';
+
 /// A simple Dart script that throws an error and catches it in user code.
 const simpleCaughtErrorProgram = r'''
   void main(List<String> args) async {
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index d4c2a8b..ebabce8 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -133,15 +133,15 @@
 class DapTestSession {
   DapTestServer server;
   DapTestClient client;
-  final Directory _testDir =
+  final Directory testDir =
       Directory.systemTemp.createTempSync('dart-sdk-dap-test');
   late final Directory testAppDir;
   late final Directory testPackagesDir;
 
   DapTestSession._(this.server, this.client) {
-    testAppDir = _testDir.createTempSync('app');
+    testAppDir = testDir.createTempSync('app');
     createPubspec(testAppDir, 'my_test_project');
-    testPackagesDir = _testDir.createTempSync('packages');
+    testPackagesDir = testDir.createTempSync('packages');
   }
 
   /// Adds package with [name] (optionally at [packageFolderUri]) to the
@@ -236,7 +236,7 @@
     await server.stop();
 
     // Clean up any temp folders created during the test runs.
-    _testDir.deleteSync(recursive: true);
+    testDir.deleteSync(recursive: true);
   }
 
   static Future<DapTestSession> setUp({List<String>? additionalArgs}) async {
diff --git a/pkg/dds/test/devtools_server/devtools_client_test.dart b/pkg/dds/test/devtools_server/devtools_client_test.dart
new file mode 100644
index 0000000..4a163b0
--- /dev/null
+++ b/pkg/dds/test/devtools_server/devtools_client_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:dds/src/devtools/client.dart';
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:stream_channel/stream_channel.dart';
+import 'package:test/test.dart';
+
+void main() {
+  late json_rpc.Peer client;
+  late DevToolsClient devToolsClient;
+  setUp(() {
+    final requestController = StreamController<String>();
+    final requestStream = requestController.stream;
+    final requestSink = requestController.sink;
+
+    final responseController = StreamController<String>();
+    final responseStream = responseController.stream;
+    final responseSink = responseController.sink;
+    client = json_rpc.Peer(StreamChannel(responseStream, requestSink));
+    unawaited(client.listen());
+
+    devToolsClient = DevToolsClient(
+      stream: requestStream,
+      sink: responseSink,
+    );
+  });
+
+  test('DevToolsClient API', () async {
+    var response = await client.sendRequest('connected', {
+      'uri': 'http://127.0.0.1:8181',
+    });
+    expect(response, isNull);
+    expect(devToolsClient.hasConnection, true);
+    expect(devToolsClient.vmServiceUri, Uri.parse('http://127.0.0.1:8181'));
+    expect(devToolsClient.embedded, false);
+    expect(devToolsClient.currentPage, isNull);
+
+    response = await client.sendRequest('disconnected');
+    expect(response, isNull);
+    expect(devToolsClient.hasConnection, false);
+    expect(devToolsClient.vmServiceUri, isNull);
+    expect(devToolsClient.embedded, false);
+    expect(devToolsClient.currentPage, isNull);
+
+    response = await client.sendRequest('currentPage', {
+      'id': 'foo',
+      'embedded': true,
+    });
+
+    expect(response, isNull);
+    expect(devToolsClient.hasConnection, false);
+    expect(devToolsClient.vmServiceUri, isNull);
+    expect(devToolsClient.embedded, true);
+    expect(devToolsClient.currentPage, 'foo');
+
+    // TODO: add tests for package:devtools_shared/devtools_server.dart
+  });
+
+  test('DevToolsClient notifications', () async {
+    final enableNotifications = Completer<void>();
+    client.registerMethod(
+      'enableNotifications',
+      (_) => enableNotifications.complete(),
+    );
+    devToolsClient.enableNotifications();
+    await enableNotifications.future;
+
+    final showPage = Completer<void>();
+    String? pageId;
+    client.registerMethod('showPage', (parameters) {
+      pageId = parameters['page'].asString;
+      showPage.complete();
+    });
+    devToolsClient.showPage('foo');
+    await showPage.future;
+    expect(pageId, 'foo');
+
+    final connectToVmService = Completer<void>();
+    String? uri;
+    bool notifyUser = false;
+    client.registerMethod('connectToVm', (parameters) {
+      uri = parameters['uri'].asString;
+      notifyUser = parameters['notify'].asBool;
+      connectToVmService.complete();
+    });
+    devToolsClient.connectToVmService(Uri.parse('http://127.0.0.1:8181'), true);
+    await connectToVmService.future;
+    expect(uri, 'http://127.0.0.1:8181');
+    expect(notifyUser, true);
+
+    final notify = Completer<void>();
+    client.registerMethod('notify', (_) => notify.complete());
+    devToolsClient.notify();
+    await notify.future;
+  });
+}
diff --git a/pkg/dds/test/get_cached_cpu_samples_test.dart b/pkg/dds/test/get_cached_cpu_samples_test.dart
index ae25095..57ce1bc 100644
--- a/pkg/dds/test/get_cached_cpu_samples_test.dart
+++ b/pkg/dds/test/get_cached_cpu_samples_test.dart
@@ -7,7 +7,7 @@
 
 import 'package:dds/dds.dart';
 import 'package:dds/src/utils/mutex.dart';
-import 'package:dds/vm_service_extensions.dart';
+import 'package:dds_service_extensions/dds_service_extensions.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:vm_service/vm_service_io.dart';
diff --git a/pkg/dds/test/get_stream_history_test.dart b/pkg/dds/test/get_stream_history_test.dart
index 101ae0c..efdaf2e 100644
--- a/pkg/dds/test/get_stream_history_test.dart
+++ b/pkg/dds/test/get_stream_history_test.dart
@@ -5,7 +5,7 @@
 import 'dart:io';
 
 import 'package:dds/dds.dart';
-import 'package:dds/vm_service_extensions.dart';
+import 'package:dds_service_extensions/dds_service_extensions.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service_io.dart';
 import 'common/test_helper.dart';
diff --git a/pkg/dds/test/on_event_with_history_test.dart b/pkg/dds/test/on_event_with_history_test.dart
index 01d2fd3..5365b03 100644
--- a/pkg/dds/test/on_event_with_history_test.dart
+++ b/pkg/dds/test/on_event_with_history_test.dart
@@ -6,7 +6,7 @@
 import 'dart:io';
 
 import 'package:dds/dds.dart';
-import 'package:dds/vm_service_extensions.dart';
+import 'package:dds_service_extensions/dds_service_extensions.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service_io.dart';
 import 'common/test_helper.dart';
diff --git a/pkg/dds/test/regress_devtools_issue_3302_test.dart b/pkg/dds/test/regress_devtools_issue_3302_test.dart
index 8c97a12..4d9c458 100644
--- a/pkg/dds/test/regress_devtools_issue_3302_test.dart
+++ b/pkg/dds/test/regress_devtools_issue_3302_test.dart
@@ -6,7 +6,7 @@
 import 'dart:io';
 
 import 'package:dds/dds.dart';
-import 'package:dds/vm_service_extensions.dart';
+import 'package:dds_service_extensions/dds_service_extensions.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service_io.dart';
 import 'common/test_helper.dart';
diff --git a/pkg/dds/tool/dap/README.md b/pkg/dds/tool/dap/README.md
index 26bbeb3..ec49ac5 100644
--- a/pkg/dds/tool/dap/README.md
+++ b/pkg/dds/tool/dap/README.md
@@ -39,7 +39,6 @@
 - `List<String>? toolArgs` - arguments passed after the tool that will run `program` (after `dart` for CLI scripts and after `dart run test:test` for test scripts)
 - `List<String>? vmAdditionalArgs` - arguments passed directly to the Dart VM (after `dart` for both CLI scripts and test scripts)
 - `String? console` - if set to `"terminal"` or `"externalTerminal"` will be run using the `runInTerminal` reverse-request; otherwise the debug adapter spawns the Dart process
-- `bool? enableAsserts` - whether to enable asserts (if not supplied, defaults to enabled)
 - `String? customTool` - an optional tool to run instead of `dart` - the custom tool must be completely compatible with the tool/command it is replacing
 - `int? customToolReplacesArgs` - the number of arguments to delete from the beginning of the argument list when invoking `customTool` - e.g. setting `customTool` to `dart_test` and
   `customToolReplacesArgs` to `2` for a test run would invoke `dart_test foo_test.dart` instead of `dart run test:test foo_test.dart` (if larger than the number of computed arguments all arguments will be removed, if not supplied will default to `0`)
diff --git a/pkg/dds_service_extensions/.gitignore b/pkg/dds_service_extensions/.gitignore
new file mode 100644
index 0000000..65c34dc
--- /dev/null
+++ b/pkg/dds_service_extensions/.gitignore
@@ -0,0 +1,10 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build outputs.
+build/
+
+# Omit committing pubspec.lock for library packages; see
+# https://dart.dev/guides/libraries/private-files#pubspeclock.
+pubspec.lock
diff --git a/pkg/dds_service_extensions/CHANGELOG.md b/pkg/dds_service_extensions/CHANGELOG.md
new file mode 100644
index 0000000..0290ebf
--- /dev/null
+++ b/pkg/dds_service_extensions/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.3.0
+
+- Moved `package:dds/vm_service_extensions.dart` into a standalone package.
diff --git a/pkg/dds_service_extensions/LICENSE b/pkg/dds_service_extensions/LICENSE
new file mode 100644
index 0000000..467a982
--- /dev/null
+++ b/pkg/dds_service_extensions/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2020, the Dart project authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google LLC nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/dds_service_extensions/README.md b/pkg/dds_service_extensions/README.md
new file mode 100644
index 0000000..9f50e4f
--- /dev/null
+++ b/pkg/dds_service_extensions/README.md
@@ -0,0 +1,3 @@
+A package used to expand the `package:vm_service` interface with support for RPCs added in the [Dart Developer Service (DDS) protocol][dds-protocol].
+
+[dds-protocol]: https://github.com/dart-lang/sdk/blob/main/pkg/dds/dds_protocol.md
diff --git a/pkg/dds_service_extensions/analysis_options.yaml b/pkg/dds_service_extensions/analysis_options.yaml
new file mode 100644
index 0000000..dee8927
--- /dev/null
+++ b/pkg/dds_service_extensions/analysis_options.yaml
@@ -0,0 +1,30 @@
+# This file configures the static analysis results for your project (errors,
+# warnings, and lints).
+#
+# This enables the 'recommended' set of lints from `package:lints`.
+# This set helps identify many issues that may lead to problems when running
+# or consuming Dart code, and enforces writing Dart using a single, idiomatic
+# style and format.
+#
+# If you want a smaller set of lints you can change this to specify
+# 'package:lints/core.yaml'. These are just the most critical lints
+# (the recommended set includes the core lints).
+# The core lints are also what is used by pub.dev for scoring packages.
+
+include: package:lints/recommended.yaml
+
+# Uncomment the following section to specify additional rules.
+
+# linter:
+#   rules:
+#     - camel_case_types
+
+# analyzer:
+#   exclude:
+#     - path/to/excluded/files/**
+
+# For more information about the core and recommended set of lints, see
+# https://dart.dev/go/core-lints
+
+# For additional information about configuring this file, see
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkg/dds_service_extensions/lib/dds_service_extensions.dart b/pkg/dds_service_extensions/lib/dds_service_extensions.dart
new file mode 100644
index 0000000..702cf58
--- /dev/null
+++ b/pkg/dds_service_extensions/lib/dds_service_extensions.dart
@@ -0,0 +1,272 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:async/async.dart';
+// ignore: implementation_imports
+import 'package:vm_service/src/vm_service.dart';
+
+extension DdsExtension on VmService {
+  static bool _factoriesRegistered = false;
+  static Version? _ddsVersion;
+
+  /// The [getDartDevelopmentServiceVersion] RPC is used to determine what version of
+  /// the Dart Development Service Protocol is served by a DDS instance.
+  ///
+  /// The result of this call is cached for subsequent invocations.
+  Future<Version> getDartDevelopmentServiceVersion() async {
+    _ddsVersion ??= await _callHelper<Version>(
+      'getDartDevelopmentServiceVersion',
+    );
+    return _ddsVersion!;
+  }
+
+  /// The [getCachedCpuSamples] RPC is used to retrieve a cache of CPU samples
+  /// collected under a [UserTag] with name `userTag`.
+  Future<CachedCpuSamples> getCachedCpuSamples(
+      String isolateId, String userTag) async {
+    if (!(await _versionCheck(1, 3))) {
+      throw UnimplementedError('getCachedCpuSamples requires DDS version 1.3');
+    }
+    return _callHelper<CachedCpuSamples>('getCachedCpuSamples', args: {
+      'isolateId': isolateId,
+      'userTag': userTag,
+    });
+  }
+
+  /// The [getAvailableCachedCpuSamples] RPC is used to determine which caches of CPU samples
+  /// are available. Caches are associated with individual [UserTag] names and are specified
+  /// when DDS is started via the `cachedUserTags` parameter.
+  Future<AvailableCachedCpuSamples> getAvailableCachedCpuSamples() async {
+    if (!(await _versionCheck(1, 3))) {
+      throw UnimplementedError(
+        'getAvailableCachedCpuSamples requires DDS version 1.3',
+      );
+    }
+    return _callHelper<AvailableCachedCpuSamples>(
+      'getAvailableCachedCpuSamples',
+    );
+  }
+
+  /// Retrieve the event history for `stream`.
+  ///
+  /// If `stream` does not have event history collected, a parameter error is
+  /// returned.
+  Future<StreamHistory> getStreamHistory(String stream) async {
+    if (!(await _versionCheck(1, 2))) {
+      throw UnimplementedError('getStreamHistory requires DDS version 1.2');
+    }
+    return _callHelper<StreamHistory>('getStreamHistory', args: {
+      'stream': stream,
+    });
+  }
+
+  /// Returns the stream for a given stream id which includes historical
+  /// events.
+  ///
+  /// If `stream` does not have event history collected, a parameter error is
+  /// sent over the returned [Stream].
+  Stream<Event> onEventWithHistory(String stream) {
+    late StreamController<Event> controller;
+    late StreamQueue<Event> streamEvents;
+
+    controller = StreamController<Event>(onListen: () async {
+      streamEvents = StreamQueue<Event>(onEvent(stream));
+      final history = (await getStreamHistory(stream)).history;
+      Event? firstStreamEvent;
+      unawaited(streamEvents.peek.then((e) {
+        firstStreamEvent = e;
+      }));
+      for (final event in history) {
+        if (firstStreamEvent != null &&
+            event.timestamp! > firstStreamEvent!.timestamp!) {
+          break;
+        }
+        controller.sink.add(event);
+      }
+      unawaited(controller.sink.addStream(streamEvents.rest));
+    }, onCancel: () {
+      try {
+        streamEvents.cancel();
+      } on StateError {
+        // Underlying stream may have already been cancelled.
+      }
+    });
+
+    return controller.stream;
+  }
+
+  /// Returns a new [Stream<Event>] of `Logging` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onLoggingEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onLoggingEventWithHistory => onEventWithHistory('Logging');
+
+  /// Returns a new [Stream<Event>] of `Stdout` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onStdoutEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onStdoutEventWithHistory => onEventWithHistory('Stdout');
+
+  /// Returns a new [Stream<Event>] of `Stderr` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onStderrEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onStderrEventWithHistory => onEventWithHistory('Stderr');
+
+  /// Returns a new [Stream<Event>] of `Extension` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onExtensionEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onExtensionEventWithHistory =>
+      onEventWithHistory('Extension');
+
+  Future<bool> _versionCheck(int major, int minor) async {
+    _ddsVersion ??= await getDartDevelopmentServiceVersion();
+    return ((_ddsVersion!.major == major && _ddsVersion!.minor! >= minor) ||
+        (_ddsVersion!.major! > major));
+  }
+
+  Future<T> _callHelper<T>(String method,
+      {String? isolateId, Map args = const {}}) {
+    if (!_factoriesRegistered) {
+      _registerFactories();
+    }
+    return callMethod(
+      method,
+      args: {
+        if (isolateId != null) 'isolateId': isolateId,
+        ...args,
+      },
+    ).then((e) => e as T);
+  }
+
+  static void _registerFactories() {
+    addTypeFactory('StreamHistory', StreamHistory.parse);
+    addTypeFactory(
+      'AvailableCachedCpuSamples',
+      AvailableCachedCpuSamples.parse,
+    );
+    addTypeFactory('CachedCpuSamples', CachedCpuSamples.parse);
+    _factoriesRegistered = true;
+  }
+}
+
+/// A collection of historical [Event]s from some stream.
+class StreamHistory extends Response {
+  static StreamHistory? parse(Map<String, dynamic>? json) =>
+      json == null ? null : StreamHistory._fromJson(json);
+
+  StreamHistory({required List<Event> history}) : _history = history;
+
+  StreamHistory._fromJson(Map<String, dynamic> json)
+      : _history = json['history']
+            .map(
+              (e) => Event.parse(e),
+            )
+            .toList()
+            .cast<Event>() {
+    this.json = json;
+  }
+
+  @override
+  String get type => 'StreamHistory';
+
+  /// Historical [Event]s for a stream.
+  List<Event> get history => UnmodifiableListView(_history);
+  final List<Event> _history;
+}
+
+/// An extension of [CpuSamples] which represents a set of cached samples,
+/// associated with a particular [UserTag] name.
+class CachedCpuSamples extends CpuSamples {
+  static CachedCpuSamples? parse(Map<String, dynamic>? json) =>
+      json == null ? null : CachedCpuSamples._fromJson(json);
+
+  CachedCpuSamples({
+    required this.userTag,
+    this.truncated,
+    required int? samplePeriod,
+    required int? maxStackDepth,
+    required int? sampleCount,
+    required int? timeSpan,
+    required int? timeOriginMicros,
+    required int? timeExtentMicros,
+    required int? pid,
+    required List<ProfileFunction>? functions,
+    required List<CpuSample>? samples,
+  }) : super(
+          samplePeriod: samplePeriod,
+          maxStackDepth: maxStackDepth,
+          sampleCount: sampleCount,
+          timeSpan: timeSpan,
+          timeOriginMicros: timeOriginMicros,
+          timeExtentMicros: timeExtentMicros,
+          pid: pid,
+          functions: functions,
+          samples: samples,
+        );
+
+  CachedCpuSamples._fromJson(Map<String, dynamic> json)
+      : userTag = json['userTag']!,
+        truncated = json['truncated'],
+        super(
+          samplePeriod: json['samplePeriod'] ?? -1,
+          maxStackDepth: json['maxStackDepth'] ?? -1,
+          sampleCount: json['sampleCount'] ?? -1,
+          timeSpan: json['timeSpan'] ?? -1,
+          timeOriginMicros: json['timeOriginMicros'] ?? -1,
+          timeExtentMicros: json['timeExtentMicros'] ?? -1,
+          pid: json['pid'] ?? -1,
+          functions: List<ProfileFunction>.from(
+            createServiceObject(json['functions'], const ['ProfileFunction'])
+                    as List? ??
+                [],
+          ),
+          samples: List<CpuSample>.from(
+            createServiceObject(json['samples'], const ['CpuSample'])
+                    as List? ??
+                [],
+          ),
+        );
+
+  @override
+  String get type => 'CachedCpuSamples';
+
+  /// The name of the [UserTag] associated with this cache of [CpuSamples].
+  final String userTag;
+
+  /// Provided if the CPU sample cache has filled and older samples have been
+  /// dropped.
+  final bool? truncated;
+}
+
+/// A collection of [UserTag] names associated with caches of CPU samples.
+class AvailableCachedCpuSamples extends Response {
+  static AvailableCachedCpuSamples? parse(Map<String, dynamic>? json) =>
+      json == null ? null : AvailableCachedCpuSamples._fromJson(json);
+
+  AvailableCachedCpuSamples({
+    required this.cacheNames,
+  });
+
+  AvailableCachedCpuSamples._fromJson(Map<String, dynamic> json)
+      : cacheNames = List<String>.from(json['cacheNames']);
+
+  @override
+  String get type => 'AvailableCachedUserTagCpuSamples';
+
+  /// A [List] of [UserTag] names associated with CPU sample caches.
+  final List<String> cacheNames;
+}
diff --git a/pkg/dds_service_extensions/lib/src/dds_service_extensions_base.dart b/pkg/dds_service_extensions/lib/src/dds_service_extensions_base.dart
new file mode 100644
index 0000000..e8a6f15
--- /dev/null
+++ b/pkg/dds_service_extensions/lib/src/dds_service_extensions_base.dart
@@ -0,0 +1,6 @@
+// TODO: Put public facing types in this file.
+
+/// Checks if you are awesome. Spoiler: you are.
+class Awesome {
+  bool get isAwesome => true;
+}
diff --git a/pkg/dds_service_extensions/pubspec.yaml b/pkg/dds_service_extensions/pubspec.yaml
new file mode 100644
index 0000000..ca19fe2
--- /dev/null
+++ b/pkg/dds_service_extensions/pubspec.yaml
@@ -0,0 +1,18 @@
+name: dds_service_extensions
+description: >-
+  Extension methods for `package:vm_service`, used to make requests a
+  Dart Development Service (DDS) instance.
+
+version: 1.3.0
+
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds_service_extensions
+
+environment:
+  sdk: '>=2.13.0 <3.0.0'
+
+dependencies:
+   async: ^2.4.1
+   vm_service: ^8.1.0
+
+dev_dependencies:
+  lints: ^1.0.0
diff --git a/pkg/dds_service_extensions/test/README b/pkg/dds_service_extensions/test/README
new file mode 100644
index 0000000..77e2983
--- /dev/null
+++ b/pkg/dds_service_extensions/test/README
@@ -0,0 +1 @@
+NOTE: Tests for this package can be found in `package:dds`.
diff --git a/pkg/dev_compiler/README.md b/pkg/dev_compiler/README.md
index 1a9e625..e20dac2 100644
--- a/pkg/dev_compiler/README.md
+++ b/pkg/dev_compiler/README.md
@@ -1,48 +1,81 @@
-The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern JavaScript (EcmaScript 6).  Its primary use today is to support fast, iterative development of Dart web applications for Chrome and other modern browsers.
+The Dart Dev Compiler (DDC) is a fast, modular compiler that generates modern
+JavaScript (EcmaScript 6). Its primary use today is to support fast, iterative
+development of Dart web applications for Chrome and other modern browsers.
 
-# Soundness and Restrictions
+# Support
 
-DDC is built upon Dart's [sound](https://dart.dev/guides/language/type-system) type system.  It only compiles programs that statically type check (i.e., no strong mode errors).  It leverages static type checking to generate simpler, readable, and more idiomatic code with fewer runtime checks.  In general, DDC is able to provide stronger type guarantees - i.e., *soundness* - than traditional Dart checked mode with significantly fewer runtime checks.
+DDC is meant to be used by build systems like bazel, `build_web_compilers` and
+`flutter_tools`  under the hood. This compiler is not meant to be used by
+application developers directly.
 
-With strong mode, DDC is stricter than traditional Dart production mode or checked mode.  Running existing Dart code on DDC will generally require fixing both static and runtime type errors.
+While at times the code generated by this compiler may be readable, the
+representation is not meant to be stable and can break with time. For that
+reason we do not recommend using this compiler to export Dart as a
+JavaScript module.
 
-For example, although the following snippet will run in production or checked mode, it will fail to compile with DDC:
+The recommended approach to compile Dart to JavaScript is to use `dart compile
+js` instead. If you intend to make a public JavaScript API based on a Dart
+implementation, such API should be declared explicitly using the standard
+Dart-JSInterop mechanisms.
 
-```dart
-var list = ["hello", "world"];  // Inferred as List<String> in strong mode
-List<int> list2 = list;  // Static type error: incompatible types
-```
+# Implementation details
 
-On the other hand, the following snippet - which tries to mask the type error via casts - will compile with DDC, but fail with a runtime type error.
+## Modularity
 
-```dart
-var list = ["hello", "world"];
-List<Object> list2 = list;  // Generics are covariant.  No runtime check required.
-List<int> list3 = list2;  // Implicit runtime downcast triggers error.
-```  
+Unlike Dart2JS, DDC does not require an entire Dart application. Instead, it
+operates modularly: it compiles a set of Dart files into a JavaScript module. A
+DDC compilation step requires a set of input Dart files and a set of *summaries*
+of dependencies. It performs modular type checking as part of this compilation
+step, and, if the input type checks, it generates a JavaScript module. The
+browser (i.e., the JavaScript runtime) loads and links the generated modules
+when running the application. During development, a compilation step only needs
+to be rerun if the Dart files or summaries it relies upon change. For most
+changes, only a very small part of your code will require recompilation.
+Moreover, modules that are unchanged can be cached in the browser.
 
-# Modularity
+## Representation
 
-DDC provides fast, incremental compilation based on standard JavaScript modules.  Unlike Dart2JS, DDC does not require an entire Dart application.  Instead, it operates modularly: it compiles a set of Dart files into a JavaScript module.  A DDC compilation step requires a set of input Dart files and a set of *summaries* of dependencies.  It performs modular type checking as part of this compilation step, and, if the input type checks, it generates a JavaScript module (e.g., [*ES6*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import), [*AMD*](https://github.com/amdjs/amdjs-api/blob/master/AMD.md), or [*CommonJS*](https://nodejs.org/docs/latest/api/modules.html)).  The browser (i.e., the JavaScript runtime) loads and links the generated modules when running the application.
-During development, a compilation step only needs to be rerun if the Dart files or summaries it relies upon change.  For most changes, only a very small part of your code will require recompilation.  Moreover, modules that are unchanged can be cached in the browser.
+Currently Dart classes are mapped to ES6 classes, Dart fields to ES6 properties,
+Dart getters/setters to ES6 getters/setters, Dart methods to ES6 methods, and so
+on. Often names are preserved and calling conventions are natural JavaScript
+ones.
 
-# EcmaScript 6
+Some Dart concepts don't map directly:
 
-DDC attempts to map Dart to idiomatic EcmaScript 6 (ES6) as cleanly as possible, and it relies heavily on static typing to do this.  In general, where Dart concepts map directly to ES6, DDC generates code accordingly.  For example, Dart classes are mapped to ES6 classes, Dart fields to ES6 properties, Dart getters/setters to ES6 getters/setters, Dart methods to ES6 methods, and so on.  In most cases, names are preserved and calling conventions are natural JavaScript ones.
+- *Libraries*. Multiple Dart libraries are mapped to a single JS module. Each
+  library appears as a first class object in the generated JS module, with its
+  top-level symbols as members. We currently use a heuristic (based upon file
+  paths) to ensure unique naming of generated library objects.
 
-There are some import caveats where Dart concepts do not map directly:
+- *Generics*. Dart generics are *reified*, i.e., they are preserved at runtime.
+  Generic classes are mapped to factories that, given one or more type
+  parameters, return an actual ES6 class (e.g., `HashMap$(core.String,
+  core.int)` produces a class that represents a HashMap from strings to ints).
+  Similarly, generic methods are mapped to factories that, given one or more
+  type parameters, return a method.
 
-- *Libraries*.  Multiple Dart libraries are mapped to a single JS module.  Each library appears as a first class object in the generated JS module, with its top-level symbols as members.  We currently use a heuristic (based upon file paths) to ensure unique naming of generated library objects.
-- *Generics*.  Dart generics are *reified*, i.e., they are preserved at runtime.  Generic classes are mapped to factories that, given one or more type parameters, return an actual ES6 class (e.g., `HashMap$(core.String, core.int)` produces a class that represents a HashMap from strings to ints).  Similarly, generic methods are mapped to factories that, given one or more type parameters, return a method.  
-- *Dynamic*.  DDC supports dynamically typed code (i.e., Dart's `dynamic` type), but it will typically generate less readable and less efficient ES6 output as many type checks must be deferred to runtime.  All dynamic operations are invoked via runtime helper code.
-- *Constructors*.  Dart supports multiple, named and factory constructors for a given class with a different initialization order for fields.  Today, these are mapped to instance or static methods on the generated ES6 class.
-- *Private members*.  Dart maps private members (e.g., private fields or methods) to ES6 symbols.  For example, `a._x` may map to `a[_x]` where `_x` is a symbol only defined in the scope of the generated library.
-- *Scoping*.  Dart scoping rules and reserved words are slightly different than JavaScript.  While we try to preserve names wherever possible, in certain cases, we are required to rename.
+- *Dynamic*. DDC supports dynamically typed code (i.e., Dart's `dynamic` type),
+  but it will typically generate less readable and less efficient ES6 output as
+  many type checks must be deferred to runtime. All dynamic operations are
+  invoked via runtime helper code.
 
-In general, the current conventions (i.e., the Application Binary Interface or ABI in compiler terminology) should not be considered stable.  We reserve the right to change these in the future.
+- *Constructors*. Dart supports multiple, named and factory constructors for a
+  given class with a different initialization order for fields. Today, these
+  are mapped to instance or static methods on the generated ES6 class.
+
+- *Private members*. Dart maps private members (e.g., private fields or
+  methods) to ES6 symbols. For example, `a._x` may map to `a[_x]` where `_x` is
+  a symbol only defined in the scope of the generated library.
+
+- *Scoping*. Dart scoping rules and reserved words are slightly different than
+  JavaScript. While we try to preserve names wherever possible, in certain
+  cases, we are required to rename.
+
+In general, the current conventions (i.e., the Application Binary Interface or
+ABI in compiler terminology) should not be considered stable. We reserve the
+right to change these in the future.
 
 # Browser support
 
-DDC currently supports Chrome stable (though users have had success running on FireFox and Safari).  In the near future, we expect to target all common modern browsers that support ES6.  ES6 itself is in active development across all modern browsers, but at advanced stages of support:
-
-[kangax.github.io/compat-table/es6](https://kangax.github.io/compat-table/es6/).
+DDC currently supports Chrome stable (though users have had success running on
+FireFox and Safari).
diff --git a/pkg/dev_compiler/USAGE.md b/pkg/dev_compiler/USAGE.md
deleted file mode 100644
index e2f0b69..0000000
--- a/pkg/dev_compiler/USAGE.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Usage
-
-The [Dart Dev Compiler](README.md) (DDC) is an **experimental** development
-compiler from Dart to EcmaScript 6. It is still incomplete, under heavy
-development, and not yet ready for production use.
-
-With those caveats, we welcome feedback for those experimenting.
-
-The easiest way to compile and run DDC generated code for now is via NodeJS.
-The following instructions are in a state of flux -- please expect them to
-change. If you find issues, please let us know.
-
-1.  Follow the [Getting the Source](https://github.com/dart-lang/sdk/wiki/Building#getting-the-source) steps, and
-    set the environment variable `DDC_PATH` to the `pkg/dev_compiler`
-    subdirectory within wherever you check that out.
-
-2.  Install nodejs v6.0 or later and add it to your path. It can be installed
-    from:
-
-    https://nodejs.org/
-
-    Note, v6 or later is required for harmony / ES6 support.
-
-3.  Define a node path (you can add other directories if you want to separate
-    things out):
-
-    ```sh
-    export NODE_PATH=$DDC_PATH/lib/js/common:.
-    ```
-
-4.  Compile a test file with a `main` entry point:
-
-    ```sh
-    dart $DDC_PATH/bin/dartdevc.dart --modules node -o hello.js hello.dart
-    ```
-
-    Note, the `hello.js` built here is not fully linked. It loads the SDK via a `require` call.
-
-5.  Run it via your node built in step 1:
-
-    ```sh
-    node -e 'require("hello").hello.main()'
-    ```
-
-6.  Compile multiple libraries using summaries. E.g., write a `world.dart` that
-    imports `hello.dart` with it's own `main`. Step 5 above generated a summary
-    (`hello.sum`) for `hello.dart`. Build world:
-
-    ```sh
-    dart $DDC_PATH/bin/dartdevc.dart --modules node -s hello.sum -o world.js world.dart
-    ```
-
-    Run world just like hello above:
-
-    ```sh
-    node -e 'require("world").world.main()'
-    ```
-
-7.  Node modules do not run directly on the browser or v8. You can use a tool
-    like `browserify` to build a linked javascript file that can:
-
-    Install:
-
-    ```sh
-    sudo npm install -g browserify
-    ```
-
-    and run, e.g.,:
-
-    ```sh
-    echo 'require("world").world.main()' | browserify -d - > world.dart.js
-    ```
-
-    The produced `world.dart.js` fully links all dependencies (`dart_sdk`,
-    `hello`, and `world`) and executes `world.main`.  It can be loaded via
-    script tag and run in Chrome (stable or later).
-
-## Feedback
-
-Please file issues in our [GitHub issue
-tracker](https://github.com/dart-lang/sdk/issues).
diff --git a/pkg/dev_compiler/doc/GENERIC_METHODS.md b/pkg/dev_compiler/doc/GENERIC_METHODS.md
deleted file mode 100644
index f57d127..0000000
--- a/pkg/dev_compiler/doc/GENERIC_METHODS.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# Using Generic Methods
-
-**Note: This document is out of date.  Please see [Sound Dart](https://dart.dev/guides/language/sound-dart) for up-to-date
-documentation on Dart's type system.  The work below was a precursor towards Dart's current type system.
-
-For historical reasons, this feature is called "generic methods", but it
-applies equally well to instance methods, static methods, top-level functions,
-local functions, and even lambda expressions.**
-
-Initially a [proposal][], generic methods are on their way to being fully
-supported in Dart. Here is how to use them.
-
-[proposal]: https://github.com/leafpetersen/dep-generic-methods/blob/master/proposal.md
-
-When they were still being prototyped, an [older comment-based syntax was
-designed][old] so that the static analysis could be implemented and tested
-before the VM and compilers needed to worry about the syntax. Now that real
-syntax is allowed everywhere, this doc has been updated.
-
-[old]: GENERIC_METHOD_COMMENTS.md
-
-## Declaring generic methods
-
-Type parameters for generic methods are listed after the method or function
-name, inside angle brackets:
-
-```dart
-/// Takes two type parameters, [K] and [V].
-Map<K, V> singletonMap<K, V>(K key, V value) {
-  return <K, V>{ key, value };
-}
-```
-
-As with classes, you can put bounds on type parameters:
-
-```dart
-/// Takes a list of two numbers of some num-derived type [T].
-T sumPair<T extends num>(List<T> items) {
-  return items[0] + items[1];
-}
-```
-
-Class methods (instance and static) can be declared to take generic parameters
-in the same way:
-
-```dart
-class C {
-  static int f<S, T>(int x) => 3;
-  int m<S, T>(int x) => 3;
-}
-```
-
-This even works for function-typed parameters, local functions, and function
-expressions:
-
-```dart
-/// Takes a generic method as a parameter [callback].
-void functionTypedParameter(T callback<T>(T thing)) {}
-
-// Declares a local generic function `itself`.
-void localFunction() {
-  T itself<T>(T thing) => thing;
-}
-
-// Binds a generic function expression to a local variable.
-void functionExpression() {
-  var lambda = <T>(T thing) => thing;
-}
-```
-
-We do not currently support a way to declare a function as *returning* a generic
-function. This will eventually be supported using a `typedef`.
-
-## Using generic method type parameters
-
-You've seen some examples already, but you can use a generic type parameter
-almost anywhere you would expect in a generic method.
-
-* Inside the method's parameter list:
-
-    ```dart
-    takeThing<T>(T thing) { ... }
-    //           ^-- Here.
-    ```
-
-* Inside type annotations in the body of the method:
-
-    ```dart
-    useThing<T>() {
-      T thing = getThing();
-    //^-- Here.
-      List<T> pair = [thing, thing];
-      //   ^-- And here.
-    }
-    ```
-
-* In the return type of the method:
-
-    ```dart
-      T itself<T>(T thing) => thing;
-    //^-- Here.
-    ```
-
-* As type arguments in generic classes and method calls:
-
-    ```dart
-    useThing<T>(T thing) {
-      var pair = <T>[thing, thing];
-      //          ^-- Here.
-      var set = new Set<T>()..add(thing);
-      //                ^-- And here.
-    }
-    ```
-
-    Note that generic methods are not yet supported *at runtime* on the VM and
-    dart2js. On those platforms, uses of generic method type arguments are
-    treated like `dynamic` today. So in this example, `pair`'s reified type at
-    runtime will be `List<dynamic>` and `set` will be `Set<dynamic>`.
-
-There are two places you *cannot* use a generic method type parameter. Both are
-because the VM and dart2js don't support reifying generic method type arguments
-yet. Since these expressions wouldn't do what you want, we've temporarily
-defined them to be an error:
-
-* As the right-hand side of an `is` or `is!` expression.
-
-    ```dart
-    testType<T>(object) {
-      print(object is T);
-      //              ^-- Error!
-      print(object is! T);
-      //               ^-- Error!
-    }
-    ```
-
-* As a type literal:
-
-    ```dart
-    printType<T>() {
-      Type t = T;
-      //       ^-- Error!
-      print(t);
-    }
-    ```
-
-Once we have full runtime support for generic methods, these will be allowed.
-
-## Calling generic methods
-
-Most of the time, when you call a generic method, you can leave off the type
-arguments and strong mode's type inference will fill them in for you
-automatically. For example:
-
-```dart
-var fruits = ["apple", "banana", "cherry"];
-var lengths = fruits.map((fruit) => fruit.length);
-```
-
-The `map()` method on Iterable is now generic and takes a type parameter for the
-element type of the returned sequence:
-
-```dart
-class Iterable<T> {
-  Iterable<S> map<S>(S transform(T element)) { ... }
-
-  // Other stuff...
-}
-```
-
-In this example, the type checker:
-
-1. Infers `List<String>` for the type of `fruits` based on the elements in the
-   list literal.
-2. That lets it infer `String` for the type of the lambda parameter `fruit`
-   passed to `map()`.
-3. Then, from the result of calling `.length`, it infers the return type of the
-   lambda to be `int`.
-4. That in turn is used to fill in the type argument to the call to `map()` as
-   `int`, and the resulting sequence is an `Iterable<int>`.
-
-If inference *isn't* able to fill in a type argument for you, it uses `dynamic`
-instead. If that isn't what you want, or it infers a type you don't want, you
-can always pass them explicitly:
-
-```dart
-// Explicitly give a type so that we don't infer "int".
-var lengths = fruits.map<num>((fruit) => fruit.length).toList();
-
-// So that we can later add doubles to the result.
-lengths.add(1.2);
-```
diff --git a/pkg/dev_compiler/doc/GENERIC_METHOD_COMMENTS.md b/pkg/dev_compiler/doc/GENERIC_METHOD_COMMENTS.md
deleted file mode 100644
index 9050eab..0000000
--- a/pkg/dev_compiler/doc/GENERIC_METHOD_COMMENTS.md
+++ /dev/null
@@ -1,237 +0,0 @@
-# Prototype Syntax for Generic Methods
-
-**Note:** This documents the deprecated comment-based syntax for generic
-methods. New code should use the [much better real syntax][real]. This document
-is preserved in case you run into existing code still using the old syntax.
-
-[real]: GENERIC_METHODS.md
-
----
-
-Generic methods are a [proposed addition to the Dart language](https://github.com/leafpetersen/dep-generic-methods/blob/master/proposal.md).
-
-This is a summary of the current (as of January 2016) comment-based generic
-method syntax supported by the analyzer strong mode and the Dart Dev Compiler.
-The comment-based syntax essentially uses the proposed actual generic method
-syntax, but wraps it in comments.  This allows developers to experiment with
-generic methods while still ensuring that their code runs on all platforms while
-generic methods are still being evaluated for inclusion into the language.
-
-## Declaring generic method parameters
-
-Generic method parameters are listed using a block comment after the method or
-function name, inside of angle brackets.
-
-```dart
-// This declares a function which takes two unused generic method parameters
-int f/*<S, T>*/(int x) => 3;
-```
-
-As with classes, you can put bounds on type parameters.
-
-```dart
-// This declares a function which takes two unused generic method parameters
-// The first parameter (S) must extend num
-// The second parameter (T) must extend List<S>
-int f/*<S extends num, T extends List<S>>*/(int x) => 3;
-```
-
-Class methods (instance and static) can be declared to take generic parameters
-in the same way.
-
-```dart
-class C {
-  static int f/*<S, T>*/(int x) => 3;
-  int m/*<S, T>*/(int x) => 3;
-}
-```
-
-Function typed parameters, local functions, and function expressions can also be
-declared to take generic parameters.
-
-```dart
-// foo takes a generic method as a parameter
-void foo(int f/*<S>*/(int x)) {}
-
-// foo declares a local generic function
-void foo() {
-  int f/*<S>*/(int x) => 3;
-  return;
-}
-
-// foo binds a generic function expression to a local variable.
-void foo() {
-  var x = /*<S>*/(int x) => x;
-}
-```
-
-We do not currently support a way to declare a function as returning a generic
-function.  This will eventually be supported using something analogous to Dart
-typedefs.
-
-## Using generic method parameters
-
-The previous examples declared generic method parameters, but did not use them.
-You can use a generic method parameter `T` anywhere that a type is expected in
-Dart by writing a type followed by `/*=T*/`.  So for example, `dynamic /*=T*/`
-will be interpreted as `dynamic` by all non-strong mode tools, but will be
-interpreted as `T` by strong mode.  In places where it is valid to leave off a
-type, simply writing `/*=T*/` will be interpreted as `dynamic` by non-strong
-mode tools, but will be interpreted as `T` by strong mode.  For example:
-
-```dart
-// foo is a generic method which takes a single generic method parameter S.
-// In strong mode, the parameter x will have type S, and the return type will
-// be S
-// In normal mode, the parameter x will have type dynamic, and the return
-// type will be dynamic.
-dynamic/*=S*/ foo/*<S>*/(dynamic/*=S*/ x) { return x; }
-```
-
-This can be written more concisely by leaving off the `dynamic`.
-
-```dart
-/*=S*/ foo/*<S>*/(/*=S*/ x) {return x;}
-```
-
-You can also put a type to the left of the `/*=T/`. This type will be used
-for all non-strong mode tools. For example:
-
-```dart
-// This method works with `int`, `double`, or `num`. The return type will
-// match the type of the parameters.
-num/*=T*/ pickAtRandom/*<T extends num>*/(num/*=T*/ x, num/*=T*/ y) { ... }
-```
-
-
-Note that the generic parameter is in scope in the return type of the function,
-in the argument list of the function, and in the body of the function.  When
-declaring local variables and parameters, you can also use the `/*=T*/` syntax with `var`.
-
-```dart
-// foo is a generic method that takes a single generic parameter S, and a value
-// x of type S
-void foo/*<S>*/(var /*=S*/ x) {
-  // In strong mode, y will also have type S
-  var /*=S*/ y = x;
-
-  // In strong mode, z will also have type S
-  dynamic /*=S*/ z = y;
-}
-```
-
-Anywhere that a type literal is expected, you can also use the `/*=T*/` syntax to
-produce a type literal from the generic method parameter.
-
-```dart
-void foo/*<S>*/(/*=S*/ x) {
-  // In strong mode, s will get the type literal for S
-  Type s = dynamic /*=S*/;
-
-  // In strong mode, this attempts to cast 3 as type S
-  var y = (3 as dynamic /*=S*/);
-}
-```
-
-You can use the `/*=T*/` syntax to replace any type with a generic type
-parameter, but you will usually want to replace `dynamic`. Otherwise, since the
-original type is used at runtime, it may cause checked mode errors:
-
-```dart
-List/*<T>*/ makeList/*<T extends num>*/() {
-  return new List<num /*=T*/>();
-}
-
-void main() {
-  List<int> list = makeList/*<int>*/(); // <-- Fails here.
-}
-```
-
-This program checks without error in strong mode but fails at runtime in checked
-mode since the list that gets created is a `List<num>`. A better choice is:
-
-```dart
-List/*<T>*/ makeList/*<T extends num>*/() {
-  return new List/*<T>*/();
-}
-
-void main() {
-  List<int> list = makeList/*<int>*/();
-}
-```
-
-## Instantiating generic classes with generic method parameters
-
-You can use generic method parameters to instantiate generic classes using the
-same `/*=T*/` syntax.
-
-```dart
-// foo is a generic method which returns a List<S> in strong mode,
-// but which returns List<dynamic> in normal mode.
-List<dynamic /*=S*/> foo/*<S>*/(/*=S*/ x) {
-   // l0 is a list literal whose reified type will be List<S> in strong mode,
-   // and List<dynamic> in normal mode.
-   var l0 = <dynamic /*=S*/>[x];
-
-   // as above, but with a regular constructor.
-   var l1 = new List<dynamic /*=S*/>();
-   return l1;
-}
-```
-
-In most cases, the entire type argument list to the generic class can be
-enclosed in parentheses, eliminating the need for explicitly writing `dynamic`.
-
-```dart
-// This is another way of writing the same code as above
-List/*<S>*/ foo/*<S>*/(/*=S*/ x) {
-   // The shorthand syntax is not yet supported for list and map literals
-   var l0 = <dynamic /*=S*/>[x];
-
-   // but with regular constructors you can use it
-   var l1 = new List/*<S>*/();
-   return l1;
-}
-```
-
-## Instantiating generic methods
-
-Generic methods can be called without passing type arguments.  Strong mode will
-attempt to infer the type arguments automatically.  If it is unable to do so,
-then the type arguments will be filled in with whatever their declared bounds
-are (by default, `dynamic`).
-
-```dart
-class C {
-  /*=S*/ inferableFromArgument/*<S>*/(/*=S*/ x) { return null;}
-  /*=S*/ notInferable/*<S>*/(int x) { return null;}
-}
-
-void main() {
-  C c = new C();
-  // This line will produce a type error, because strong mode will infer
-  // `int` as the generic argument to fill in for S
-  String x = c.inferableFromArgument(3);
-
-  // This line will not produce a type error, because strong mode is unable
-  // to infer a type and will fill in the type argument with `dynamic`.
-  String y = c.notInferable(3);
-}
-```
-
-In the case that strong mode cannot infer the generic type arguments, the same
-syntax that was shown above for instantiating generic classes can be used to
-instantiate generic methods explicitly.
-
-```dart
-void main() {
-  C c = new C();
-  // This line will produce a type error, because strong mode will infer
-  // `int` as the generic argument to fill in for S
-  String x = c.inferableFromArgument(3);
-
-  // This line will produce a type error in strong mode, because `int` is
-  // explicitly passed in as the argument to use for S
-  String y = c.notInferable/*<int>*/(3);
-}
-```
diff --git a/pkg/dev_compiler/doc/JS_CODEGEN.md b/pkg/dev_compiler/doc/JS_CODEGEN.md
deleted file mode 100644
index 11b9b8f..0000000
--- a/pkg/dev_compiler/doc/JS_CODEGEN.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Strong Mode and Idiomatic JavaScript
-
-**Note: This document is out of date.  Please see [Sound Dart](https://dart.dev/guides/language/sound-dart) for up-to-date
-documentation on Dart's type system.  The work below was a precursor towards Dart's current type system.**
-
-The Dart Dev Compiler (DDC) uses [Strong Mode](STRONG_MODE.md) to safely generate
-idiomatic JavaScript.  This enables better interoperability between Dart and JavaScript code.
-
-The standard Dart type system is unsound by design.  This means that static type annotations may not match the actual runtime values even when a program is running in checked mode.  This allows considerable flexibility, but it also means that Dart implementations cannot easily use these annotations for optimization or code generation.
-
-Because of this, existing Dart implementations require dynamic dispatch.  Furthermore, because Dart’s dispatch semantics are different from JavaScript’s, it effectively precludes mapping Dart calls to idiomatic JavaScript.  For example, the following Dart code:
-
-```dart
-var x = a.bar;
-b.foo("hello", x);
-```
-
-cannot easily be mapped to the identical JavaScript code.  If `a` does not contain a `bar` field, Dart requires a `NoSuchMethodError` while JavaScript simply returns undefined.  If `b` contains a `foo` method, but with the wrong number of arguments, Dart again requires a `NoSuchMethodError` while JavaScript either ignores extra arguments or fills in omitted ones with undefined.   
-
-To capture these differences, the Dart2JS compiler instead generates code that approximately looks like:
-
-```dart
-var x = getInterceptor(a).get$bar(a);
-getInterceptor(b).foo$2(b, "hello", x);
-```
-The “interceptor” is Dart’s dispatch table for the objects `a` and `b`, and the mangled names (`get$bar` and `foo$2`) account for Dart’s different dispatch semantics.
-
-The above highlights why Dart-JavaScript interoperability hasn’t been seamless: Dart objects and methods do not look like normal JavaScript ones.
-
-DDC relies on strong mode to map Dart calling conventions to normal JavaScript ones.  If `a` and `b` have static type annotations (with a type other than `dynamic`), strong mode statically verifies that they have a field `bar` and a 2-argument method `foo` respectively.  In this case, DDC safely generates the identical JavaScript:
-
-```javascript
-var x = a.bar;
-b.foo("hello", x);
-```
-
-Note that DDC still supports the `dynamic` type, but relies on runtime helper functions in this case.  E.g., if `a` and `b` are type `dynamic`, DDC instead generates:
-
-```javascript
-var x = dload(a, "bar");
-dsend(b, "foo", "hello", x);
-```
-
-where `dload` and `dsend` are runtime helpers that implement Dart dispatch semantics.  Programmers are encouraged to use static annotations to avoid this. Strong mode is able to use static checking to enforce much of what checked mode does at runtime.  In the code above, strong mode statically verifies that `b`’s type (if not `dynamic`) has a `foo` method that accepts a `String` as its first argument and `a.bar`’s type as its second.  If the code is sufficiently typed, runtime checks are unnecessary.
diff --git a/pkg/dev_compiler/doc/RUNTIME_SAFETY.md b/pkg/dev_compiler/doc/RUNTIME_SAFETY.md
deleted file mode 100644
index 8c86c10..0000000
--- a/pkg/dev_compiler/doc/RUNTIME_SAFETY.md
+++ /dev/null
@@ -1,198 +0,0 @@
-# Strong Mode in the Dart Dev Compiler
-
-## Overview
-
-In the Dart Dev Compiler (DDC), [static strong mode](STATIC_SAFETY.md) checks are augmented with stricter runtime behavior.  Together, they enforce the soundness of Dart type annotations.
-
-In general, and in contrast to Dart's checked mode, most safety is enforced statically, at analysis time.  DDC exploits this to generate relatively few runtime checks while still providing stronger guarantees than checked mode.
-
-In particular, DDC adds the following:
-
- - Stricter (but fewer) runtime type checks
- - Reified type narrowing
- - Restricted `is`/`as` checks
-
-In all these cases, DDC (with static checks) is stricter than standard checked mode (or production mode).  It may reject (either statically or at runtime) programs that run correctly in checked mode (similar to how checked mode may reject programs that run in production mode).
-
-On the other hand, programs that statically check and run correctly in DDC should also run the same in checked mode.  A caveat to note is that mirrors (or `runtimeType`) may show a more narrow type in DDC (though, in practice, programmers are discouraged from using these features for performance / code size reasons).
-
-## Runtime checks
-
-In practice, strong mode enforces most type annotations at compile time, and, thus, requires less work at runtime to enforce safety.  Consider the following Dart code:
-
-```dart
-String foo(Map<int, String> map, int x) {
-  return map[x.abs()];
-}
-```
-
-Strong mode enforces that the function `foo` is only invoked in a manner consistent with its signature.  DDC - which assumes strong mode static checking - inserts no further runtime checks.  In contrast, standard Dart checked mode would check the type of the parameters -- `map` and `x` -- along with the type of the return value at runtime on every invocation of `foo`.  Even Dart production mode, depending on the implementation and its ability to optimize, may require similar checking to dynamically dispatch the map lookup and the method call in the body of `foo`.
-
-Nevertheless, there are cases where DDC still requires runtime checks.  (Note: DDC may eventually provide a mode to elide these checks, but this would violate soundness and is beyond the scope of this document.)
-
-### Implicit casts
-
-Dart has flexible assignability rules.  Programmers are not required to explicitly cast from supertypes to subtypes.  For example, the following is valid Dart:
-
-```dart
-Object o = ...;
-String s = o;  // Implicit downcast
-String s2 = s.substring(1);
-```
-
-The assignment to `s` is an implicit downcast from `Object` to `String` and triggers a runtime check in DDC to ensure it is correct.
-
-Note that checked mode would also perform this runtime test.  Unlike checked mode, DDC would not require a check on the assignment to `s2` - this type is established statically.
-
-### Inferred variables
-
-Dart's inference may narrow the static type of certain variables.  If the variable is mutable, DDC enforces the narrower type at runtime when necessary.
-
-In the following example, strong mode will infer of the type of the local variable `y` as an `int`:  
-
-```dart
-int bar(Object x) {
-  var y = 0;
-  if (x != null) {
-    y = x;
-  }
-  return y.abs();
-}
-```
-
-This allows it to, for example, static verify the call to `y.abs()` and determine that it returns an `int`.  However, the parameter `x` is typed as `Object` and the assignment from `x` to `y` now requires a type check to ensure that `y` is only assigned an `int`.
-
-Note, strong mode and DDC are conservative by enforcing a tighter type than required by standard Dart checked mode.  For example, checked mode would accept a non-`int` `x` with an `abs` method that happened to return an `int`.  In strong mode, a programmer would have to explicitly opt into this behavior by annotating `y` as an `Object` or `dynamic`.
-
-### Covariant generics
-
-Strong mode preserves the covariance of Dart's generic classes.  To support this soundly, DDC injects runtime checks on parameters in method invocations whose type is a class type parameter.  Consider the call to `baz` in the parameterized class `A`:
-
-```dart
-class A<T> {
-  T baz(T x, int y) => x;
-}
-
-void foo(A<Object> a) {
-  a.baz(42, 38);
-}
-
-void main() {
-  var aString = new A<String>();
-  foo(aString);
-}
-```
-
-Statically, sound mode will not generate an error or warning on this code.  The call to `baz` in `foo` is statically valid as `42` is an `Object` (as required by the static type of `a`).  However, the runtime type of `a` in this example is the narrower `A<String>`.  At runtime, when baz is executed, DDC will check that the type of `x` matches the reified type parameter and, in this example, fail.
-
-Note, only `x` requires a runtime check.  Unlike checked mode, no runtime check is required for `y` or the return value.  Both are statically verified.
-
-### Dynamic operations
-
-Strong mode allows programmers to explicitly use `dynamic` as a type.  It also allows programmers to omit types, and in some of these cases inference may fall back on `dynamic` if it cannot determine a static type.  In these cases, DDC inserts runtime checks (typically in the form of runtime helper calls).  
-
-For example, in the following:
-
-```dart
-int foo(int x) => x + 1;
-
-void main() {
-  dynamic bar = foo;
-  bar("hello"); // DDC runtime error
-}
-```
-
-`foo` (via `bar`) is incorrectly invoked on a `String`.  There is no static error as `bar` is typed `dynamic`.  Instead DDC, performs extra runtime checking on the invocation of `bar`.  In this case, it would generate a runtime type error.  Note, if the type of `bar` had been omitted, it would have been inferred, and the error would have been reported statically.
-
-Nevertheless, there are situations where programmers may prefer a dynamic type for flexibility.
-
-## Runtime type Narrowing
-
-Strong mode statically infers tighter types for functions and generics.  In DDC, this is reflected in the reified type at runtime.  This allows DDC to enforce the stricter type soundly at runtime when necessary.
-
-In particular, this means that DDC may have a stricter concrete runtime type than other Dart implementations for generic classes and functions.  The DDC type will always be a subtype.
-
-This will impact execution in the following ways:
-  - DDC may trigger runtime errors where checked mode is forgiving.
-  - Code that uses reflection may observe a narrower type in DDC.
-
-### Allocation inference
-
-When strong infers a narrower type for a closure literal or other allocation expression, DDC reifies this narrower type at runtime.  As a result, it can soundly enforce typing errors at runtime.  
-
-The following is an example of where static checking fails to catch a typing error:
-
-```dart
-apply(int g(x), y) {
-  print(g(y));
-}
-
-typedef int Int2Int(int x);
-
-void main() {
-  Int2Int f = (x) => x + x;
-  apply(f, "hello");
-}
-```
-
-A programmer examining `apply` would reasonably expect it to print an `int` value.  The analyzer (with or without strong mode) fails to report a problem.  Standard Dart checked simply prints `"hellohello"`.  In DDC, however, a runtime error is thrown on the application of `g` in `apply`.  The closure literal assigned to `f` in `main` is reified as an `int -> int`, and DDC enforces this at runtime.
-
-In this example, if `apply` and its parameters were fully typed, strong mode would report a static error, and DDC would impose no runtime check.
-
-### Generic methods
-
-[Note: This is not yet implemented correctly.](https://github.com/dart-lang/dev_compiler/issues/301)
-
-Similarly, DDC requires that [generic methods](GENERIC_METHODS.md) return the correct reified type.  In strong mode, `Iterable.map` is a generic method.  In DDC, `lengths` in `main` will have a reified type of `List<int>`.  In `foo`, this will trigger a runtime error when a string is added to the list.
-
-```dart
-void foo(List l) {
-  l.add("a string");
-}
-
-void main() {
-  Iterable<String> list = <String>["hello", "world"];
-  List<int> lengths = list.map((x) => x.length).toList();
-  foo(lengths);
-  print(lengths[2]);
-}
-```
-
-Standard checked mode would print `"a string"` without error.
-
-## Is / As restrictions
-
-In standard Dart, `is` and `as` runtime checks expose the unsoundness of the type system in certain cases.  For example, consider:
-
-```dart
-var list = <dynamic>["hello", "world"];
-if (list is List<int>) {
-  ...
-} else if (list is List<String>) {
-  ...
-}
-```
-
-Perhaps surprisingly, the first test - `list is List<int>` - evaluates to true here.  Such code is highly likely to be erroneous.
-
-Strong mode provides a stricter subtyping check and DDC enforces this at runtime.  For compatibility with standard Dart semantics, however, DDC throws a runtime error when an `is` or `as` check would return a different answer with strong mode typing semantics.
-
-In the example above, the first `is` check would generate a runtime error.
-
-Note, we are exploring making this a static error or warning in strong mode.  In general, an expression:
-
-```dart
-x is T
-```
-
-or
-
-```dart
-x as T
-```
-
-is only guaranteed safe when `T` is a *ground type*:
-
-- A non-generic class type (e.g., `Object`, `String`, `int`, ...).
-- A generic class type where all type parameters are implicitly or explicitly `dynamic` (e.g., `List<dynamic>`, `Map`, …).
-- A function type where the return type and all parameter types are `dynamic` (e.g., (`dynamic`, `dynamic`) -> `dynamic`, ([`dynamic`]) -> `dynamic`).
diff --git a/pkg/dev_compiler/doc/STATIC_SAFETY.md b/pkg/dev_compiler/doc/STATIC_SAFETY.md
deleted file mode 100644
index 4710af4..0000000
--- a/pkg/dev_compiler/doc/STATIC_SAFETY.md
+++ /dev/null
@@ -1,530 +0,0 @@
-# Strong Mode Static Checking
-
-**Note: This document is out of date.  Please see [Sound Dart](https://dart.dev/guides/language/sound-dart) for up-to-date
-documentation on Dart's type system.  The work below was a precursor towards Dart's current type system.**
-
-## Overview
-
-The Dart programming language has an optional, unsound type system.  Although it is similar in appearance to languages such as Java, C#, or C++, its type system and static checking are fundamentally different.  It permits erroneous behavior in ways that may be surprising to programmers coming from those and other conventional typed languages.
-
-In Dart, static type annotations can be often misleading.  Dart code such as:
-
-```dart
-  var list = ["hello", "world"];
-  List<int> listOfInts = list;
-```
-
-produces neither static nor runtime errors.  Actual errors may show up much later on, e.g., with the following code, only at runtime on the invocation of `abs`:
-
-```dart
-  Iterable<int> iterableOfInts = listOfInts.map((i) => i.abs());
-```
-
-Strong mode aims to catch such errors early by validating that variables - e.g., `listOfInts` - actually match their corresponding static type annotations - e.g., `List<int>`.  It constrains the Dart programming language to a subset of programs that type check under a restricted set of rules.  It statically rejects examples such as the above.
-
-To accomplish this, strong mode involves the following:
-
- - **Type inference**.  Dart’s standard type rules treats untyped variables as `dynamic`, which
-suppresses any static warnings on them.  Strong mode infers static types based upon context.  In the example above, strong mode infers that `list` has type `List`.  Note, in strong mode, programmers may still explicitly use the `dynamic` type.
-
- - **Strict subtyping**.  Dart’s primary sources of unsoundness are due to its subtyping rules on function types and generic classes.  Strong mode restricts these: e.g., `List` may not used as `List<int>` in the example above.
-
- - **Generic methods**.  Standard Dart does not yet provide generic methods.  This makes certain polymorphic methods difficult to use soundly.  For example, the `List.map` invocation above is statically typed to return an `Iterable<dynamic>` in standard Dart.  Strong mode allows methods to be annotated as generic. `List.map` is statically typed to return an `Iterable<T>` where `T` is bound to `int` in the previous example.  A number of common higher-order methods are annotated and checked as generic in strong mode, and programmers may annotate their own methods as well.
-
-Strong mode is designed to work in conjunction with the Dart Dev Compiler (DDC), which uses static type verification to generate better code.  DDC augments strong mode static checking with a minimal set of [runtime checks](RUNTIME_SAFETY.md) that aim to provide full soundness of types.
-
-Strong mode static analysis may also be used alone for stricter error checking.
-
-Formal details of the strong mode type system may be found  [here](https://dart-lang.github.io/dev_compiler/strong-dart.pdf).
-
-## Usage
-
-Strong mode is now integrated into the Dart Analyzer.  The analyzer may be invoked in strong mode as follows:
-
-    $ dartanalyzer --strong myapp.dart
-
-Strong mode may also be enabled in IDEs by creating (if necessary) an `.analysis_options` file in your project and appending the following entry to it:
-
-```
-analyzer:
-  strong-mode: true
-```
-
-## Type Inference
-
-With strong mode, we want to provide stronger typing while preserving the
-terseness of Dart. [Idiomatic Dart
-code](https://dart.dev/guides/language/effective-dart) discourages type annotations
-outside of API boundaries, and user shouldn't have to add more types to get
-better checking. Instead, strong mode uses type inference.
-
-In Dart, per the specification, the static type of a variable `x` declared as:
-
-```dart
-var x = <String, String>{ "hello": "world"};
-```
-
-is `dynamic` as there is no explicit type annotation on the left-hand side. To discourage code bloat, the Dart style guide generally recommends omitting these type annotations in many situations.  In these cases, the benefits of strong mode would be lost.
-
-To avoid this, strong mode uses type inference.  In the case above, strong mode infers and enforces the type of `x` as `Map<String, String>`.  An important aspect to inference is ordering: when an inferred type may be used to infer another type.  To maximize the impact, we perform the following inference:
-
-- Top-level and static fields
-- Instance fields and methods
-- Local variables
-- Constructor calls and literals
-- Generic method invocations
-
-Inference may tighten the static type as compared to the Dart specification.  An implicitly dynamic type, either alone or in the context of a function or generic parameter type, is inferred to a more specific type.  This inference may result in stricter type errors than standard Dart.
-
-In [DDC](RUNTIME_SAFETY.md), inference may also affect the reified runtime type.
-
-### Top-level and Static Fields
-
-Strong mode infers any untyped top-level field or static field from the type of
-its initializer.  The static type of the declared variable is inferred as the static type of the initializer.  For example, consider:
-
-```dart
-var PI = 3.14159;
-var radius = 2;
-var circumference = 2 * PI * radius;
-```
-
-Strong mode infers the static type of `PI` as `double` and `radius` as `int` directly from their initializers.  It infers the static type of `circumference` as `double`, transitively using the other inferred types. Standard Dart rules would treat all of these static types as `dynamic`.  Note that the following later assignment would be allowed in standard Dart, but disallowed (as a static type error) in strong mode:
-```dart
-radius = "five inches";
-```
-Strong mode inference avoids circular dependences.  If a variable’s initializer expression refers to another variable whose type would be dependent (directly or indirectly) on the first, the static type of that other variable is treated as `dynamic` for the purpose of inference.
-
-### Instance Fields and Methods
-
-Strong mode performs two types of inference on instance fields and methods.
-
-The first uses base types to constrain overrides in subtypes.  Consider the following example:
-
-```dart
-abstract class A {
-   Map get m;
-   int value(int i);
-}
-
-class B extends A {
-   var m;
-   value(i) => m[i];
-   …
-}
-```
-
-In Dart, overridden method, getter, or setter types should be subtypes of the corresponding base class ones (otherwise, static warnings are given).  In standard Dart, the above declaration of `B` is not an error: both `m`’s getter type and `value`’s return type are `dynamic`.
-
-Strong mode -- without inference -- would disallow this: if `m` in `B` could be assigned any kind of object, including one that isn't a Map, it would violate the type contract in the declaration of `A`.
-
-However, rather than rejecting the above code, strong mode employs inference to tighten the static types to obtain a valid override.  The corresponding types in B are inferred as if it was:
-
-```dart
-class B extends A {
-  Map m;
-  int value(int i) => m[i];
-  …
-}
-```
-
-Note that tightening the argument type for `i` to `int` is not required for soundness; it is done for convenience as it is the typical intent.  The programmer may explicitly type this as `dynamic` or `Object` to avoid inferring the narrower type.
-
-The second form inference is limited to instance fields (not methods) and is similar to that on static fields.  For instance fields where the static type is omitted and an initializer is present, the field’s type is inferred as the initializer’s type.  In this continuation of our example:
-
-```dart
-class C extends A {
-  var y = 42;
-  var m = <int, int>{ 0: 38};
-  ...
-}
-```
-
-the instance field `y` has inferred type `int` based upon its initializer.  Note that override-based inference takes precedence over initializer-based inference.  The instance field `m` has inferred type `Map`, not `Map<int, int>` due to the corresponding declaration in `A`.
-
-### Local Variables
-
-As with fields, local variable types are inferred if the static type is omitted and an initializer expression is present.  In the following example:
-
-```dart
-Object foo(int x) {
-   final y = x + 1;
-   var z = y * 2;
-   return z;
-}
-```
-
-the static types of `y` and `z` are both inferred as `int` in strong mode.  Note that local inference is done in program order: the inferred type of `z` is computed using the inferred type of `y`. Local inference may result in strong mode type errors in otherwise legal Dart code.  In the above, a second assignment to `z` with a string value:    
-```dart
-z = "$z";
-```
-would trigger a static error in strong mode, but is allowed in standard Dart.  In strong mode, the programmer must use an explicit type annotation to suppress inference.  Explicitly declaring `z` with the type `Object` or `dynamic` would suffice in this case.
-
-### Constructor Calls and Literals
-
-Strong mode also performs contextual inference on allocation expressions.  This inference is rather different from the above: it tightens the runtime type of the corresponding expression using the static type of its context.  Contextual inference is used on expressions that allocate a new object: closure literals, map and list literals, and explicit constructor invocations (i.e., via `new` or `const`).
-
-In DDC, these inferred types are also [reified at runtime](RUNTIME_SAFETY.md) on the newly allocated objects to provide a stronger soundness guarantee.
-
-#### Closure literals
-
-Consider the following example:
-
-```dart
-int apply(int f(int arg), int value) {
-  return f(value);
-}
-
-void main() {  
-  int result =
-    apply((x) { x = x * 9 ~/ 5; return x + 32; }, 41);
-  print(result);
-}
-```
-
-The function `apply` takes another function `f`, typed `(int) -> int`, as its first argument.  It is invoked in `main` with a closure literal.  In standard Dart, the static type of this closure literal would be `(dynamic) -> dynamic`.  In strong mode, this type cannot be safely converted to `(int) -> int` : it may return a `String` for example.   
-
-Dart has a syntactic limitation in this case: it is not possible to statically annotate the return type of a closure literal.
-
-Strong mode sidesteps this difficulty via contextual inference.  It infers the closure type as `(int) -> int`.  Note, this may trigger further inference and type checks in the body of the closure.
-
-#### List and map literals
-
-Similarly, strong mode infers tighter runtime types for list and map literals.  E.g., in
-
-```dart
-List<String> words = [ "hello", "world" ];
-```
-
-the runtime type is inferred as `List<String>` in order to match the context of the left hand side.  In other words, the code above type checks and executes as if it was:
-
-```dart
-List<String> words = <String>[ "hello", "world" ];
-```
-
-Similarly, the following will now trigger a static error in strong mode:
-
-```dart
-List<String> words = [ "hello", 42 ]; // Strong Mode Error: 42 is not a String
-```
-
-Contextual inference may be recursive:
-
-```dart
-Map<List<String>, Map<int, int>> map =
-	{ ["hello"]: { 0: 42 }};
-```
-
-In this case, the inner map literal is inferred as a `Map<int, int>`.  Note, strong mode will statically reject code where the contextually required type is not compatible.  This will trigger a static error:
-
-```dart
-Map<List<String>, Map<int, int>> map =
-  { ["hello"]: { 0: "world" }}; // STATIC ERROR
-```
-
-as "world" is not of type `int`.
-
-#### Constructor invocations
-
-Finally, strong mode performs similar contextual inference on explicit constructor invocations via `new` or `const`.  For example:
-
-```dart
-Set<String> string = new Set.from(["hello", "world"]);
-```
-
-is treated as if it was written as:
-
-```dart
-Set<String> string =
-  new Set<String>.from(<String>["hello", "world"]);
-```
-
-Note, as above, context is propagated downward into the expression.
-
-## Strict subtyping
-
-The primary sources of unsoundness in Dart are generics and functions.  Both introduce circularity in the Dart subtyping relationship.
-
-### Generics
-
-Generics in Dart are covariant, with the added rule that the `dynamic` type may serve as both ⊤ (top) and ⊥ (bottom) of the type hierarchy in certain situations.  For example, let *<:<sub>D</sub>*  represent the standard Dart subtyping rule.  Then, for all types `S` and `T`:
-
-`List<S>` <:<sub>D</sub> `List<dynamic>` <:<sub>D</sub> `List<T>`
-
-where `List` is equivalent to `List<dynamic>`.  This introduces circularity - e.g.:
-
-`List<int>` <:<sub>D</sub> `List` <:<sub>D</sub> `List<String>`<:<sub>D</sub> `List` <:<sub>D</sub> `List<int>`
-
-From a programmer’s perspective, this means that, at compile-time, values that are statically typed `List<int>` may later be typed `List<String>` and vice versa.  At runtime, a plain `List` can interchangeably act as a `List<int>` or a `List<String>` regardless of its actual values.
-
-The example taken from [here](https://github.com/dart-lang/dev_compiler/blob/strong/STRONG_MODE.md#motivation) exploits this:
-
-```dart
-class MyList extends ListBase<int> implements List {
-   Object length;
-
-   MyList(this.length);
-
-   operator[](index) => "world";
-   operator[]=(index, value) {}
-}
-```
-
-A `MyList` may masquerade as a `List<int>` as it is transitively a subtype:
-
-`MyList` <:<sub>D</sub> `List` <:<sub>D</sub>`List<int>`
-
-In strong mode, we introduce a stricter subtyping rule <:<sub>S</sub> to disallow this.  In this case, in the context of a generic type parameter, dynamic may only serve as ⊤.  This means that this is still true:
-
-`List<int>` <:<sub>S</sub> `List`
-
-but that this is not:
-
-`List` ~~<:<sub>S</sub> `List<int>`~~
-
-The example above fails in strong mode:
-
-`MyList` <:<sub>S</sub> `List` ~~<:<sub>S</sub> `List<int>`~~
-
-
-### Functions
-
-The other primary source of unsoundness in Dart is function subtyping.  An unusual feature of the Dart type system is that function types are bivariant in both the parameter types and the return type (see Section 19.5 of the [Dart specification][dartspec]).  As with generics, this leads to circularity:
-
-`(int) -> int` <:<sub>D</sub> `(Object) -> Object` <:<sub>D</sub> `(int) -> int`
-
-And, as before, this can lead to surprising behavior.  In Dart, an overridden method’s type should be a subtype of the base class method’s type (otherwise, a static warning is given).  In our running example, the (implicit) `MyList.length` getter has type:
-
-`() -> Object`
-
-while the `List.length` getter it overrides has type:
-
-`() -> int`
-
-This is valid in standard Dart as:
-
-`() -> Object` <:<sub>D</sub> `() -> int`
-
-Because of this, a `length` that returns "hello" (a valid `Object`) triggers no static or runtime warnings or errors.
-
-Strong mode enforces the stricter, [traditional function subtyping](https://en.wikipedia.org/wiki/Subtyping#Function_types) rule: subtyping is contravariant in parameter types and covariant in return types.  This permits:
-
-`() -> int` <:<sub>S</sub> `() -> Object`
-
-but disallows:
-
-`() -> Object` <:<sub>S</sub> `() -> int`
-
-With respect to our example, strong mode requires that any subtype of a List have an int-typed length.  It statically rejects the length declaration in MyList.
-
-## Generic Methods
-
-Strong mode introduces generic methods to allow more expressive typing on polymorphic methods.  Such code in standard Dart today often loses static type information.  For example, the `Iterable.map` method is declared as below:
-
-```dart
-abstract class Iterable<E> {
-  ...
-  Iterable map(f(E e));
-}
-```
-
-Regardless of the static type of the function `f`, the `map` always returns an `Iterable<dynamic>` in standard Dart.  As result, standard Dart tools miss the obvious error on the following code:
-
-```dart
-Iterable<int> results = <int>[1, 2, 3].map((x) => x.toString()); // Static error only in strong mode
-```
-
-The variable `results` is statically typed as if it contains `int` values, although it clearly contains `String` values at runtime.
-
-The [generic methods proposal](https://github.com/leafpetersen/dep-generic-methods/blob/master/proposal.md) adds proper generic methods to the Dart language as a first class language construct and to make methods such as the `Iterable.map` generic.
-
-To enable experimentation, strong mode provides a [generic methods prototype](GENERIC_METHODS.md) based on the existing proposal, but usable on all existing Dart implementations today.  Strong mode relies on this to report the error on the example above.
-
-The `Iterable.map` method is now declared as follows:
-
-```dart
-abstract class Iterable<E> {
-  ...
-  Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E e));
-}
-```
-
-At a use site, the generic type may be explicitly provided or inferred from context:
-
-```
-  var l = <int>[1, 2, 3];
-  var i1 = l.map((i) => i + 1);
-  var l2 = l.map/*<String>*/((i) { ... });
-```
-
-In the first invocation of `map`, the closure is inferred (from context) as `int -> int`, and the generic type of map is inferred as `int` accordingly.  As a result, `i1` is inferred as `Iterable<int>`.  In the second, the type parameter is explicitly bound to `String`, and the closure is checked against this type.  `i2` is typed as `Iterable<String>`.
-
-Further details on generic methods in strong mode and in DDC may be found [here](GENERIC_METHODS.md).
-
-## Additional Restrictions
-
-In addition to stricter typing rules, strong mode enforces other
-restrictions on Dart programs.
-
-### Warnings as Errors
-
-Strong mode effectively treats all standard Dart static warnings as static errors.  Most of these warnings are required for soundness (e.g., if a concrete class is missing methods required by a declared interface).  A full list of Dart static warnings may found in the [Dart specification][dartspec], or enumerated here:
-
-[https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/lib/src/generated/error.dart#L3772](https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fdart-lang%2Fsdk%2Fblob%2Fmaster%2Fpkg%2Fanalyzer%2Flib%2Fsrc%2Fgenerated%2Ferror.dart%23L3772&sa=D&sntz=1&usg=AFQjCNFc4E37M1PshVcw4zk7C9jXgqfGbw)
-
-### Super Invocations
-
-In the context of constructor initializer lists, strong mode restricts `super` invocations to the end.  This restriction simplifies generated code with minimal effect on the program.
-
-### For-in loops
-
-In for-in statements of the form:
-
-```dart
-for (var i in e) { … }
-```
-
-Strong mode requires the expression `e` to be an `Iterable`.  When the loop variable `i` is also statically typed:
-
-```dart
-for (T i in e) { … }
-```
-
-the expression `e` is required to be an `Iterable<T>`.
-
-*Note: we may weaken these.*
-
-### Field overrides
-
-By default, fields are overridable in Dart.  
-
-```dart
-int init(int n) {
-  print('Initializing with $n');
-  return n;
-}
-
-class A {
-  int x = init(42);
-}
-
-class B extends A {
-  int x;
-}
-```
-
-Disallow overriding fields: this results in complicated generated
-code where a field definition in a subclass shadows the field
-  definition in a base class but both are generally required to be
-  allocated.  Users should prefer explicit getters and setters in such
-  cases.  See [issue 52](https://github.com/dart-lang/dev_compiler/issues/52).
-
-## Optional Features
-
-### Disable implicit casts
-
-This is an optional feature of strong mode. It disables implicit down casts. For example:
-
-```dart
-main() {
-  num n = 0.5;
-  int x = n; // error: invalid assignment
-  int y = n as int; // ok at compile time, might fail when run
-}
-```
-
-Casts from `dynamic` must be explicit as well:
-
-```dart
-main() {
-  dynamic d = 'hi';
-  int x = d; // error: invalid assignment
-  int y = d as int; // ok at compile time, might fail when run
-}
-```
-
-This option is experimental and may be changed or removed in the future.
-Try it out in your project by editing .analysis_options:
-
-```yaml
-analyzer:
-  strong-mode:
-    implicit-casts: False
-```
-
-Or pass `--no-implicit-casts` to Dart Analyzer:
-
-```
-dartanalyzer --strong --no-implicit-casts my_app.dart
-```
-
-### Disable implicit dynamic
-
-This is an optional feature of analyzer, intended primarily for use with strong mode's inference.
-It rejects implicit uses of `dynamic` that strong mode inference fails to fill in with a concrete type,
-ensuring that all types are either successfully inferred or explicitly written. For example:
-
-```dart
-main() {
-  var x; // error: implicit dynamic
-  var i = 123; // okay, inferred to be `int x`
-  dynamic y; // okay, declared as dynamic
-}
-```
-
-This also affects: parameters, return types, fields, creating objects with generic type, generic functions/methods, and
-supertypes:
-
-```dart
-// error: parameters and return types are implicit dynamic
-f(x) => x + 42;
-dynamic f(dynamic x) => x + 42; // okay
-int f(int x) => x + 42; // okay
-
-class C {
-  var f; // error: implicit dynamic field
-  dynamic f; // okay
-}
-
-main() {
-  var x = []; // error: implicit List<dynamic>
-  var y = [42]; // okay: List<int>
-  var z = <dynamic>[]; // okay: List<dynamic>
-  
-  T genericFn<T>() => null;
-  genericFn(); // error: implicit genericFn<dynamic>
-  genericFn<dynamic>(); // okay
-  int x = genericFn(); // okay, inferred genericFn<int>
-}
-
-// error: implicit supertype Iterable<dynamic>
-class C extends Iterable { /* ... */ }
-// okay
-class C extends Iterable<dynamic> { /* ... */ }
-```
-
-This feature is to prevent accidental use of `dynamic` in code that does not intend to use it.
-
-This option is experimental and may be changed or removed in the future.
-Try it out in your project by editing .analysis_options:
-
-```yaml
-analyzer:
-  strong-mode:
-    implicit-dynamic: False
-```
-
-Or pass `--no-implicit-dynamic` to Dart Analyzer:
-
-```
-dartanalyzer --strong --no-implicit-dynamic my_app.dart
-```
-
-### Open Items
-
-- Is / As restrictions: Dart's `is` and `as` checks are unsound for certain types
-(generic classes, certain function types).  In [DDC](RUNTIME_SAFETY.md), problematic
-`is` and `as` checks trigger runtime errors.  We are considering introducing static
-errors for these cases.
-
-[dartspec]: https://dart.dev/guides/language/spec "Dart Language Spec"
diff --git a/pkg/dev_compiler/doc/definition/macros.tex b/pkg/dev_compiler/doc/definition/macros.tex
deleted file mode 100644
index a5e4a1e..0000000
--- a/pkg/dev_compiler/doc/definition/macros.tex
+++ /dev/null
@@ -1,67 +0,0 @@
-%%% Cascaded items for math mode
-%% start with \begin{cascade}
-%% new line at previous indentation with \cascline
-%% new line with greater indentation with \cascitem
-%% end with \end{cascade}
-%% default indentation is 2em, adjust with \cascadeindent
-\newdimen\cascadeindent
-\cascadeindent=1em\newdimen\cascdimen
-\newcommand{\cascindent}{\global\advance\cascdimen by\cascadeindent \hspace{\cascdimen}}
-\newcommand{\cascitem}{\\ \global\advance\cascdimen by\cascadeindent \hspace{\cascdimen}}
-\newcommand{\cascback}[1]{\\ \global\advance\cascdimen by-#1.0\cascadeindent \hspace{\cascdimen}}
-\newcommand{\cascline}{\\ \hspace{\cascdimen}}
-\newenvironment{cascade}{\begin{array}[t]{@{}l@{}} \global\cascdimen=0em}{\end{array}}
-
-
-%%% Binding colon stuff
-\mathchardef\col="003A  % \col for binding colon (mathcode ordinary: less space)
-\mathchardef\semi="603B % \semi for (regular) semicolon
-%% use \semicolonforbindingcolon to redefine ; to stand for binding colon
-\newcommand{\semicolonforbindingcolon}{\mathcode`;="003A}
-
-%%% Angle bracket stuff
-\mathchardef\lt="313C  % \lt for <
-\mathchardef\gt="313E  % \gt for >
-%% use \ltgtforanglebrackets to redefine <,> to stand for \langle, \rangle
-\newcommand{\ltgtforanglebrackets}{\mathcode`<="4268 \mathcode`>="5269}
-
-\newcommand{\kwop}[1]{\ensuremath{\mathop{\mathbf{#1}}}}
-\newcommand{\kwbin}[1]{\ensuremath{\mathbin{\mathbf{#1}}}}
-\newcommand{\kw}[1]{\ensuremath{\mathord{\mathbf{#1}}}}
-
-\newcommand{\comment}[1]{\hfill \fbox{\Large{#1}}}
-
-%\newcommand{\qed}{\rule{5pt}{8pt}} 
-\newcommand{\thmbox}
-   {{\ \hfill\hbox{%
-      \vrule width1.0ex height1.0ex
-   }\parfillskip 0pt}}
-
-\newenvironment{proof}{{\textbf{Proof:} }}{\thmbox}
-\newenvironment{proofsketch}{{\textbf{Proof (Sketch):} }}{\thmbox}
-
-\newcommand{\thmstep}[2]{
-  \noindent\begin{tabular}{@{}l@{}l}
-    \lefteqn{\mbox{#1}} &\\
-    \mbox{  } & $\begin{array}{l}#2\end{array}$
-  \end{tabular}
-  }
-
-\newcommand{\thmstepp}[2]{
-  \noindent\begin{tabular}{lll}
-    \lefteqn{\mbox{#1}} &\\
-    \mbox{  } & #2
-  \end{tabular}
-  }
-
-\newcommand{\ifthenthm}[2]{
-  \noindent\begin{tabular}[t]{@{}l@{}l}
-    If & \\
-    & $\begin{array}[t]{l}#1\end{array}$ \\
-    then & \\
-    & $\begin{array}[t]{l}#2\end{array}$
-  \end{tabular}
-  }
-
-% symbol abbreviations
-\newcommand{\stepsto}{\longmapsto}
diff --git a/pkg/dev_compiler/doc/definition/proof.sty b/pkg/dev_compiler/doc/definition/proof.sty
deleted file mode 100644
index c272a81..0000000
--- a/pkg/dev_compiler/doc/definition/proof.sty
+++ /dev/null
@@ -1,259 +0,0 @@
-%	proof.sty	(Proof Figure Macros)
-%
-% 	version 3.1 (for both LaTeX 2.09 and LaTeX 2e)
-%	Nov 24, 2005
-% 	Copyright (C) 1990 -- 2005, Makoto Tatsuta (tatsuta@nii.ac.jp)
-% 
-% This program is free software; you can redistribute it or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation; either versions 1, or (at your option)
-% any later version.
-% 
-% This program is distributed in the hope that it will be useful
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-%	Usage:
-%		In \documentstyle, specify an optional style `proof', say,
-%			\documentstyle[proof]{article}.
-%
-%	The following macros are available:
-%
-%	In all the following macros, all the arguments such as
-%	<Lowers> and <Uppers> are processed in math mode.
-%
-%	\infer<Lower><Uppers>
-%		draws an inference.
-%
-%		Use & in <Uppers> to delimit upper formulae.
-%		<Uppers> consists more than 0 formulae.
-%
-%		\infer returns \hbox{ ... } or \vbox{ ... } and
-%		sets \@LeftOffset and \@RightOffset globally.
-%
-%	\infer[<Label>]<Lower><Uppers>
-%		draws an inference labeled with <Label>.
-%
-%	\infer*<Lower><Uppers>
-%		draws a many step deduction.
-%
-%	\infer*[<Label>]<Lower><Uppers>
-%		draws a many step deduction labeled with <Label>.
-%
-%	\infer=<Lower><Uppers>
-%		draws a double-ruled deduction.
-%
-%	\infer=[<Label>]<Lower><Uppers>
-%		draws a double-ruled deduction labeled with <Label>.
-%
-%	\deduce<Lower><Uppers>
-%		draws an inference without a rule.
-%
-%	\deduce[<Proof>]<Lower><Uppers>
-%		draws a many step deduction with a proof name.
-%
-%	Example:
-%		If you want to write
-%       	       	    B C
-%		 	   -----
-%		       A     D
-%		      ----------
-%			  E
-%	use
-%		\infer{E}{
-%			A
-%			&
-%			\infer{D}{B & C}
-%		}
-%
-
-%	Style Parameters
-
-\newdimen\inferLineSkip		\inferLineSkip=2pt
-\newdimen\inferLabelSkip	\inferLabelSkip=5pt
-\def\inferTabSkip{\quad}
-
-%	Variables
-
-\newdimen\@LeftOffset	% global
-\newdimen\@RightOffset	% global
-\newdimen\@SavedLeftOffset	% safe from users
-
-\newdimen\UpperWidth
-\newdimen\LowerWidth
-\newdimen\LowerHeight
-\newdimen\UpperLeftOffset
-\newdimen\UpperRightOffset
-\newdimen\UpperCenter
-\newdimen\LowerCenter
-\newdimen\UpperAdjust
-\newdimen\RuleAdjust
-\newdimen\LowerAdjust
-\newdimen\RuleWidth
-\newdimen\HLabelAdjust
-\newdimen\VLabelAdjust
-\newdimen\WidthAdjust
-
-\newbox\@UpperPart
-\newbox\@LowerPart
-\newbox\@LabelPart
-\newbox\ResultBox
-
-%	Flags
-
-\newif\if@inferRule	% whether \@infer draws a rule.
-\newif\if@DoubleRule	% whether \@infer draws doulbe rules.
-\newif\if@ReturnLeftOffset	% whether \@infer returns \@LeftOffset.
-
-%	Special Fonts
-
-\def\DeduceSym{\vtop{\baselineskip4\p@ \lineskiplimit\z@
-    \vbox{\hbox{.}\hbox{.}\hbox{.}}\hbox{.}}}
-
-%	Macros
-
-% Renaming @ifnextchar and @ifnch of LaTeX2e to @IFnextchar and @IFnch.
-
-\def\@IFnextchar#1#2#3{%
-  \let\reserved@e=#1\def\reserved@a{#2}\def\reserved@b{#3}\futurelet
-    \reserved@c\@IFnch}
-\def\@IFnch{\ifx \reserved@c \@sptoken \let\reserved@d\@xifnch
-      \else \ifx \reserved@c \reserved@e\let\reserved@d\reserved@a\else
-          \let\reserved@d\reserved@b\fi
-      \fi \reserved@d}
-
-\def\@ifEmpty#1#2#3{\def\@tempa{\@empty}\def\@tempb{#1}\relax
-	\ifx \@tempa \@tempb #2\else #3\fi }
-
-\def\infer{\@IFnextchar *{\@inferSteps}{\relax
-	\@IFnextchar ={\@inferDoubleRule}{\@inferOneStep}}}
-
-\def\@inferOneStep{\@inferRuletrue \@DoubleRulefalse
-	\@IFnextchar [{\@infer}{\@infer[\@empty]}}
-
-\def\@inferDoubleRule={\@inferRuletrue \@DoubleRuletrue
-	\@IFnextchar [{\@infer}{\@infer[\@empty]}}
-
-\def\@inferSteps*{\@IFnextchar [{\@@inferSteps}{\@@inferSteps[\@empty]}}
-
-\def\@@inferSteps[#1]{\@deduce{#1}[\DeduceSym]}
-
-\def\deduce{\@IFnextchar [{\@deduce{\@empty}}
-	{\@inferRulefalse \@infer[\@empty]}}
-
-%	\@deduce<Proof Label>[<Proof>]<Lower><Uppers>
-
-\def\@deduce#1[#2]#3#4{\@inferRulefalse
-	\@infer[\@empty]{#3}{\@infer[{#1}]{#2}{#4}}}
-
-%	\@infer[<Label>]<Lower><Uppers>
-%		If \@inferRuletrue, it draws a rule and <Label> is right to
-%		a rule. In this case, if \@DoubleRuletrue, it draws
-%		double rules.
-%
-%		Otherwise, draws no rule and <Label> is right to <Lower>.
-
-\def\@infer[#1]#2#3{\relax
-% Get parameters
-	\if@ReturnLeftOffset \else \@SavedLeftOffset=\@LeftOffset \fi
-	\setbox\@LabelPart=\hbox{$#1$}\relax
-	\setbox\@LowerPart=\hbox{$#2$}\relax
-%
-	\global\@LeftOffset=0pt
-	\setbox\@UpperPart=\vbox{\tabskip=0pt \halign{\relax
-		\global\@RightOffset=0pt \@ReturnLeftOffsettrue $##$&&
-		\inferTabSkip
-		\global\@RightOffset=0pt \@ReturnLeftOffsetfalse $##$\cr
-		#3\cr}}\relax
-	\UpperLeftOffset=\@LeftOffset
-	\UpperRightOffset=\@RightOffset
-% Calculate Adjustments
-	\LowerWidth=\wd\@LowerPart
-	\LowerHeight=\ht\@LowerPart
-	\LowerCenter=0.5\LowerWidth
-%
-	\UpperWidth=\wd\@UpperPart \advance\UpperWidth by -\UpperLeftOffset
-	\advance\UpperWidth by -\UpperRightOffset
-	\UpperCenter=\UpperLeftOffset
-	\advance\UpperCenter by 0.5\UpperWidth
-%
-	\ifdim \UpperWidth > \LowerWidth
-		% \UpperCenter > \LowerCenter
-	\UpperAdjust=0pt
-	\RuleAdjust=\UpperLeftOffset
-	\LowerAdjust=\UpperCenter \advance\LowerAdjust by -\LowerCenter
-	\RuleWidth=\UpperWidth
-	\global\@LeftOffset=\LowerAdjust
-%
-	\else	% \UpperWidth <= \LowerWidth
-	\ifdim \UpperCenter > \LowerCenter
-%
-	\UpperAdjust=0pt
-	\RuleAdjust=\UpperCenter \advance\RuleAdjust by -\LowerCenter
-	\LowerAdjust=\RuleAdjust
-	\RuleWidth=\LowerWidth
-	\global\@LeftOffset=\LowerAdjust
-%
-	\else	% \UpperWidth <= \LowerWidth
-		% \UpperCenter <= \LowerCenter
-%
-	\UpperAdjust=\LowerCenter \advance\UpperAdjust by -\UpperCenter
-	\RuleAdjust=0pt
-	\LowerAdjust=0pt
-	\RuleWidth=\LowerWidth
-	\global\@LeftOffset=0pt
-%
-	\fi\fi
-% Make a box
-	\if@inferRule
-%
-	\setbox\ResultBox=\vbox{
-		\moveright \UpperAdjust \box\@UpperPart
-		\nointerlineskip \kern\inferLineSkip
-		\if@DoubleRule
-		\moveright \RuleAdjust \vbox{\hrule width\RuleWidth
-			\kern 1pt\hrule width\RuleWidth}\relax
-		\else
-		\moveright \RuleAdjust \vbox{\hrule width\RuleWidth}\relax
-		\fi
-		\nointerlineskip \kern\inferLineSkip
-		\moveright \LowerAdjust \box\@LowerPart }\relax
-%
-	\@ifEmpty{#1}{}{\relax
-%
-	\HLabelAdjust=\wd\ResultBox	\advance\HLabelAdjust by -\RuleAdjust
-	\advance\HLabelAdjust by -\RuleWidth
-	\WidthAdjust=\HLabelAdjust
-	\advance\WidthAdjust by -\inferLabelSkip
-	\advance\WidthAdjust by -\wd\@LabelPart
-	\ifdim \WidthAdjust < 0pt \WidthAdjust=0pt \fi
-%
-	\VLabelAdjust=\dp\@LabelPart
-	\advance\VLabelAdjust by -\ht\@LabelPart
-	\VLabelAdjust=0.5\VLabelAdjust	\advance\VLabelAdjust by \LowerHeight
-	\advance\VLabelAdjust by \inferLineSkip
-%
-	\setbox\ResultBox=\hbox{\box\ResultBox
-		\kern -\HLabelAdjust \kern\inferLabelSkip
-		\raise\VLabelAdjust \box\@LabelPart \kern\WidthAdjust}\relax
-%
-	}\relax % end @ifEmpty
-%
-	\else % \@inferRulefalse
-%
-	\setbox\ResultBox=\vbox{
-		\moveright \UpperAdjust \box\@UpperPart
-		\nointerlineskip \kern\inferLineSkip
-		\moveright \LowerAdjust \hbox{\unhbox\@LowerPart
-			\@ifEmpty{#1}{}{\relax
-			\kern\inferLabelSkip \unhbox\@LabelPart}}}\relax
-	\fi
-%
-	\global\@RightOffset=\wd\ResultBox
-	\global\advance\@RightOffset by -\@LeftOffset
-	\global\advance\@RightOffset by -\LowerWidth
-	\if@ReturnLeftOffset \else \global\@LeftOffset=\@SavedLeftOffset \fi
-%
-	\box\ResultBox
-}
diff --git a/pkg/dev_compiler/doc/definition/static-semantics.tex b/pkg/dev_compiler/doc/definition/static-semantics.tex
deleted file mode 100644
index b103d95..0000000
--- a/pkg/dev_compiler/doc/definition/static-semantics.tex
+++ /dev/null
@@ -1,1062 +0,0 @@
-\subsection*{Field lookup}
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \\
-          \fieldDecl{x}{\tau} \in \many{\mathit{ce}}
-        }
-        {\fieldLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{x}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}}
-        }
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad x \notin \many{\mathit{ce}} \\
-         \fieldLookup{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{x}{\tau}
-        }
-        {\fieldLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{x}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}}
-        }
-
-
-\subsection*{Method lookup}
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \\
-          \methodDecl{m}{\tau}{\sigma} \in \many{\mathit{ce}}
-        }
-        {\methodLookup{\Phi}
-          {\TApp{C}{\tau_0, \ldots, \tau_n}}{m}
-          {\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}}
-          {\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\sigma}}
-        }
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad m \notin \many{\mathit{ce}} \\
-         \methodLookup{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{m}{\tau}{\sigma}
-        }
-        {\methodLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{m}
-          {\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}}
-          {\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\sigma}}
-        }
-
-\subsection*{Method and field absence}
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad x \notin \many{\mathit{ce}} \\
-         \fieldAbsent{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{x}
-        }
-        {\fieldAbsent{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{x}
-        }
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad m \notin \many{\mathit{ce}} \\
-         \methodAbsent{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{m}{\tau}{\sigma}
-        }
-        {\methodAbsent{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{m}
-        }
-
-\iftrans{
-
-\subsection*{Type translation}
-
-To translate covariant generics, we essentially want to treat all contravariant
-occurrences of type variables as $\Dynamic$.  The type translation
-$\down{\tau}$ implements this.  It is defined in terms of the dual operator
-$\up{\tau}$ which translates positive occurences of type variables as $\Dynamic$.
-
-\begin{eqnarray*}
-  \down{T} & = & T \\
-  \down{\Arrow[k]{\tau_0, \ldots, \tau_n}{\tau_r}} & = & 
-     \Arrow[k]{\up{\tau_0}, \ldots, \up{\tau_n}}{\down{\tau_r}} \\
-  \down{\TApp{C}{\tau_0, \ldots, \tau_n}} & = & \TApp{C}{\down{\tau_0}, \ldots, \down{\tau_n}} \\
-  \down{\tau} & = & \tau\ \mbox{otherwise}
-\end{eqnarray*}
-
-\begin{eqnarray*}
-  \up{T} & = & \Dynamic \\
-  \up{\Arrow[k]{\tau_0, \ldots, \tau_n}{\tau_r}} & = & 
-     \Arrow[k]{\down{\tau_0}, \ldots, \down{\tau_n}}{\up{\tau_r}} \\
-  \up{\TApp{C}{\tau_0, \ldots, \tau_n}} & = & \TApp{C}{\up{\tau_0}, \ldots, \up{\tau_n}} \\
-  \up{\tau} & = & \tau\ \mbox{if $\tau$ is base type.}
-\end{eqnarray*}
-
-
-}
-\subsection*{Expression typing: $\yieldsOk{\Phi, \Delta, \Gamma}{e}{\opt{\tau}}{e'}{\tau'}$} 
-\hrulefill\\
-
-
-\sstext{ Expression typing is a relation between typing contexts, a term ($e$),
-  an optional type ($\opt{\tau}$), and a type ($\tau'$).  The general idea is
-  that we are typechecking a term ($e$) and want to know if it is well-typed.
-  The term appears in a context, which may (or may not) impose a type constraint
-  on the term.  For example, in $\dvar{x:\tau}{e}$, $e$ appears in a context
-  which requires it to be a subtype of $\tau$, or to be coercable to $\tau$.
-  Alternatively if $e$ appears as in $\dvar{x:\_}{e}$, then the context does not
-  provide a type constraint on $e$.  This ``contextual'' type information is
-  both a constraint on the term, and may also provide a source of information
-  for type inference in $e$.  The optional type $\opt{\tau}$ in the typing
-  relation corresponds to this contextual type information.  Viewing the
-  relation algorithmically, this should be viewed as an input to the algorithm,
-  along with the term.  The process of checking a term allows us to synthesize a
-  precise type for the term $e$ which may be more precise than the type required
-  by the context.  The type $\tau'$ in the relation represents this more
-  precise, synthesized type.  This type should be thought of as an output of the
-  algorithm.  It should always be the case that the synthesized (output) type is
-  a subtype of the checked (input) type if the latter is present.  The
-  checking/synthesis pattern allows for the propagation of type information both
-  downwards and upwards. 
-
-  It is often the case that downwards propagation is not useful.  Consequently,
-  to simplify the presentation the rules which do not use the checking type
-  require that it be empty ($\_$).  This does not mean that such terms cannot be
-  checked when contextual type information is supplied: the first typing rule
-  allows contextual type information to be dropped so that such rules apply in
-  the case that we have contextual type information, subject to the contextual
-  type being a supertype of the synthesized type:
-
-}{
-For subsumption, the elaboration of the underlying term carries through.
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\sigma} \quad\quad
-         \subtypeOf{\Phi, \Delta}{\sigma}{\tau}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}{e}{\tau}{e'}{\sigma}} 
-
-\sstext{
-The implicit downcast rule also allows this when the contextual type is a
-subtype of the synthesized type, corresponding to an implicit downcast.
-}{
-In an implicit downcast, the elaboration adds a check so that an error
-will be thrown if the types do not match at runtime.
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\sigma} \quad\quad
-         \subtypeOf{\Phi, \Delta}{\tau}{\sigma}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}{e}{\tau}{\echeck{e'}{\tau}}{\tau}} 
-
-\sstext{Variables are typed according to their declarations:}{}
-
-\axiom{\yieldsOk{\Phi, \Delta, \extends{\Gamma}{x}{\tau}}{x}{\_}{x}{\tau}}
-
-\sstext{Numbers, booleans, and null all have a fixed synthesized type.}{}
-
-\axiom{\yieldsOk{\Phi, \Delta, \Gamma}{i}{\_}{i}{\Num}}
-
-\axiom{\yieldsOk{\Phi, \Delta, \Gamma}{\eff}{\_}{\eff}{\Bool}} 
-
-\axiom{\yieldsOk{\Phi, \Delta, \Gamma}{\ett}{\_}{\ett}{\Bool}} 
-
-\axiom{\yieldsOk{\Phi, \Delta, \Gamma}{\enull}{\_}{\enull}{\Bottom}} 
-
-\sstext{A $\ethis$ expression is well-typed if we are inside of a method, and $\sigma$
-is the type of the enclosing class.}{}
-
-\infrule{\Gamma = \Gamma'_{\sigma}
-        }
-        {
-          \yieldsOk{\Phi, \Delta, \Gamma}{\ethis}{\_}{\ethis}{\sigma}
-        } 
-
-\sstext{A fully annotated function is well-typed if its body is well-typed at its
-declared return type, under the assumption that the variables have their
-declared types.  
-}{
-
-A fully annotated function elaborates to a function with an elaborated body.
-The rest of the function elaboration rules fill in the reified type using
-contextual information if present and applicable, or $\Dynamic$ otherwise.
-
-}
-
-\infrule{\Gamma' = \extends{\Gamma}{\many{x}}{\many{\tau}} \quad\quad 
-         \stmtOk{\Phi, \Delta, \Gamma'}{s}{\sigma}{s'}{\Gamma'}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{\many{x:\tau}}{\sigma}{s}}
-                  {\_}
-                  {\elambda{\many{x:\tau}}{\sigma}{s'}}
-                  {\Arrow[-]{\many{\tau}}{\sigma}}
-        } 
-
-\sstext{A function with a missing argument type is well-typed if it is well-typed with
-the argument type replaced with $\Dynamic$.}
-{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{x_0:\opt{\tau_0}, \ldots, x_i:\Dynamic, \ldots, x_n:\opt{\tau_n}}{\opt{\sigma}}{s}}
-                  {\opt{\tau}}
-                  {e_f}
-                  {\tau_f}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{x_0:\opt{\tau_0}, \ldots, x_i:\_, \ldots, x_n:\opt{\tau_n}}{\opt{\sigma}}{s}}
-                  {\opt{\tau}}
-                  {e_f}
-                  {\tau_f}
-        } 
-
-\sstext{A function with a missing argument type is well-typed if it is well-typed with
-the argument type replaced with the corresponding argument type from the context
-type.  Note that this rule overlaps with the previous: the formal presentation
-leaves this as a non-deterministic choice.}{}
-
-\infrule{\tau_c = \Arrow[k]{\upsilon_0, \ldots, \upsilon_n}{\upsilon_r} \\
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{x_0:\opt{\tau_0}, \ldots, x_i:\upsilon_i, \ldots, x_n:\opt{\tau_n}}{\opt{\sigma}}{s}}
-                  {\tau_c}
-                  {e_f}
-                  {\tau_f}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{x_0:\opt{\tau_0}, \ldots, x_i:\_, \ldots, x_n:\opt{\tau_n}}{\opt{\sigma}}{s}}
-                  {\tau_c}
-                  {e_f}
-                  {\tau_f}
-        } 
-
-\sstext{A function with a missing return type is well-typed if it is well-typed with
-the return type replaced with $\Dynamic$.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{\many{x:\opt{\tau}}}{\Dynamic}{s}}
-                  {\opt{\tau_c}}
-                  {e_f}
-                  {\tau_f}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{\many{x:\opt{\tau}}}{\_}{s}}
-                  {\opt{\tau_c}}
-                  {e_f}
-                  {\tau_f}
-        } 
-
-\sstext{A function with a missing return type is well-typed if it is well-typed with
-the return type replaced with the corresponding return type from the context
-type.  Note that this rule overlaps with the previous: the formal presentation
-leaves this as a non-deterministic choice.  }{}
-
-\infrule{\tau_c = \Arrow[k]{\upsilon_0, \ldots, \upsilon_n}{\upsilon_r} \\
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{\many{x:\opt{\tau}}}{\upsilon_r}{s}}
-                  {\tau_c}
-                  {e_f}
-                  {\tau_f}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\elambda{\many{x:\opt{\tau}}}{\_}{s}}
-                  {\tau_c}
-                  {e_f}
-                  {\tau_f}
-        } 
-
-
-\sstext{Instance creation creates an instance of the appropriate type.}{}
-
-% FIXME(leafp): inference
-% FIXME(leafp): deal with bounds
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\ldots}) \in \Phi \\ 
-  \mbox{len}(\many{\tau}) = n+1}
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\enew{C}{\many{\tau}}{}}
-                  {\_}
-                  {\enew{C}{\many{\tau}}{}}
-                  {\TApp{C}{\many{\tau}}}
-        } 
-
-
-\sstext{Members of the set of primitive operations (left unspecified) can only be
-applied.  Applications of primitives are well-typed if the arguments are
-well-typed at the types given by the signature of the primitive.}{}
-
-\infrule{\eprim\, :\, \Arrow[]{\many{\tau}}{\sigma} \quad\quad
-         \yieldsOk{\Phi, \Delta, \Gamma}{e}{\tau}{e'}{\tau'}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eprimapp{\eprim}{\many{e}}}
-                  {\_}
-                  {\eprimapp{\eprim}{\many{e'}}}
-                  {\sigma}
-        } 
-
-\sstext{Function applications are well-typed if the applicand is well-typed and has
-function type, and the arguments are well-typed.}
-{
-
-Function application of an expression of function type elaborates to either a
-call or a dynamic (checked) call, depending on the variance of the applicand.
-If the applicand is a covariant (fuzzy) type, then a dynamic call is generated.
-
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\_}
-                  {e'}
-                  {\Arrow[k]{\many{\tau_a}}{\tau_r}} \\
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {e_a}
-                  {\tau_a}
-                  {e_a'}
-                  {\tau_a'} \quad \mbox{for}\ e_a, \tau_a \in \many{e_a}, \many{\tau_a} 
-\iftrans{\\         e_c = \begin{cases}
-                 \ecall{e'}{\many{e_a'}} & \text{if $k = -$}\\
-                 \edcall{e'}{\many{e_a'}} & \text{if $k = +$}
-                 \end{cases}}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\ecall{e}{\many{e_a}}}
-                  {\_}
-                  {e_c}
-                  {\tau_r}
-        } 
-
-\sstext{Application of an expression of type $\Dynamic$ is well-typed if the arguments
-are well-typed at any type. }
-{
-
-  Application of an expression of type $\Dynamic$ elaborates to a dynamic call.
-
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\_}
-                  {e'}
-                  {\Dynamic} \\
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {e_a}
-                  {\_}
-                  {e_a'}
-                  {\tau_a'} \quad \mbox{for}\ e_a \in \many{e_a}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\ecall{e}{\many{e_a}}}
-                  {\_}
-                  {\edcall{e'}{\many{e_a'}}}
-                  {\Dynamic}
-        } 
-
-\iftrans{
-\sstext{A dynamic call expression is well-typed so long as the applicand and the
-arguments are well-typed at any type.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\Dynamic}
-                  {e'}
-                  {\tau} \\
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {e_a}
-                  {\_}
-                  {e_a'}
-                  {\tau_a} \quad \mbox{for}\ e_a \in \many{e_a}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\edcall{e}{\many{e_a}}}
-                  {\_}
-                  {\edcall{e'}{\many{e_a'}}}
-                  {\Dynamic}
-        }
-
-}
-
-\sstext{A method load is well-typed if the term is well-typed, and the method name is
-present in the type of the term.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\_}
-                  {e'}
-                  {\sigma} \quad\quad
-         \methodLookup{\Phi}{\sigma}{m}{\sigma}{\tau}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eload{e}{m}}
-                  {\_}
-                  {\eload{e'}{m}}
-                  {\tau}
-        }
-
-\sstext{A method load from a term of type $\Dynamic$ is well-typed if the term is
-well-typed.}
-{
-
-  A method load from a term of type $\Dynamic$ elaborates to a dynamic (checked)
-  load.
-
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\Dynamic}
-                  {e'}
-                  {\tau} 
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eload{e}{m}}
-                  {\_}
-                  {\edload{e'}{m}}
-                  {\Dynamic}
-        }
-
-\iftrans{
-\sstext{A dynamic method load is well typed so long as the term is well-typed.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\Dynamic}
-                  {e'}
-                  {\tau} 
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\edload{e}{m}}
-                  {\_}
-                  {\edload{e'}{m}}
-                  {\Dynamic}
-        }
-
-}
-
-\sstext{A field load from $\ethis$ is well-typed if the field name is present in the
-type of $\ethis$.}{}
-
-\infrule{\Gamma = \Gamma_\tau & \fieldLookup{\Phi}{\tau}{x}{\sigma}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eload{\ethis}{x}}
-                  {\_}
-                  {\eload{\ethis}{x}}
-                  {\sigma}
-        } 
-
-\sstext{An assignment expression is well-typed so long as the term is well-typed at a
-type which is compatible with the type of the variable being assigned.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\opt{\tau}}
-                  {e'}
-                  {\sigma} \quad\quad
-        \yieldsOk{\Phi, \Delta, \Gamma}
-                  {x}
-                  {\sigma}
-                  {x}
-                  {\sigma'}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eassign{x}{e}}
-                  {\opt{\tau}}
-                  {\eassign{x}{e'}}
-                  {\sigma}
-        } 
-
-\sstext{A field assignment is well-typed if the term being assigned is well-typed, the
-field name is present in the type of $\ethis$, and the declared type of the
-field is compatible with the type of the expression being assigned.}{}
-
-\infrule{\Gamma = \Gamma_\tau \quad\quad 
-         \yieldsOk{\Phi, \Delta, \Gamma}
-                  {e}
-                  {\opt{\tau}}
-                  {e'}
-                  {\sigma} \\
-        \fieldLookup{\Phi}{\tau}{x}{\sigma'} \quad\quad
-        \subtypeOf{\Phi, \Delta}{\sigma}{\sigma'}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eset{\ethis}{x}{e}}
-                  {\_}
-                  {\eset{\ethis}{x}{e}}
-                  {\sigma}
-        } 
-
-\sstext{A throw expression is well-typed at any type.}{}
-
-\axiom{\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\ethrow}
-                  {\_}
-                  {\ethrow}
-                  {\sigma}
-        } 
-
-\sstext{A cast expression is well-typed so long as the term being cast is well-typed.
-The synthesized type is the cast-to type.  We require that the cast-to type be a
-ground type.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\sigma} \quad\quad \mbox{$\tau$ is ground}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eas{e}{\tau}}
-                  {\_}
-                  {\eas{e'}{\tau}}
-                  {\tau}
-        } 
-
-\sstext{An instance check expression is well-typed if the term being checked is
-well-typed. We require that the cast to-type be a ground type.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\sigma} \quad\quad \mbox{$\tau$ is ground}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\eis{e}{\tau}}
-                  {\_}
-                  {\eis{e'}{\tau}}
-                  {\Bool}
-        } 
-
-\iftrans{
-
-\sstext{A check expression is well-typed so long as the term being checked is
-well-typed.  The synthesized type is the target type of the check.}{}
-
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\sigma}
-        }
-        {\yieldsOk{\Phi, \Delta, \Gamma}
-                  {\echeck{e}{\tau}}
-                  {\_}
-                  {\echeck{e'}{\tau}}
-                  {\tau}
-        } 
-
-}
-
-\subsection*{Declaration typing: $\declOk[d]{\Phi, \Delta, \Gamma}{\mathit{vd}}{\mathit{vd'}}{\Gamma'}$}
-\hrulefill\\
-
-\sstext{
-Variable declaration typing checks the well-formedness of the components, and
-produces an output context $\Gamma'$ which contains the binding introduced by
-the declaration.
-
-A simple variable declaration with a declared type is well-typed if the
-initializer for the declaration is well-typed at the declared type.  The output
-context binds the variable at the declared type.
-}
-{
-  Elaboration of declarations elaborates the underlying expressions.  
-}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\tau}{e'}{\tau'}
-        }
-        {\declOk[d]{\Phi, \Delta, \Gamma}
-                {\dvar{x:\tau}{e}}
-                {\dvar{x:\tau'}{e'}}
-                {\extends{\Gamma}{x}{\tau}}
-        }
-
-\sstext{A simple variable declaration without a declared type is well-typed if the
-initializer for the declaration is well-typed at any type.  The output context
-binds the variable at the synthesized type (a simple form of type inference).}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\tau'}
-        }
-        {\declOk[d]{\Phi, \Delta, \Gamma}
-                {\dvar{x:\_}{e}}
-                {\dvar{x:\tau'}{e'}}
-                {\extends{\Gamma}{x}{\tau'}}
-        }
-
-\sstext{A function declaration is well-typed if the body of the function is well-typed
-with the given return type, under the assumption that the function and its
-parameters have their declared types.  The function is assumed to have a
-contravariant (precise) function type.  The output context binds the function
-variable only.}{}
-
-\infrule{\tau_f = \Arrow[-]{\many{\tau_a}}{\tau_r} \quad\quad 
-         \Gamma' = \extends{\Gamma}{f}{\tau_f} \quad\quad
-         \Gamma'' = \extends{\Gamma'}{\many{x}}{\many{\tau_a}} \\
-         \stmtOk{\Phi, \Delta, \Gamma''}{s}{\tau_r}{s'}{\Gamma_0}
-        }
-        {\declOk[d]{\Phi, \Delta, \Gamma}
-                {\dfun{\tau_r}{f}{\many{x:\tau_a}}{s}}
-                {\dfun{\tau_r}{f}{\many{x:\tau_a}}{s'}}
-                {\Gamma'}
-        }
-
-\subsection*{Statement typing: $\stmtOk{\Phi, \Delta, \Gamma}{\mathit{s}}{\tau}{\mathit{s'}}{\Gamma'}$}
-\hrulefill\\
-
-\sstext{The statement typing relation checks the well-formedness of statements and
-produces an output context which reflects any additional variable bindings
-introduced into scope by the statements.
-}{
-
-Statement elaboration elaborates the underlying expressions.
-
-}
-
-\sstext{A variable declaration statement is well-typed if the variable declaration is
-well-typed per the previous relation, with the corresponding output context.
-}{}
-
-\infrule{\declOk[d]{\Phi, \Delta, \Gamma}
-                {\mathit{vd}}
-                {\mathit{vd'}}
-                {\Gamma'}
-        }
-        {\stmtOk{\Phi, \Delta, \Gamma}
-                {\mathit{vd}}
-                {\tau}
-                {\mathit{vd'}}
-                {\Gamma'}
-        }
-
-\sstext{An expression statement is well-typed if the expression is well-typed at any
-type per the expression typing relation.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\_}{e'}{\tau}
-        }
-        {\stmtOk{\Phi, \Delta, \Gamma}{e}{\tau}{e'}{\Gamma}
-        }
-
-\sstext{A conditional statement is well-typed if the condition is well-typed as a
-boolean, and the statements making up the two arms are well-typed.  The output
-context is unchanged.}{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\Bool}{e'}{\sigma} \\
-         \stmtOk{\Phi, \Delta, \Gamma}{s_1}{\tau_r}{s_1'}{\Gamma_1} \quad\quad
-         \stmtOk{\Phi, \Delta, \Gamma}{s_2}{\tau_r}{s_2'}{\Gamma_2} 
-        }
-        {\stmtOk{\Phi, \Delta, \Gamma}
-                {\sifthenelse{e}{s_1}{s_2}}
-                {\tau_r}
-                {\sifthenelse{e'}{s_1'}{s_2'}}
-                {\Gamma}
-        }
-
-\sstext{A return statement is well-typed if the expression being returned is well-typed
-at the given return type.  }{}
-
-\infrule{\yieldsOk{\Phi, \Delta, \Gamma}{e}{\tau_r}{e'}{\tau}
-        }
-        {\stmtOk{\Phi, \Delta, \Gamma}{\sreturn{e}}{\tau_r}{\sreturn{e'}}{\Gamma}
-        }
-
-\sstext{A sequence statement is well-typed if the first component is well-typed, and the
-second component is well-typed with the output context of the first component as
-its input context.  The final output context is the output context of the second
-component.}{}
-
-\infrule{\stmtOk{\Phi, \Delta, \Gamma}{s_1}{\tau_r}{s_1'}{\Gamma'} \quad\quad
-         \stmtOk{\Phi, \Delta, \Gamma'}{s_2}{\tau_r}{s_2'}{\Gamma''}
-        }
-        {\stmtOk{\Phi, \Delta, \Gamma}{s_1;s_2}{\tau_r}{s_1';s_2'}{\Gamma''}
-        }
-
-\subsection*{Class member typing:  $\declOk[ce]{\Phi, \Delta, \Gamma}{\mathit{vd} : \mathit{ce}}{\mathit{vd}'}{\Gamma'}$}
-\hrulefill\\
-
-\sstext{ 
-
-A class member is well-typed with a given signature ($\mathit{ce}$) taken from
-the class hierarchy if the signature type matches the type on the definition,
-and if the definition is well-typed.
-
-}
-{
-
-Elaborating class members is done with respect to a signature.  The field
-translation simply translates the field as a variable declaration.
-
-}
-
-
-\infrule{
-          \declOk[d]{\Phi, \Delta, \Gamma}
-                 {\dvar{x:\opt{\tau}}{e}}
-                 {\mathit{vd'}}
-                 {\Gamma'}
-        }
-        {
-          \declOk[ce]{\Phi, \Delta, \Gamma}
-                 {\dvar{x:\opt{\tau}}{e} : \fieldDecl{x}{\opt{\tau}}}
-                 {\mathit{vd'}}
-                 {\Gamma'}
-        }
-
-
-\iftrans{
-
-Translating methods requires introducing guard expressions.  The signature
-provides an internal and an external type for the method.  The external type is
-the original declared type of the method, and is the signature which the method
-presents to external clients.  Because we implement covariant generics, clients
-may see an instantiation of this signature which will allow them to violate the
-contract expected by the implementation.  To handle this, we rewrite the method
-to match an internal signature which is in fact soundly covariant in the type
-parameters (that is, all contravariant type parameters are replaced with
-$\Dynamic$, and hence all remaining type parameters occur in properly covariant
-positions).  This property is enforced in the override checking relation: from
-the perspective of this relation, there is simply another internal type which
-defines how to wrap the method with guards.
-
-The translation insists that the internal and external types be function types
-of the appropriate arity, and that the external type is equal to the type of the
-declaration.  The declaration is translated using the underlying function
-definition translation, but is then wrapped with guards to enforce the type
-contract, producing a valid function of the internal (covariant) type.  The
-original body of the function is wrapped in a lambda function, which is applied
-using a dynamic call which checks that the arguments (which may have negative
-occurrences of type variables which are treated as $\Dynamic$ in the internal
-type) are appropriate for the actual body.  The original function returns a type
-$\tau_r$ which may be a super-type of the internal type (since negative
-occurrences of type variables must be treated as dynamic), and so we insert a
-check expression to guard against runtime type mismatches here.
-
-This is a very simplistic translation for now.  We could choose, in the case
-that the body returns a lambda, to push the checking down into the lambda
-(essentially wrapping it in place).  
-
-}
-
-\infrule{ \mathit{vd} = \dfun{\tau_r}{f}{x_0:\tau_0, \ldots, x_n:\tau_n}{s} \\
-          \sigma_e = \Arrow[+]{\tau_0, \ldots, \tau_n}{\tau_r} 
-\iftrans{\quad\quad 
-                 \sigma_i = \Arrow{\upsilon_0, \ldots, \upsilon_n}{\upsilon_r}
-} \\
-          \declOk[d]{\Phi, \Delta, \Gamma}
-                 {\mathit{vd}}
-                 {\dfun{\tau_r}{f}{x_0:\tau_0, \ldots, x_n:\tau_n}{s'}}
-                 {\Gamma'}
-\iftrans{\\
-                 e_g = \elambda{x_0:\tau_0, \ldots, x_n:\tau_n}{\tau_r}{s'}\\
-                 s_g = \sreturn{(\echeck{\edcall{e_g}{x_0 , \ldots, x_n}}{\upsilon_r})} \\
-                 \mathit{vd}_g = \dfun{\upsilon_r}{f}{x_0:\upsilon_0, \ldots, x_n:\upsilon_n}{s_g} 
-}
-        }
-        {
-          \declOk[ce]{\Phi, \Delta, \Gamma}
-                 {\mathit{vd} : \methodDecl{f}{\sigma_i}{\sigma_e}}
-                 {\mathit{vd}_g}
-                 {\Gamma'}
-        }
-
-\subsection*{Class declaration typing:  $\declOk[c]{\Phi, \Gamma}{\mathit{cd}}{\mathit{cd'}}{\Gamma'}$}
-\hrulefill\\
-
-\sstext{ 
-
-A class declaration is well-typed with a given signature ($\Sig$) taken from the
-class hierarchy if the signature matches the definition, and if each member of
-the class is well-typed with the corresponding signature from the class
-signature.  The members are checked with the generic type parameters bound in
-the type context, and with the type of the current class set as the type of
-$\ethis$ on the term context $\Gamma$.
-
-}
-{
-
-Elaboration of a class requires that the class hierarchy $\Phi$ have a matching
-signature for the class declaration.  Each class member in the class is
-elaborated using the corresponding class element from the signature.
-
-}
-
-
-\infrule{\mathit{cd} = \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\mathit{vd}_0, \ldots, \mathit{vd}_n} \\
-         (C : \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\mathit{ce}_0, \ldots, \many{ce}_n}) \in \Phi \\ 
-         \Delta = \many{T} \quad 
-         \Gamma_i = 
-         \begin{cases}
-           \Gamma_{\TApp{C}{\many{T}}} & \mbox{if $\mathit{vd}_i$ is a method} \\
-           \Gamma & \mbox{if $\mathit{vd}_i$ is a field} \\
-         \end{cases}\\
-
-         \declOk[ce]{\Phi, \Delta, \Gamma_i}{\mathit{vd}_i : \mathit{ce}_i}{\mathit{vd}'_i}{\Gamma'_i} \quad\quad
-         \mbox{for}\ i \in 0, \ldots, n 
-\iftrans{\\
-         \mathit{cd'} = \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\many{\mathit{vd'}}}
-}
-        }
-        {\declOk[c]{\Phi, \Gamma}
-                   {\mathit{cd}}
-                   {\mathit{cd'}}{\Gamma'}
-        }
-
-\subsection*{Override checking:\\  \quad\quad$\overrideOk{\Phi}
-                                             {\TApp{C}{T_0, \ldots, T_n}}
-                                             {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                                             {\mathit{ce}}$}
-\hrulefill\\
-
-\sstext{
-
-The override checking relation is the primary relation that checks the
-consistency of the class hierarchy.  We assume a non-cyclic class hierarchy as a
-syntactic pre-condition.  The override check relation checks that in a class
-declaration $\TApp{C}{T_0, \ldots, T_n}$ which extends $\TApp{G}{\tau_0, \ldots,
-  \tau_k}$, the definition of an element with signature $\mathit{ce}$ is valid.  
-
-}{
-
-Override checking remains largely the same, with the exception of additional
-consistency constraints on the internal signatures for methods.
-
-}
-
-\sstext{
-
-A field with the type elided is a valid override if the same field with type
-$\Dynamic$ is valid.
-
-}{
-
-}
-
-\infrule{
-           \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\fieldDecl{x}{\Dynamic}}
-
-        }
-        {
-         \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\fieldDecl{x}{\_}}
-        }
-
-\sstext{
-
-A field with a type $\tau$ is a valid override if it appears in the super type
-with the same type.
-
-}{
-
-}
-
-\infrule{\fieldLookup{\Phi}{\TApp{G}{\tau_0, \ldots, \tau_k}}{x}{\tau}
-        }
-        {
-         \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\fieldDecl{x}{\tau}}
-        }
-
-\sstext{
-
-A field with a type $\tau$ is a valid override if it does not appear in the super type.
-
-}{
-
-}
-
-\infrule{\fieldAbsent{\Phi}{\TApp{G}{\tau_0, \ldots, \tau_k}}{x}
-        }
-        {
-         \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\fieldDecl{x}{\tau}}
-        }
-
-\sstext{
-
-A method with a type $\sigma$ is a valid override if it does not appear in the super type.
-
-}{
-
-For a non-override method, we require that the internal type $\tau$ be a subtype
-of $\down{\sigma}$ where $\sigma$ is the declared type.  Essentially, this
-enforces the property that the initial declaration of a method in the hierarchy
-has a covariant internal type.
-
-}
-
-\infrule{
-\iftrans{
-      \Delta = T_0, \ldots, T_n \quad\quad
-      \subtypeOf{\Phi, \Delta}{\tau}{\down{\sigma}}\ \\
-}
-      \methodAbsent{\Phi}{\TApp{G}{\tau_0, \ldots, \tau_k}}{f}
-    }
-    {
-      \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\methodDecl{f}{\tau}{\sigma}}
-    }
-
-\sstext{
-
-A method with a type $\sigma$ is a valid override if it appears in the super
-type, and $\sigma$ is a subtype of the type of the method in the super class.
-
-}{
-
-For a method override, we require two coherence conditions.  As before, we
-require that the internal type $\tau$ be a subtype of the $\down{\sigma}$ where
-$\sigma$ is the external type.  Moreover, we also insist that the external type
-$\sigma$ be a subtype of the external type of the method in the superclass, and
-that the internal type $\tau$ be a subtype of the internal type in the
-superclass.  Note that it this last consistency property that ensures that
-covariant generics are ``poisonous'' in the sense that non-generic subclasses of
-generic classes must still have additional checks.  For example, a superclass
-with a method of external type $\sigma_s = \Arrow{T}{T}$ will have internal type
-$\tau_s = \Arrow{\Dynamic}{T}$.  A subclass of an instantiation of this class
-with $\Num$ can validly override this method with one of external type $\sigma =
-\Arrow{\Num}{\Num}$.  This is unsound in general since the argument occurrence
-of $T$ in $\sigma_s$ is contra-variant.  However, the additional consistency
-requirement is that the internal type of the subclass method must be a subtype
-of $\subst{\Num}{T}{\tau_s} = \Arrow{\Dynamic}{\Num}$.  This enforces the
-property that the overridden method must expect to be used at type
-$\Arrow{\Dynamic}{\Num}$, and hence must check its arguments (and potentially
-its return value as well in the higher-order case).  This checking code is
-inserted during the elaboration of class members above.
-
-  }
-
-\infrule{
-\iftrans{
-      \Delta = T_0, \ldots, T_n \quad\quad 
-      \subtypeOf{\Phi, \Delta}{\tau}{\down{\sigma}}\ \\
-}
-      \methodLookup{\Phi}{\TApp{G}{\tau_0, \ldots, \tau_k}}{f}{\tau_s}{\sigma_s} \\
-\iftrans{
-      \subtypeOf{\Phi, \Delta}{\tau}{\tau_s}\quad\quad 
-}
-      \subtypeOf{\Phi, \Delta}{\sigma}{\sigma_s}
-    }
-    {
-      \overrideOk{\Phi}
-                 {\TApp{C}{T_0, \ldots, T_n}}
-                 {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                 {\methodDecl{f}{\tau}{\sigma}}
-    }
-
-\subsection*{Toplevel declaration typing:  $\declOk[t]{\Phi, \Gamma}{\mathit{td}}{\mathit{td'}}{\Gamma'}$}
-\hrulefill\\
-
-\sstext{
-
-Top level variable declarations are well-typed if they are well-typed according
-to their respective specific typing relations.
-
-}{
-
-Top level declaration elaboration falls through to the underlying variable and
-class declaration code.
-
-}
-
-\infrule
-    {\declOk[d]{\Phi, \epsilon, \Gamma}{\mathit{vd}}{\mathit{vd'}}{\Gamma'}
-      
-    }
-    {\declOk[t]{\Phi, \Gamma}{\mathit{vd}}{\mathit{vd'}}{\Gamma'}
-    }
-
-\infrule
-    {\declOk[c]{\Phi, \Gamma}{\mathit{cd}}{\mathit{cd'}}{\Gamma'}
-      
-    }
-    {\declOk[t]{\Phi, \Gamma}{\mathit{cd}}{\mathit{cd'}}{\Gamma'}
-    }
-
-
-\subsection*{Well-formed class signature:  $\ok{\Phi}{\Sig}$}
-\hrulefill\\
-
-\sstext{
-
-The well-formed class signature relation checks whether a class signature is
-well-formed with respect to a given class hierarchy $\Phi$.
-
-}{
-
-}
-
-\sstext{
-
-The $\Object$ signature is always well-formed.
-
-}{
-
-}
-
-\axiom{\ok{\Phi}{\Object}
-      }
-
-\sstext{
-
-A signature for a class $C$ is well-formed if its super-class signature is
-well-formed, and if every element in its signature is a valid override of the
-super-class.
-
-}{
-
-}
-
-\infrule{\Sig = \dclass{\TApp{C}{\many{T}}}
-                              {\TApp{G}{\tau_0, \ldots, \tau_k}}
-                              {\mathit{ce}_0, \ldots, \mathit{ce}_n} \\
-        (G : \Sig') \in \Phi \quad\quad \ok{\Phi}{\Sig'} \\
-        \overrideOk{\Phi}{\TApp{C}{\many{T}}}{\TApp{G}{\tau_0, \ldots, \tau_k}}{\mathit{ce}_i} 
-        \quad\quad
-        \mbox{for}\ \mathit{ce}_i \in \mathit{ce}_0, \ldots, \mathit{ce}_n 
-        }
-        {\ok{\Phi}{\Sig}
-        }
-
-\subsection*{Well-formed class hierarchy:  $\ok{}{\Phi}$}
-\hrulefill\\
-
-\sstext{
-
-A class hierarchy is well-formed if all of the signatures in it are well-formed
-with respect to it.
-
-}{
-
-}
-
-\infrule{\ok{\Phi}{\Sig}\ \mbox{for}\, \Sig\, \in \Phi
-        }
-        {\ok{}{\Phi}
-        }
-
-\subsection*{Program typing:  $\programOk{\Phi}{P}{P'}$}
-\hrulefill\\
-
-%%Definitions:
-%%
-%% \begin{eqnarray*}
-%% \sigof{\mathit{vd}} & = &
-%%   \begin{cases}
-%%     \fieldDecl{x}{\tau} & \mbox{if}\ \mathit{vd} = \dvar{x:\tau}{e}\\
-%%     \fieldDecl{x}{\Dynamic} & \mbox{if}\ \mathit{vd} = \dvar{x:\_}{e}\\
-%%     \methodDecl{f}{\tau_f}{\Arrow[+]{\many{\tau}}{\sigma}} & \mbox{if}\ \mathit{vd} = \dfun{\sigma}{f}{\many{x:\tau}}{s}
-%% \end{cases}\\
-%% \sigof{\mathit{cd}} & = & C\, : \, \dclass{\TApp{C}{\many{T}}}
-%%                                          {\TApp{G}{\tau_0, \ldots, \tau_k}}
-%%                                          {\mathit{ce}_0, \ldots, \mathit{ce}_n} \\
-%% \mbox{where} && 
-%%          \mathit{cd} = \dclass{\TApp{C}{\many{T}}}
-%%                               {\TApp{G}{\tau_0, \ldots, \tau_k}}
-%%                               {\mathit{vd}_0, \ldots, \mathit{vd}_n} \\
-%% \mbox{and} &&
-%%         \mathit{ce}_i = \sigof{vd_i} \quad \mbox{for}\ i \in 0, \ldots, n 
-%%\end{eqnarray*}
-
-\sstext{
-
-Program well-formedness is defined with respect to a class hierarchy $\Phi$.  It
-is not specified how $\Phi$ is produced, but the well-formedness constraints in
-the various judgments should constrain it appropriately.  A program is
-well-formed if each of the top level declarations in the program is well-formed
-in a context in which all of the previous variable declarations have been
-checked and inserted in the context, and if the body of the program is
-well-formed in the final context.  We allow classes to refer to each other in
-any order, since $\Phi$ is pre-specified, but do not model out of order
-definitions of top level variables and functions.  We assume as a syntactic
-property that the class hierarchy $\Phi$ is acyclic.
-
-}{
-
-}
-
-\infrule{  \Gamma_0 = \epsilon \quad\quad
-           \declOk[t]{\Phi, \Gamma_i}{\mathit{td}_i}{\mathit{td}'_i}{\Gamma_{i+1}} \quad 
-           \mbox{for}\ i \in 0,\ldots,n\\
-           \stmtOk{\Phi, \epsilon, \Gamma_{n+1}}{s}{\tau}{s'}{\Gamma_{n+1}'}
-        }
-        { \programOk{\Phi}{\program{\mathit{td}_0, \ldots, \mathit{td}_n}{s}}
-          {\program{\mathit{td}'_0, \ldots, \mathit{td}'_n}{s'}}
-        }
diff --git a/pkg/dev_compiler/doc/definition/strong-dart.pdf b/pkg/dev_compiler/doc/definition/strong-dart.pdf
deleted file mode 100644
index 1b58a47..0000000
--- a/pkg/dev_compiler/doc/definition/strong-dart.pdf
+++ /dev/null
Binary files differ
diff --git a/pkg/dev_compiler/doc/definition/strong-dart.tex b/pkg/dev_compiler/doc/definition/strong-dart.tex
deleted file mode 100644
index 216b476..0000000
--- a/pkg/dev_compiler/doc/definition/strong-dart.tex
+++ /dev/null
@@ -1,347 +0,0 @@
-\documentclass[fleqn, draft]{article}
-\usepackage{proof, amsmath, amssymb, ifthen}
-\input{macros.tex}
-
-% types
-\newcommand{\Arrow}[3][-]{#2 \overset{#1}{\rightarrow} #3}
-\newcommand{\Bool}{\mathbf{bool}}
-\newcommand{\Bottom}{\mathbf{bottom}}
-\newcommand{\Dynamic}{\mathbf{dynamic}}
-\newcommand{\Null}{\mathbf{Null}}
-\newcommand{\Num}{\mathbf{num}}
-\newcommand{\Object}{\mathbf{Object}}
-\newcommand{\TApp}[2]{#1\mathrm{<}#2\mathrm{>}}
-\newcommand{\Type}{\mathbf{Type}}
-\newcommand{\Weak}[1]{\mathbf{\{#1\}}}
-\newcommand{\Sig}{\mathit{Sig}}
-\newcommand{\Boxed}[1]{\langle #1 \rangle}
-
-% expressions
-\newcommand{\eassign}[2]{#1 = #2}
-\newcommand{\eas}[2]{#1\ \mathbf{as}\ #2}
-\newcommand{\ebox}[2]{\langle#1\rangle_{#2}}
-\newcommand{\ecall}[2]{#1(#2)}
-\newcommand{\echeck}[2]{\kwop{check}(#1, #2)}
-\newcommand{\edcall}[2]{\kwop{dcall}(#1, #2)}
-\newcommand{\edload}[2]{\kwop{dload}(#1, #2)}
-\newcommand{\edo}[1]{\kwdo\{\,#1\,\}}
-\newcommand{\eff}{\mathrm{ff}}
-\newcommand{\eis}[2]{#1\ \mathbf{is}\ #2}
-\newcommand{\elabel}[1][l]{\mathit{l}}
-\newcommand{\elambda}[3]{(#1):#2 \Rightarrow #3}
-\newcommand{\eload}[2]{#1.#2}
-\newcommand{\enew}[3]{\mathbf{new}\,\TApp{#1}{#2}(#3)}
-\newcommand{\enull}{\mathbf{null}}
-\newcommand{\eobject}[2]{\kwobject_{#1} \{#2\}}
-\newcommand{\eprimapp}[2]{\ecall{#1}{#2}}
-\newcommand{\eprim}{\kwop{op}}
-\newcommand{\esend}[3]{\ecall{\eload{#1}{#2}}{#3}}
-\newcommand{\eset}[3]{\eassign{#1.#2}{#3}}
-\newcommand{\esuper}{\mathbf{super}}
-\newcommand{\ethis}{\mathbf{this}}
-\newcommand{\ethrow}{\mathbf{throw}}
-\newcommand{\ett}{\mathrm{tt}}
-\newcommand{\eunbox}[1]{{*#1}}
-
-% keywords
-\newcommand{\kwclass}{\kw{class}}
-\newcommand{\kwdo}{\kw{do}}
-\newcommand{\kwelse}{\kw{else}}
-\newcommand{\kwextends}{\kw{extends}}
-\newcommand{\kwfun}{\kw{fun}}
-\newcommand{\kwif}{\kw{if}}
-\newcommand{\kwin}{\kw{in}}
-\newcommand{\kwlet}{\kw{let}}
-\newcommand{\kwobject}{\kw{object}}
-\newcommand{\kwreturn}{\kw{return}}
-\newcommand{\kwthen}{\kw{then}}
-\newcommand{\kwvar}{\kw{var}}
-
-% declarations
-\newcommand{\dclass}[3]{\kwclass\ #1\ \kwextends\ #2\ \{#3\}}
-\newcommand{\dfun}[4]{#2(#3):#1 = #4}
-\newcommand{\dvar}[2]{\kwvar\ #1\ =\ #2}
-
-
-\newcommand{\fieldDecl}[2]{\kwvar\ #1 : #2}
-\newcommand{\methodDecl}[3]{\kwfun\ #1 : \iftrans{#2 \triangleleft} #3}
-
-% statements
-\newcommand{\sifthenelse}[3]{\kwif\ (#1)\ \kwthen\ #2\ \kwelse\ #3}
-\newcommand{\sreturn}[1]{\kwreturn\ #1}
-
-% programs
-\newcommand{\program}[2]{\kwlet\ #1\ \kwin\ #2}
-
-% relational operators
-\newcommand{\sub}{\mathbin{<:}}
-
-% utilities
-\newcommand{\many}[1]{\overrightarrow{#1}}
-\newcommand{\alt}{\ \mathop{|}\ }
-\newcommand{\opt}[1]{[#1]}
-\newcommand{\bind}[3]{#1 \Leftarrow\, #2\ \kw{in}\ #3}
-
-\newcommand{\note}[1]{\textbf{NOTE:} \textit{#1}}
-
-%dynamic semantics
-\newcommand{\TypeError}{\mathbf{Error}}
-
-% inference rules
-\newcommand{\infrulem}[3][]{
-  \begin{array}{c@{\ }c}
-    \begin{array}{cccc}
-      #2 \vspace{-2mm} 
-    \end{array} \\
-    \hrulefill & #1 \\
-    \begin{array}{l}
-      #3
-    \end{array}
-  \end{array}
-  }
-
-\newcommand{\axiomm}[2][]{
-  \begin{array}{cc}
-    \hrulefill & #1 \\
-    \begin{array}{c}
-      #2
-    \end{array}
-  \end{array}
-  }
-
-\newcommand{\infrule}[3][]{
-  \[ 
-  \infrulem[#1]{#2}{#3}
-  \]
-  }
-
-\newcommand{\axiom}[2][]{
-  \[ 
-  \axiomm[#1]{#2}
-  \]
-  }
-
-% judgements and relations
-\newboolean{show_translation}
-\setboolean{show_translation}{false}
-\newcommand{\iftrans}[1]{\ifthenelse{\boolean{show_translation}}{#1}{}}
-\newcommand{\ifnottrans}[1]{\ifthenelse{\boolean{show_translation}}{#1}}
-
-\newcommand{\blockOk}[4]{#1 \vdash #2 \col #3\iftrans{\, \Uparrow\, #4}}
-\newcommand{\declOk}[5][]{#2 \vdash_{#1} #3 \, \Uparrow\, \iftrans{#4\, :\,} #5}
-\newcommand{\extends}[4][:]{#2[#3\ #1\ #4]}
-\newcommand{\fieldLookup}[4]{#1 \vdash #2.#3\, \leadsto_f\, #4}
-\newcommand{\methodLookup}[5]{#1 \vdash #2.#3\, \leadsto_m\, \iftrans{#4 \triangleleft} #5}
-\newcommand{\fieldAbsent}[3]{#1 \vdash #3 \notin #2}
-\newcommand{\methodAbsent}[3]{#1 \vdash #3 \notin #2}
-\newcommand{\hastype}[3]{#1 \vdash #2 \, : \, #3}
-\newcommand{\stmtOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow \iftrans{#4\, :\,} #5}
-\newcommand{\subst}[2]{[#1/#2]}
-\newcommand{\subtypeOfOpt}[5][?]{#2 \vdash\ #3 \sub^{#1} #4\, \Uparrow\, #5}
-\newcommand{\subtypeOf}[4][]{#2 \vdash\ #3 \sub^{#1} #4}
-\newcommand{\yieldsOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow\, \iftrans{#4\, :\,} #5}
-\newcommand{\programOk}[3]{#1 \vdash #2\iftrans{\, \Uparrow\, #3}}
-\newcommand{\ok}[2]{#1 \vdash #2\, \mbox{\textbf{ok}}}
-\newcommand{\overrideOk}[4]{#1 \vdash #2\,\kwextends\, #3 \Leftarrow\, #4}
-
-\newcommand{\down}[1]{\ensuremath{\downharpoonleft\!\!#1\!\!\downharpoonright}}
-\newcommand{\up}[1]{\ensuremath{\upharpoonleft\!\!#1\!\!\upharpoonright}}
-\newcommand{\sigof}[1]{\mathit{sigof}(#1)}
-\newcommand{\typeof}[1]{\mathit{typeof}(#1)}
-\newcommand{\sstext}[2]{\ifthenelse{\boolean{show_translation}}{#2}{#1}}
-
-\newcommand{\evaluatesTo}[5][]{\{#2\alt #3\}  \stepsto_{#1} \{#4 \alt #5\}}
-
-
-\title{Dart strong mode definition}
-
-\begin{document}
-
-\textbf{\large PRELIMINARY DRAFT}
-
-\section*{Syntax}
-
-
-Terms and types.  Note that we allow types to be optional in certain positions
-(currently function arguments and return types, and on variable declarations).
-Implicitly these are either inferred or filled in with dynamic.
-
-There are explicit terms for dynamic calls and loads, and for dynamic type
-checks.
-
-Fields can only be read or set within a method via a reference to this, so no
-dynamic set operation is required (essentially dynamic set becomes a dynamic
-call to a setter).  This just simplifies the presentation a bit.  Methods may be
-externally loaded from the object (either to call them, or to pass them as
-closurized functions).
-
-\[
-\begin{array}{lcl}
-\text{Type identifiers} & ::= &  C, G, T, S, \ldots \\
-%
-\text{Arrow kind ($k$)} & ::= &  +, -\\
-%
-\text{Types $\tau, \sigma$} & ::= &
- T \alt \Dynamic \alt \Object \alt \Null \alt \Type \alt \Num \\ &&
-   \alt \Bool
-   \alt \Arrow[k]{\many{\tau}}{\sigma} \alt \TApp{C}{\many{\tau}} \\
-%
-\text{Ground types $\tau, \sigma$} & ::= &
- \Dynamic \alt \Object \alt \Null \alt \Type \alt \Num \\ &&
-   \alt \Bool
-   \alt \Arrow[+]{\many{\Dynamic}}{\Dynamic} \alt \TApp{C}{\many{\Dynamic}} \\
-%
-\text{Optional type ($[\tau]$)} & ::= &  \_ \alt \tau \\
-%
-\text{Term identifiers} & ::= & a, b, x, y, m, n, \ldots \\
-%
-\text{Primops ($\phi$)} & ::= & \mathrm{+}, \mathrm{-} \ldots \mathrm{||} \ldots \\
-%
-\text{Expressions $e$} & ::= & 
- x \alt i \alt \ett \alt \eff \alt \enull \alt \ethis \\&&
-   \alt \elambda{\many{x:\opt{\tau}}}{\opt{\sigma}}{s} 
-   \alt \enew{C}{\many{\tau}}{} \\&&
-   \alt \eprimapp{\eprim}{\many{e}} \alt \ecall{e}{\many{e}} \\&&
-   \alt \eload{e}{m} \alt \eload{\ethis}{x} \\&&
-   \alt \eassign{x}{e} \alt \eset{\ethis}{x}{e} \\&&
-   \alt \ethrow \alt \eas{e}{\tau} \alt \eis{e}{\tau} \\
-%
-\text{Declaration ($\mathit{vd}$)} & ::= &
-   \dvar{x:\opt{\tau}}{e} \alt \dfun{\tau}{f}{\many{x:\tau}}{s} \\
-%
-\text{Statements ($s$)} & ::= & \mathit{vd} \alt e \alt \sifthenelse{e}{s_1}{s_2} 
-   \alt \sreturn{e} \alt s;s \\
-%
-\text{Class decl ($\mathit{cd}$)} & ::= & \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\many{\mathit{vd}}} \\
-%
-\text{Toplevel decl ($\mathit{td}$)} & ::= & \mathit{vd} \alt \mathit{cd}\\
-%
-\text{Program ($P$)} & ::= & \program{\many{\mathit{td}}}{s}
-\end{array}
-\]
-
-
-Type contexts map type variables to their bounds.
-
-Class signatures describe the methods and fields in an object, along with the
-super class of the class.  There are no static methods or fields.
-
-The class hierararchy records the classes with their signatures.
-
-The term context maps term variables to their types.  I also abuse notation and
-allow for the attachment of an optional type to term contexts as follows:
-$\Gamma_\sigma$ refers to a term context within the body of a method whose class
-type is $\sigma$.
-
-\[
-\begin{array}{lcl}
-\text{Type context ($\Delta$)} & ::= &  \epsilon \alt \Delta, T \sub \tau \\
-\text{Class element ($\mathit{ce}$)} & ::= & 
-  \fieldDecl{x}{\tau} \alt \methodDecl{f}{\tau}{\sigma} \\
-\text{Class signature ($\Sig$)} & ::= &
-  \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\many{\mathit{ce}}} \\
-\text{Class hierarchy ($\Phi$)} & ::= &  \epsilon \alt \Phi, C\ :\ \Sig \\
-\text{Term context ($\Gamma$)} & ::= &  \epsilon \alt \Gamma, x\ :\ \tau
-\end{array}
-\]
-
-
-\section*{Subtyping}
-
-\subsection*{Variant Subtyping}
-
-We include a special kind of covariant function space to model certain dart
-idioms.  An arrow type decorated with a positive variance annotation ($+$)
-treats $\Dynamic$ in its argument list covariantly: or equivalently, it treats
-$\Dynamic$ as bottom.  This variant subtyping relation captures this special
-treatment of dynamic.
-
-\axiom{\subtypeOf[+]{\Phi, \Delta}{\Dynamic}{\tau}}
-
-\infrule{\subtypeOf{\Phi, \Delta}{\sigma}{\tau} \quad \sigma \neq \Dynamic}
-        {\subtypeOf[+]{\Phi, \Delta}{\sigma}{\tau}}
-
-\infrule{\subtypeOf{\Phi, \Delta}{\sigma}{\tau}}
-        {\subtypeOf[-]{\Phi, \Delta}{\sigma}{\tau}}
-
-\subsection*{Invariant Subtyping}
-
-Regular subtyping is defined in a fairly standard way, except that generics are
-uniformly covariant, and that function argument types fall into the variant
-subtyping relation defined above.
-
-\axiom{\subtypeOf{\Phi, \Delta}{\tau}{\Dynamic}}
-
-\axiom{\subtypeOf{\Phi, \Delta}{\tau}{\Object}} 
-
-\axiom{\subtypeOf{\Phi, \Delta}{\Bottom}{\tau}}
-
-\axiom{\subtypeOf{\Phi, \Delta}{\tau}{\tau}} 
-
-\infrule{(S\, :\, \sigma) \in \Delta \quad
-         \subtypeOf{\Phi, \Delta}{\sigma}{\tau}}
-        {\subtypeOf{\Phi, \Delta}{S}{\tau}} 
-
-\infrule{\subtypeOf[k_1]{\Phi, \Delta}{\sigma_i}{\tau_i} \quad i \in 0, \ldots, n \quad\quad
-         \subtypeOf{\Phi, \Delta}{\tau_r}{\sigma_r} \\
-         \quad (k_0 = \mbox{-}) \lor (k_1 = \mbox{+})
-        } 
-        {\subtypeOf{\Phi, \Delta}
-                   {\Arrow[k_0]{\tau_0, \ldots, \tau_n}{\tau_r}}
-                   {\Arrow[k_1]{\sigma_0, \ldots, \sigma_n}{\sigma_r}}} 
-
-\infrule{\subtypeOf{\Phi, \Delta}{\tau_i}{\sigma_i} & i \in 0, \ldots, n}
-        {\subtypeOf{\Phi, \Delta}
-          {\TApp{C}{\tau_0, \ldots, \tau_n}}
-          {\TApp{C}{\sigma_0, \ldots, \sigma_n}}}
-
-\infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{\ldots}) \in \Phi \\
-         \subtypeOf{\Phi, \Delta}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}}{\TApp{G}{\sigma_0, \ldots, \sigma_m}}}
-        {\subtypeOf{\Phi, \Delta}
-          {\TApp{C}{\tau_0, \ldots, \tau_n}}
-          {\TApp{G}{\sigma_0, \ldots, \sigma_m}}}
-
-
-
-\section*{Typing}
-\input{static-semantics}
-
-\pagebreak
-\section*{Elaboration}
-\setboolean{show_translation}{true}
-
-Elaboration is a type driven translation which maps a source Dart term to a
-translated term which corresponds to the original term with additional dynamic
-type checks inserted to reify the static unsoundness as runtime type errors.
-For the translation, we extend the source language slightly as follows.
-\[
-\begin{array}{lcl}
-\text{Expressions $e$} & ::= & \ldots 
-   \alt \edcall{e}{\many{e}} \alt \edload{e}{m} \alt \echeck{e}{\tau}\\
-\end{array}
-\]
-
-The expression language is extended with an explicitly checked dynamic call
-operation, and explicitly checked dynamic method load operation, and a runtime
-type test.  Note that while a user level cast throws an exception on failure,
-the runtime type test term introduced here produces a hard type error which
-cannot be caught programmatically.
-
-We also extend typing contexts slightly by adding an internal type to method signatures.
-\[
-\begin{array}{lcl}
-\text{Class element ($\mathit{ce}$)} & ::= & 
-  \fieldDecl{x}{\tau} \alt \methodDecl{f}{\tau}{\sigma} \\
-\end{array}
-\]
-A method signature of the form $\methodDecl{f}{\tau}{\sigma}$ describes a method
-whose public interface is described by $\sigma$, but which has an internal type
-$\tau$ which is a subtype of $\sigma$, but which is properly covariant in any
-type parameters.  The elaboration introduces runtime type checks to mediate
-between the two types.  This is discussed further in the translation of classes
-below.
-
-\input{static-semantics}
-
-
-\end{document}
diff --git a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
index a293c28..b2647e0 100644
--- a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
+++ b/pkg/dev_compiler/lib/src/kernel/asset_file_system.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.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -43,7 +41,7 @@
   }
 
   void close() {
-    client?.close(force: true);
+    client.close(force: true);
   }
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 5b514be..9b9fd08 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -825,10 +825,6 @@
     }
   }
 
-  // Add platform defined variables
-  // TODO(47243) Remove when all code paths read these from the `Target`.
-  declaredVariables.addAll(sdkLibraryEnvironmentDefines);
-
   return declaredVariables;
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index 6d5c418..215ba19 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -25,7 +25,6 @@
 import '../compiler/js_names.dart';
 import 'asset_file_system.dart';
 import 'command.dart';
-import 'target.dart' show sdkLibraryEnvironmentDefines;
 
 /// The service that handles expression compilation requests from
 /// the debugger.
@@ -231,8 +230,6 @@
       ..omitPlatform = true
       ..environmentDefines = {
         if (environmentDefines != null) ...environmentDefines,
-        // TODO(47243) Remove when all code paths read these from the `Target`.
-        ...sdkLibraryEnvironmentDefines
       }
       ..explicitExperimentalFlags = explicitExperimentalFlags
       ..onDiagnostic = _onDiagnosticHandler(errors, warnings, infos)
diff --git a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
index ce67906..3adfae3 100644
--- a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
+++ b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.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.
 
-// @dart=2.9
-
 import 'dart:async';
 import 'dart:io';
 import 'dart:math';
@@ -30,10 +28,10 @@
   final Duration Function(int) _connectionTimeout;
 
   /// The callback that determines when to cancel a request.
-  final Duration Function(int) _reponseTimeout;
+  final Duration Function(int) _responseTimeout;
 
   /// The callback to call to indicate that a request is being retried.
-  final void Function(Uri, HttpClientResponse, int) _onRetry;
+  final void Function(Uri, HttpClientResponse?, int)? _onRetry;
 
   /// Creates a client wrapping [_inner] that retries HTTP requests.
   RetryTimeoutClient(
@@ -44,13 +42,13 @@
     Duration Function(int retryCount) delay = _defaultDelay,
     Duration Function(int retryCount) connectionTimeout = _defaultTimeout,
     Duration Function(int retryCount) responseTimeout = _defaultTimeout,
-    void Function(Uri, HttpClientResponse, int retryCount) onRetry,
+    void Function(Uri, HttpClientResponse?, int retryCount)? onRetry,
   })  : _retries = retries,
         _when = when,
         _whenError = whenError,
         _delay = delay,
         _connectionTimeout = connectionTimeout,
-        _reponseTimeout = responseTimeout,
+        _responseTimeout = responseTimeout,
         _onRetry = onRetry {
     RangeError.checkNotNegative(_retries, 'retries');
   }
@@ -67,13 +65,14 @@
       Uri url, Future<HttpClientRequest> Function(Uri) method) async {
     var i = 0;
     for (;;) {
-      HttpClientResponse response;
+      HttpClientResponse? response;
       try {
         _inner.connectionTimeout = _connectionTimeout(i);
         var request = await method(url).timeout(
-          _reponseTimeout(i),
-          onTimeout: () =>
-              throw TimeoutException('$url, retry:$i', _reponseTimeout(i)),
+          _responseTimeout(i),
+          onTimeout: (() =>
+              throw TimeoutException('$url, retry:$i', _responseTimeout(i))
+                  as FutureOr<HttpClientRequest> Function()),
         );
         response = await request.close();
       } catch (error, stackTrace) {
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index bb79eb8..90dc78e 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -20,34 +20,6 @@
 import 'constants.dart' show DevCompilerConstantsBackend;
 import 'kernel_helpers.dart';
 
-/// Boolean environment variables that indicate which libraries are available in
-/// dev compiler.
-// TODO(jmesserly): provide an option to compile without dart:html & friends?
-const sdkLibraryEnvironmentDefines = {
-  'dart.isVM': 'false',
-  'dart.library.async': 'true',
-  'dart.library.core': 'true',
-  'dart.library.collection': 'true',
-  'dart.library.convert': 'true',
-  // TODO(jmesserly): this is not really supported in dart4web other than
-  // `debugger()`
-  'dart.library.developer': 'true',
-  'dart.library.io': 'false',
-  'dart.library.isolate': 'false',
-  'dart.library.js': 'true',
-  'dart.library.js_util': 'true',
-  'dart.library.math': 'true',
-  'dart.library.mirrors': 'false',
-  'dart.library.typed_data': 'true',
-  'dart.library.indexed_db': 'true',
-  'dart.library.html': 'true',
-  'dart.library.html_common': 'true',
-  'dart.library.svg': 'true',
-  'dart.library.ui': 'false',
-  'dart.library.web_audio': 'true',
-  'dart.library.web_gl': 'true',
-};
-
 /// A kernel [Target] to configure the Dart Front End for dartdevc.
 class DevCompilerTarget extends Target {
   DevCompilerTarget(this.flags);
@@ -60,10 +32,6 @@
   Map<String, Class>? _nativeClasses;
 
   @override
-  Map<String, String> updateEnvironmentDefines(Map<String, String> map) =>
-      map..addAll(sdkLibraryEnvironmentDefines);
-
-  @override
   bool get enableSuperMixins => true;
 
   @override
diff --git a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
index 77b6904..b0e10c1 100644
--- a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io' show HttpServer;
@@ -96,8 +94,8 @@
 }
 
 void main() async {
-  HttpServer server;
-  AssetFileSystem fileSystem;
+  late HttpServer server;
+  late AssetFileSystem fileSystem;
   group('AssetFileSystem with a server', () {
     setUpAll(() async {
       var hostname = 'localhost';
diff --git a/pkg/dev_compiler/test/worker/worker_test.dart b/pkg/dev_compiler/test/worker/worker_test.dart
index 84111ba..25a4474 100644
--- a/pkg/dev_compiler/test/worker/worker_test.dart
+++ b/pkg/dev_compiler/test/worker/worker_test.dart
@@ -10,22 +10,21 @@
 
 import 'package:bazel_worker/bazel_worker.dart';
 import 'package:bazel_worker/testing.dart';
-import 'package:path/path.dart' show dirname, join, joinAll;
 import 'package:test/test.dart';
 
 Directory tmp = Directory.systemTemp.createTempSync('ddc_worker_test');
-File file(String path) => File(join(tmp.path, joinAll(path.split('/'))));
+File file(String path) => File.fromUri(tmp.uri.resolve(path));
 
 void main() {
   var baseArgs = <String>[];
-  final binDir = dirname(Platform.resolvedExecutable);
-  // Note, the bots use the dart binary in the top-level build directory.
-  // On windows, this is a .bat file.
-  final dartdevc = 'dartdevc${Platform.isWindows ? ".bat" : ""}';
-  final executable = binDir.endsWith('bin')
-      ? join(binDir, dartdevc)
-      : join(binDir, 'dart-sdk', 'bin', dartdevc);
-  final executableArgs = <String>[];
+  final executableArgs = <String>[
+    Platform.script.resolve('../../bin/dartdevc.dart').path,
+    '--sound-null-safety',
+    '--dart-sdk-summary',
+    Uri.parse(Platform.resolvedExecutable)
+        .resolve('ddc_outline_sound.dill')
+        .path
+  ];
   group('DDC: Hello World', () {
     final argsFile = file('hello_world.args');
     final inputDartFile = file('hello_world.dart');
@@ -54,7 +53,7 @@
 
     test('can compile in worker mode', () async {
       var args = executableArgs.toList()..add('--persistent_worker');
-      var process = await Process.start(executable, args);
+      var process = await Process.start(Platform.executable, args);
       var messageGrouper = AsyncMessageGrouper(process.stdout);
 
       var request = WorkRequest();
@@ -97,7 +96,7 @@
 
     test('can compile in basic mode', () {
       var args = executableArgs.toList()..addAll(compilerArgs);
-      var result = Process.runSync(executable, args);
+      var result = Process.runSync(Platform.executable, args);
 
       expect(result.exitCode, EXIT_CODE_OK);
       expect(result.stdout, isEmpty);
@@ -109,7 +108,7 @@
       var args = List<String>.from(executableArgs)
         ..add('--does-not-exist')
         ..addAll(compilerArgs);
-      var result = Process.runSync(executable, args);
+      var result = Process.runSync(Platform.executable, args);
 
       expect(result.exitCode, 64);
       expect(result.stdout,
@@ -123,7 +122,7 @@
         ..add('--does-not-exist')
         ..add('--ignore-unrecognized-flags')
         ..addAll(compilerArgs);
-      var result = Process.runSync(executable, args);
+      var result = Process.runSync(Platform.executable, args);
 
       expect(result.exitCode, EXIT_CODE_OK);
       expect(result.stdout, isEmpty);
@@ -135,7 +134,7 @@
       argsFile.createSync();
       argsFile.writeAsStringSync(compilerArgs.join('\n'));
       var args = executableArgs.toList()..add('@${argsFile.path}');
-      var process = await Process.start(executable, args);
+      var process = await Process.start(Platform.executable, args);
       await stderr.addStream(process.stderr);
       var futureProcessOutput = process.stdout.map(utf8.decode).toList();
 
@@ -149,7 +148,7 @@
         ..add('--modules')
         ..add('legacy')
         ..addAll(compilerArgs);
-      var result = Process.runSync(executable, args);
+      var result = Process.runSync(Platform.executable, args);
 
       expect(result.exitCode, EXIT_CODE_OK);
       expect(result.stdout, isEmpty);
@@ -187,7 +186,7 @@
 
     test('can compile in basic mode', () {
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -203,7 +202,7 @@
       expect(greetingSummary.existsSync(), isTrue);
 
       result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -223,7 +222,7 @@
 
     test('reports error on overlapping summaries', () {
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -239,7 +238,7 @@
       expect(greetingSummary.existsSync(), isTrue);
 
       result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -255,7 +254,7 @@
       expect(greeting2Summary.existsSync(), isTrue);
 
       result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -289,7 +288,7 @@
 
     test('incorrect usage', () {
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -304,7 +303,7 @@
     test('compile errors', () {
       badFileDart.writeAsStringSync('main() => "hello world"');
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -340,7 +339,7 @@
 
     test('works if part and library supplied', () {
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
@@ -359,7 +358,7 @@
 
     test('works if part is not supplied', () {
       var result = Process.runSync(
-          executable,
+          Platform.executable,
           executableArgs +
               baseArgs +
               [
diff --git a/pkg/dev_compiler/tool/ddc b/pkg/dev_compiler/tool/ddc
deleted file mode 100755
index cfe8879..0000000
--- a/pkg/dev_compiler/tool/ddc
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/bin/bash
-#
-# Compiles code with DDC and runs the resulting code in node.js.
-#
-# The first script supplied should be the one with `main()`.
-#
-# Saves the output in the same directory as the sources for convenient
-# inspection, modification or rerunning the code.
-set -e
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-SDK_DIR="$( cd "${PROG_NAME%/*}/../../.."; pwd -P)"
-
-if [[ `uname` == 'Darwin' ]];
-then
-  OUT_DIR="$SDK_DIR"/xcodebuild
-else
-  OUT_DIR="$SDK_DIR"/out
-fi
-
-if [ -z "$DART_CONFIGURATION" ];
-then
-  DIRS=$( ls "$OUT_DIR" )
-  # list of possible configurations in decreasing desirability
-  CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64")
-  DART_CONFIGURATION="None"
-  for CONFIG in ${CONFIGS[*]}
-  do
-    for DIR in $DIRS;
-    do
-      if [ "$CONFIG" = "$DIR" ];
-      then
-        # choose most desirable configuration that is available and break
-        DART_CONFIGURATION="$DIR"
-        break 2
-      fi
-    done
-  done
-  if [ "$DART_CONFIGURATION" = "None" ]
-  then
-    echo "No valid dart configuration found in $OUT_DIR"
-    exit 1
-  fi
-fi
-
-ROOT_OUT_DIR="$OUT_DIR"/"$DART_CONFIGURATION"
-GEN_DIR="$ROOT_OUT_DIR"/gen/utils/dartdevc
-
-KERNEL=false
-if [ "$1" = "-k" ]; then
-  KERNEL=true
-  shift
-fi
-
-BASENAME=$( basename "${1%.*}")
-LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-
-if [ "$KERNEL" = true ]; then
-
-  if [ ! -e $ROOT_OUT_DIR/ddc_sdk.dill ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_kernel_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
-
-  $SDK_DIR/sdk/bin/dartdevc --kernel --modules=node \
-      --dart-sdk-summary=$ROOT_OUT_DIR/ddc_sdk.dill \
-      -o $LIBROOT/$BASENAME.js $*
-else
-
-  if [ ! -e $GEN_DIR/ddc_sdk.sum ]; then
-    echo "DDC SDK must be built first, please run:"
-    echo "    pushd $SDKDIR"
-    echo "    ./tools/build.py -m release dartdevc_sdk"
-    exit 1
-  fi
-
-  NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
-  $SDK_DIR/sdk/bin/dartdevc --modules=node \
-      --library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-      -o $LIBROOT/$BASENAME.js $*
-fi
-
-export NODE_PATH
-pushd $LIBROOT > /dev/null
-# TODO(jmesserly): we could have this output the same content as the devtool
-# script, so you could debug the output without recompiling?
-echo "
-    let source_maps;
-    try {
-      source_maps = require('source-map-support');
-      source_maps.install();
-    } catch(e) {
-    }
-    let sdk = require(\"dart_sdk\");
-    let main = require(\"./$BASENAME\").$BASENAME.main;
-    try {
-      sdk._isolate_helper.startRootIsolate(main, []);
-    } catch(e) {
-      if (!source_maps) {
-        console.log('For Dart source maps: npm install source-map-support');
-      }
-      console.error(e);
-      process.exit(1);
-    }" \
-    > $LIBROOT/$BASENAME.run.js
-node $BASENAME.run.js || exit 1
-popd > /dev/null
diff --git a/pkg/expect/lib/config.dart b/pkg/expect/lib/config.dart
new file mode 100644
index 0000000..5229645
--- /dev/null
+++ b/pkg/expect/lib/config.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Access to the runner configuration this test is running in.
+///
+/// Provides queries against and properties of the current configuration
+/// that a test is being compiled and executed in.
+///
+/// This library is separate from `expect.dart` because it uses
+/// `fromEnvironment` constants that cannot be precompiled,
+/// and we precompile `expect.dart`.
+
+library expect_config;
+
+import 'package:smith/smith.dart';
+
+final Configuration _configuration = Configuration.parse(
+    const String.fromEnvironment("test_runner.configuration"),
+    <String, dynamic>{});
+
+bool get isDart2jsConfiguration {
+  return _configuration.compiler == Compiler.dart2js;
+}
+
+bool get isDdcConfiguration {
+  return _configuration.compiler == Compiler.dartdevk ||
+      _configuration.compiler == Compiler.dartdevc;
+}
+
+bool get isVmAotConfiguration {
+  return _configuration.compiler == Compiler.dartkp;
+}
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 1b1a534..e7413dd17 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -243,9 +243,13 @@
         buffer.write('_');
       } else {
         int first = equivalence[0];
-        buffer..write('#')..write(first);
+        buffer
+          ..write('#')
+          ..write(first);
         if (first == i) {
-          buffer..write('=')..write(objects[i]);
+          buffer
+            ..write('=')
+            ..write(objects[i]);
         }
       }
     }
@@ -259,7 +263,10 @@
     if (first.isNotEmpty && first.length == objects.length) return;
     var buffer = new StringBuffer("Expect.allIdentical([");
     _writeEquivalences(objects, equivalences, buffer);
-    buffer..write("]")..write(msg)..write(")");
+    buffer
+      ..write("]")
+      ..write(msg)
+      ..write(")");
     _fail(buffer.toString());
   }
 
@@ -290,7 +297,10 @@
     if (!hasEquivalence) return;
     var buffer = new StringBuffer("Expect.allDistinct([");
     _writeEquivalences(objects, equivalences, buffer);
-    buffer..write("]")..write(msg)..write(")");
+    buffer
+      ..write("]")
+      ..write(msg)
+      ..write(")");
     _fail(buffer.toString());
   }
 
@@ -387,7 +397,7 @@
     String defaultMessage =
         'Expect.stringEquals(expected: <$expected>", <$actual>$msg) fails';
 
-    if ((expected == null) || (actual == null)) {
+    if ((expected as dynamic) == null || (actual as dynamic) == null) {
       _fail('$defaultMessage');
     }
 
@@ -583,45 +593,52 @@
     }
   }
 
-  static bool _defaultCheck([dynamic e]) => true;
+  static bool _defaultCheck([dynamic _]) => true;
 
   /**
-   * Calls the function [f] and verifies that it throws a `T`.
-   * The optional [check] function can provide additional validation
-   * that the correct object is being thrown.  For example, to check
-   * the content of the thrown boject you could write this:
+   * Verifies that [computation] throws a [T].
    *
-   *     Expect.throws<MyException>(myThrowingFunction,
-   *          (e) => e.myMessage.contains("WARNING"));
+   * Calls the [computation] function and fails if that call doesn't throw,
+   * throws something which is not a [T], or throws a [T] which does not
+   * satisfy the optional [check] function.
    *
-   * The type variable can be omitted and the type checked in [check]
-   * instead. This was traditionally done before Dart had generic methods.
+   * Returns the accepted thrown [T] object, if one is caught.
+   * This value can be checked further, instead of checking it in the [check]
+   * function. For example, to check the content of the thrown object,
+   * you could write this:
+   * ```
+   * var e = Expect.throws<MyException>(myThrowingFunction);
+   * Expect.isTrue(e.myMessage.contains("WARNING"));
+   * ```
+   * The type variable can be omitted, in which case it defaults to [Object],
+   * and the (sub-)type of the object can be checked in [check] instead.
+   * This was traditionally done before Dart had generic methods.
    *
-   * If `f` fails an expectation (i.e., throws an [ExpectException]), that
-   * exception is not caught by [Expect.throws]. The test is still considered
-   * failing.
+   * If `computation` fails another test expectation
+   * (i.e., throws an [ExpectException]),
+   * that exception cannot be caught and accepted by [Expect.throws].
+   * The test is still considered failing.
    */
-  static void throws<T>(void f(),
-      [bool check(T error) = _defaultCheck, String reason = ""]) {
+  static T throws<T extends Object>(void Function() computation,
+      [bool Function(T error)? check, String? reason]) {
     // TODO(vsm): Make check and reason nullable or change call sites.
     // Existing tests pass null to set a reason and/or pass them through
     // via helpers.
     // TODO(rnystrom): Using the strange form below instead of "??=" to avoid
     // warnings of unnecessary null checks when analyzed as NNBD code.
-    if ((check as dynamic) == null) check = _defaultCheck;
-    if ((reason as dynamic) == null) reason = "";
+    reason ??= "";
     String msg = reason.isEmpty ? "" : "($reason)";
-    if (f is! Function()) {
+    if ((computation as dynamic) == null) {
       // Only throws from executing the function body should count as throwing.
       // The failure to even call `f` should throw outside the try/catch.
-      _fail("Expect.throws$msg: Function f not callable with zero arguments");
+      testError("Function must not be null");
     }
     try {
-      f();
+      computation();
     } catch (e, s) {
       // A test failure doesn't count as throwing.
       if (e is ExpectException) rethrow;
-      if (e is T && check(e as dynamic)) return;
+      if (e is T && (check ?? _defaultCheck)(e)) return e;
       // Throws something unexpected.
       String type = "";
       if (T != dynamic && T != Object) {
@@ -633,47 +650,41 @@
     _fail('Expect.throws$msg fails: Did not throw');
   }
 
-  static void throwsArgumentError(void f(), [String reason = "ArgumentError"]) {
-    Expect.throws(f, (error) => error is ArgumentError, reason);
-  }
+  static ArgumentError throwsArgumentError(void f(),
+          [String reason = "ArgumentError"]) =>
+      Expect.throws<ArgumentError>(f, _defaultCheck, reason);
 
-  static void throwsAssertionError(void f(),
-      [String reason = "AssertionError"]) {
-    Expect.throws(f, (error) => error is AssertionError, reason);
-  }
+  static AssertionError throwsAssertionError(void f(),
+          [String reason = "AssertionError"]) =>
+      Expect.throws<AssertionError>(f, _defaultCheck, reason);
 
-  static void throwsFormatException(void f(),
-      [String reason = "FormatException"]) {
-    Expect.throws(f, (error) => error is FormatException, reason);
-  }
+  static FormatException throwsFormatException(void f(),
+          [String reason = "FormatException"]) =>
+      Expect.throws<FormatException>(f, _defaultCheck, reason);
 
-  static void throwsNoSuchMethodError(void f(),
-      [String reason = "NoSuchMethodError"]) {
-    Expect.throws(f, (error) => error is NoSuchMethodError, reason);
-  }
+  static NoSuchMethodError throwsNoSuchMethodError(void f(),
+          [String reason = "NoSuchMethodError"]) =>
+      Expect.throws<NoSuchMethodError>(f, _defaultCheck, reason);
 
-  static void throwsReachabilityError(void f(),
-      [String reason = "ReachabilityError"]) {
-    Expect.throws(
-        f, (error) => error.toString().startsWith('ReachabilityError'), reason);
-  }
+  static Error throwsReachabilityError(void f(),
+          [String reason = "ReachabilityError"]) =>
+      Expect.throws<Error>(f,
+          (error) => error.toString().startsWith('ReachabilityError'), reason);
 
-  static void throwsRangeError(void f(), [String reason = "RangeError"]) {
-    Expect.throws(f, (error) => error is RangeError, reason);
-  }
+  static RangeError throwsRangeError(void f(),
+          [String reason = "RangeError"]) =>
+      Expect.throws<RangeError>(f, _defaultCheck, reason);
 
-  static void throwsStateError(void f(), [String reason = "StateError"]) {
-    Expect.throws(f, (error) => error is StateError, reason);
-  }
+  static StateError throwsStateError(void f(),
+          [String reason = "StateError"]) =>
+      Expect.throws<StateError>(f, _defaultCheck, reason);
 
-  static void throwsTypeError(void f(), [String reason = "TypeError"]) {
-    Expect.throws(f, (error) => error is TypeError, reason);
-  }
+  static TypeError throwsTypeError(void f(), [String reason = "TypeError"]) =>
+      Expect.throws<TypeError>(f, _defaultCheck, reason);
 
-  static void throwsUnsupportedError(void f(),
-      [String reason = "UnsupportedError"]) {
-    Expect.throws(f, (error) => error is UnsupportedError, reason);
-  }
+  static UnsupportedError throwsUnsupportedError(void f(),
+          [String reason = "UnsupportedError"]) =>
+      Expect.throws<UnsupportedError>(f, _defaultCheck, reason);
 
   /// Reports that there is an error in the test itself and not the code under
   /// test.
@@ -748,20 +759,20 @@
     _getTestName = getName;
   }
 
-  // TODO(rnystrom): Type this `String Function()?` once this library doesn't
-  // need to be NNBD-agnostic.
-  static dynamic _getTestName;
+  static String Function() _getTestName = _kEmptyString;
 
   final String message;
   final String name;
 
-  ExpectException(this.message)
-      : name = (_getTestName == null) ? "" : _getTestName();
+  ExpectException(this.message) : name = _getTestName();
 
   String toString() {
     if (name != "") return 'In test "$name" $message';
     return message;
   }
+
+  /// Initial value for _getTestName.
+  static String _kEmptyString() => "";
 }
 
 /// Is true iff type assertions are enabled.
@@ -769,7 +780,7 @@
 final bool typeAssertionsEnabled = (() {
   try {
     dynamic i = 42;
-    String s = i;
+    String s = i; // ignore: unused_local_variable
   } on TypeError {
     return true;
   }
diff --git a/pkg/expect/pubspec.yaml b/pkg/expect/pubspec.yaml
index 70c2817..54c4ad1 100644
--- a/pkg/expect/pubspec.yaml
+++ b/pkg/expect/pubspec.yaml
@@ -13,7 +13,10 @@
 
 dependencies:
   meta: any
+  smith: any
 
 dependency_overrides:
  meta:
   path: ../meta
+ smith:
+  path: ../smith
diff --git a/pkg/expect/test/nnbd_mode_test.dart b/pkg/expect/test/nnbd_mode_test.dart
index 35dd345..1bacdec 100644
--- a/pkg/expect/test/nnbd_mode_test.dart
+++ b/pkg/expect/test/nnbd_mode_test.dart
@@ -6,7 +6,7 @@
 
 final bool strong = () {
   try {
-    int i = null as dynamic;
+    int i = null as dynamic; // ignore: unused_local_variable
     return false;
   } catch (e) {
     return true;
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index cc832b8..c1cae63 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -12,6 +12,7 @@
     - test/extensions/data/**
     - test/id_testing/data/**
     - test/language_versioning/data/**
+    - test/macro_application/data/**
     - test/macros/data/**
     - test/patching/data/**
     - test/predicates/data/**
diff --git a/pkg/front_end/benchmarks/patterns/generate_datatypes.dart b/pkg/front_end/benchmarks/patterns/generate_datatypes.dart
new file mode 100644
index 0000000..5592a2d
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generate_datatypes.dart
@@ -0,0 +1,202 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:_fe_analyzer_shared/src/util/relativize.dart';
+import 'package:dart_style/dart_style.dart' show DartFormatter;
+
+const String dataTypeOutputPrefix = 'datatype';
+
+const List<int> dataTypeHierarchySizes = [
+  1,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  12,
+  16,
+  24,
+  32,
+  48,
+  64,
+  96,
+  128,
+  192,
+  256,
+  // 512, too many nested expressions or statements
+  // 1024,
+];
+
+void main() {
+  Uri dataFolder = Platform.script.resolve('generated/');
+  generateDataTypeTests(dataFolder);
+  for (int size in dataTypeHierarchySizes) {
+    generateDataTypeHierarchy(dataFolder, size);
+  }
+}
+
+void generateDataTypeTests(Uri dataFolder) {
+  Uri fileUri = dataFolder.resolve('${dataTypeOutputPrefix}.dart');
+  StringBuffer sb = new StringBuffer();
+  sb.writeln('''
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+// 
+//   ${relativizeUri(Uri.base, Platform.script, isWindows)}
+
+import '../test_datatypes.dart';''');
+
+  for (int size in dataTypeHierarchySizes) {
+    sb.writeln('''
+import '${dataTypeOutputPrefix}$size.dart';''');
+  }
+
+  sb.writeln('''
+
+List<Test> tests = [''');
+
+  for (int size in dataTypeHierarchySizes) {
+    sb.writeln('''
+  Test<Base$size>(
+      $size, 
+      createData$size, 
+      {dynamicDispatchStrategy: incByDynamicDispatch$size, 
+       ifThenElseStrategy: incByIfThenElseDispatch$size,
+       visitorStrategy: incByVisitorDispatch$size}),
+''');
+  }
+
+  sb.writeln('''
+];
+''');
+
+  String result = new DartFormatter().format(sb.toString());
+  new File.fromUri(fileUri).writeAsStringSync(result);
+}
+
+void generateDataTypeHierarchy(Uri dataFolder, int size) {
+  Uri fileUri = dataFolder.resolve('${dataTypeOutputPrefix}${size}.dart');
+  StringBuffer sb = new StringBuffer();
+  sb.writeln('''
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+// 
+//   ${relativizeUri(Uri.base, Platform.script, isWindows)}
+''');
+  sb.writeln('''
+import '../test_datatypes.dart';
+
+abstract class Base$size {
+  void dynamicDispatch(Counter counter);
+  
+  R accept<R, A>(Visitor$size<R, A> visitor, A arg);
+}
+''');
+  for (int i = 0; i < size; i++) {
+    sb.writeln('''
+class Sub$i extends Base$size {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+  
+  void ifThenElseDispatch$i(Counter counter) {
+    counter.inc();
+  }
+  
+  void visitorDispatch$i(Counter counter) {
+    counter.inc();
+  }
+  
+  @override
+  R accept<R, A>(Visitor$size<R, A> visitor, A arg) {
+    return visitor.visitSub$i(this, arg);
+  }
+}
+''');
+  }
+  sb.writeln('''
+List<Base$size> createData$size() {
+  return [''');
+  for (int i = 0; i < size; i++) {
+    sb.writeln('''
+    Sub$i(),''');
+  }
+  sb.writeln('''
+  ];
+}
+''');
+  sb.writeln('''
+void incByDynamicDispatch$size(Base$size base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+''');
+
+  sb.writeln('''
+void incByIfThenElseDispatch$size(Base$size base, Counter counter) {''');
+  for (int i = 0; i < size; i++) {
+    if (i == 0) {
+      sb.writeln('''
+  if (base is Sub$i) {''');
+    } else {
+      sb.writeln('''
+  } else if (base is Sub$i) {''');
+    }
+    sb.write('''
+    base.ifThenElseDispatch$i(counter);
+''');
+  }
+  sb.writeln('''
+  }
+}
+''');
+
+  sb.writeln('''
+const Visitor$size<void, Counter> visitor = CounterVisitor$size(); 
+
+void incByVisitorDispatch$size(Base$size base, Counter counter) {
+  base.accept(visitor, counter);
+}
+''');
+
+  sb.writeln('''
+abstract class Visitor$size<R, A> {''');
+  for (int i = 0; i < size; i++) {
+    sb.writeln('''
+  R visitSub$i(Sub$i sub, A arg);''');
+  }
+  sb.writeln('''
+}
+''');
+
+  sb.writeln('''
+class CounterVisitor$size implements Visitor$size<void, Counter> {
+  const CounterVisitor$size();
+''');
+
+  for (int i = 0; i < size; i++) {
+    sb.writeln('''
+  @override
+  void visitSub$i(Sub$i sub, Counter counter) {
+    sub.visitorDispatch$i(counter);
+  }
+  ''');
+  }
+  sb.writeln('''
+}
+''');
+
+  String result = new DartFormatter().format(sb.toString());
+  new File.fromUri(fileUri).writeAsStringSync(result);
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype.dart b/pkg/front_end/benchmarks/patterns/generated/datatype.dart
new file mode 100644
index 0000000..cfaa462
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+import 'datatype1.dart';
+import 'datatype2.dart';
+import 'datatype3.dart';
+import 'datatype4.dart';
+import 'datatype5.dart';
+import 'datatype6.dart';
+import 'datatype7.dart';
+import 'datatype8.dart';
+import 'datatype12.dart';
+import 'datatype16.dart';
+import 'datatype24.dart';
+import 'datatype32.dart';
+import 'datatype48.dart';
+import 'datatype64.dart';
+import 'datatype96.dart';
+import 'datatype128.dart';
+import 'datatype192.dart';
+import 'datatype256.dart';
+
+List<Test> tests = [
+  Test<Base1>(1, createData1, {
+    dynamicDispatchStrategy: incByDynamicDispatch1,
+    ifThenElseStrategy: incByIfThenElseDispatch1,
+    visitorStrategy: incByVisitorDispatch1
+  }),
+  Test<Base2>(2, createData2, {
+    dynamicDispatchStrategy: incByDynamicDispatch2,
+    ifThenElseStrategy: incByIfThenElseDispatch2,
+    visitorStrategy: incByVisitorDispatch2
+  }),
+  Test<Base3>(3, createData3, {
+    dynamicDispatchStrategy: incByDynamicDispatch3,
+    ifThenElseStrategy: incByIfThenElseDispatch3,
+    visitorStrategy: incByVisitorDispatch3
+  }),
+  Test<Base4>(4, createData4, {
+    dynamicDispatchStrategy: incByDynamicDispatch4,
+    ifThenElseStrategy: incByIfThenElseDispatch4,
+    visitorStrategy: incByVisitorDispatch4
+  }),
+  Test<Base5>(5, createData5, {
+    dynamicDispatchStrategy: incByDynamicDispatch5,
+    ifThenElseStrategy: incByIfThenElseDispatch5,
+    visitorStrategy: incByVisitorDispatch5
+  }),
+  Test<Base6>(6, createData6, {
+    dynamicDispatchStrategy: incByDynamicDispatch6,
+    ifThenElseStrategy: incByIfThenElseDispatch6,
+    visitorStrategy: incByVisitorDispatch6
+  }),
+  Test<Base7>(7, createData7, {
+    dynamicDispatchStrategy: incByDynamicDispatch7,
+    ifThenElseStrategy: incByIfThenElseDispatch7,
+    visitorStrategy: incByVisitorDispatch7
+  }),
+  Test<Base8>(8, createData8, {
+    dynamicDispatchStrategy: incByDynamicDispatch8,
+    ifThenElseStrategy: incByIfThenElseDispatch8,
+    visitorStrategy: incByVisitorDispatch8
+  }),
+  Test<Base12>(12, createData12, {
+    dynamicDispatchStrategy: incByDynamicDispatch12,
+    ifThenElseStrategy: incByIfThenElseDispatch12,
+    visitorStrategy: incByVisitorDispatch12
+  }),
+  Test<Base16>(16, createData16, {
+    dynamicDispatchStrategy: incByDynamicDispatch16,
+    ifThenElseStrategy: incByIfThenElseDispatch16,
+    visitorStrategy: incByVisitorDispatch16
+  }),
+  Test<Base24>(24, createData24, {
+    dynamicDispatchStrategy: incByDynamicDispatch24,
+    ifThenElseStrategy: incByIfThenElseDispatch24,
+    visitorStrategy: incByVisitorDispatch24
+  }),
+  Test<Base32>(32, createData32, {
+    dynamicDispatchStrategy: incByDynamicDispatch32,
+    ifThenElseStrategy: incByIfThenElseDispatch32,
+    visitorStrategy: incByVisitorDispatch32
+  }),
+  Test<Base48>(48, createData48, {
+    dynamicDispatchStrategy: incByDynamicDispatch48,
+    ifThenElseStrategy: incByIfThenElseDispatch48,
+    visitorStrategy: incByVisitorDispatch48
+  }),
+  Test<Base64>(64, createData64, {
+    dynamicDispatchStrategy: incByDynamicDispatch64,
+    ifThenElseStrategy: incByIfThenElseDispatch64,
+    visitorStrategy: incByVisitorDispatch64
+  }),
+  Test<Base96>(96, createData96, {
+    dynamicDispatchStrategy: incByDynamicDispatch96,
+    ifThenElseStrategy: incByIfThenElseDispatch96,
+    visitorStrategy: incByVisitorDispatch96
+  }),
+  Test<Base128>(128, createData128, {
+    dynamicDispatchStrategy: incByDynamicDispatch128,
+    ifThenElseStrategy: incByIfThenElseDispatch128,
+    visitorStrategy: incByVisitorDispatch128
+  }),
+  Test<Base192>(192, createData192, {
+    dynamicDispatchStrategy: incByDynamicDispatch192,
+    ifThenElseStrategy: incByIfThenElseDispatch192,
+    visitorStrategy: incByVisitorDispatch192
+  }),
+  Test<Base256>(256, createData256, {
+    dynamicDispatchStrategy: incByDynamicDispatch256,
+    ifThenElseStrategy: incByIfThenElseDispatch256,
+    visitorStrategy: incByVisitorDispatch256
+  }),
+];
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype1.dart b/pkg/front_end/benchmarks/patterns/generated/datatype1.dart
new file mode 100644
index 0000000..542cd8f
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype1.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base1 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor1<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base1 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor1<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+List<Base1> createData1() {
+  return [
+    Sub0(),
+  ];
+}
+
+void incByDynamicDispatch1(Base1 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch1(Base1 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  }
+}
+
+const Visitor1<void, Counter> visitor = CounterVisitor1();
+
+void incByVisitorDispatch1(Base1 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor1<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+}
+
+class CounterVisitor1 implements Visitor1<void, Counter> {
+  const CounterVisitor1();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype12.dart b/pkg/front_end/benchmarks/patterns/generated/datatype12.dart
new file mode 100644
index 0000000..ee6fa5a
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype12.dart
@@ -0,0 +1,389 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base12 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor12<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base12 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor12<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+List<Base12> createData12() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+  ];
+}
+
+void incByDynamicDispatch12(Base12 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch12(Base12 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  }
+}
+
+const Visitor12<void, Counter> visitor = CounterVisitor12();
+
+void incByVisitorDispatch12(Base12 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor12<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+}
+
+class CounterVisitor12 implements Visitor12<void, Counter> {
+  const CounterVisitor12();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype128.dart b/pkg/front_end/benchmarks/patterns/generated/datatype128.dart
new file mode 100644
index 0000000..3c9f086
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype128.dart
@@ -0,0 +1,3753 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base128 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor128<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+class Sub48 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub48(this, arg);
+  }
+}
+
+class Sub49 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub49(this, arg);
+  }
+}
+
+class Sub50 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub50(this, arg);
+  }
+}
+
+class Sub51 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub51(this, arg);
+  }
+}
+
+class Sub52 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub52(this, arg);
+  }
+}
+
+class Sub53 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub53(this, arg);
+  }
+}
+
+class Sub54 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub54(this, arg);
+  }
+}
+
+class Sub55 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub55(this, arg);
+  }
+}
+
+class Sub56 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub56(this, arg);
+  }
+}
+
+class Sub57 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub57(this, arg);
+  }
+}
+
+class Sub58 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub58(this, arg);
+  }
+}
+
+class Sub59 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub59(this, arg);
+  }
+}
+
+class Sub60 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub60(this, arg);
+  }
+}
+
+class Sub61 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub61(this, arg);
+  }
+}
+
+class Sub62 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub62(this, arg);
+  }
+}
+
+class Sub63 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub63(this, arg);
+  }
+}
+
+class Sub64 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub64(this, arg);
+  }
+}
+
+class Sub65 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub65(this, arg);
+  }
+}
+
+class Sub66 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub66(this, arg);
+  }
+}
+
+class Sub67 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub67(this, arg);
+  }
+}
+
+class Sub68 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub68(this, arg);
+  }
+}
+
+class Sub69 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub69(this, arg);
+  }
+}
+
+class Sub70 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub70(this, arg);
+  }
+}
+
+class Sub71 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub71(this, arg);
+  }
+}
+
+class Sub72 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub72(this, arg);
+  }
+}
+
+class Sub73 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub73(this, arg);
+  }
+}
+
+class Sub74 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub74(this, arg);
+  }
+}
+
+class Sub75 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub75(this, arg);
+  }
+}
+
+class Sub76 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub76(this, arg);
+  }
+}
+
+class Sub77 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub77(this, arg);
+  }
+}
+
+class Sub78 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub78(this, arg);
+  }
+}
+
+class Sub79 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub79(this, arg);
+  }
+}
+
+class Sub80 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub80(this, arg);
+  }
+}
+
+class Sub81 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub81(this, arg);
+  }
+}
+
+class Sub82 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub82(this, arg);
+  }
+}
+
+class Sub83 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub83(this, arg);
+  }
+}
+
+class Sub84 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub84(this, arg);
+  }
+}
+
+class Sub85 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub85(this, arg);
+  }
+}
+
+class Sub86 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub86(this, arg);
+  }
+}
+
+class Sub87 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub87(this, arg);
+  }
+}
+
+class Sub88 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub88(this, arg);
+  }
+}
+
+class Sub89 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub89(this, arg);
+  }
+}
+
+class Sub90 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub90(this, arg);
+  }
+}
+
+class Sub91 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub91(this, arg);
+  }
+}
+
+class Sub92 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub92(this, arg);
+  }
+}
+
+class Sub93 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub93(this, arg);
+  }
+}
+
+class Sub94 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub94(this, arg);
+  }
+}
+
+class Sub95 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub95(this, arg);
+  }
+}
+
+class Sub96 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub96(this, arg);
+  }
+}
+
+class Sub97 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub97(this, arg);
+  }
+}
+
+class Sub98 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub98(this, arg);
+  }
+}
+
+class Sub99 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub99(this, arg);
+  }
+}
+
+class Sub100 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub100(this, arg);
+  }
+}
+
+class Sub101 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub101(this, arg);
+  }
+}
+
+class Sub102 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub102(this, arg);
+  }
+}
+
+class Sub103 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub103(this, arg);
+  }
+}
+
+class Sub104 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub104(this, arg);
+  }
+}
+
+class Sub105 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub105(this, arg);
+  }
+}
+
+class Sub106 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub106(this, arg);
+  }
+}
+
+class Sub107 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub107(this, arg);
+  }
+}
+
+class Sub108 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub108(this, arg);
+  }
+}
+
+class Sub109 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub109(this, arg);
+  }
+}
+
+class Sub110 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub110(this, arg);
+  }
+}
+
+class Sub111 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub111(this, arg);
+  }
+}
+
+class Sub112 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub112(this, arg);
+  }
+}
+
+class Sub113 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub113(this, arg);
+  }
+}
+
+class Sub114 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub114(this, arg);
+  }
+}
+
+class Sub115 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub115(this, arg);
+  }
+}
+
+class Sub116 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub116(this, arg);
+  }
+}
+
+class Sub117 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub117(this, arg);
+  }
+}
+
+class Sub118 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub118(this, arg);
+  }
+}
+
+class Sub119 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub119(this, arg);
+  }
+}
+
+class Sub120 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub120(this, arg);
+  }
+}
+
+class Sub121 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub121(this, arg);
+  }
+}
+
+class Sub122 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub122(this, arg);
+  }
+}
+
+class Sub123 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub123(this, arg);
+  }
+}
+
+class Sub124 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub124(this, arg);
+  }
+}
+
+class Sub125 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub125(this, arg);
+  }
+}
+
+class Sub126 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub126(this, arg);
+  }
+}
+
+class Sub127 extends Base128 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor128<R, A> visitor, A arg) {
+    return visitor.visitSub127(this, arg);
+  }
+}
+
+List<Base128> createData128() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+    Sub48(),
+    Sub49(),
+    Sub50(),
+    Sub51(),
+    Sub52(),
+    Sub53(),
+    Sub54(),
+    Sub55(),
+    Sub56(),
+    Sub57(),
+    Sub58(),
+    Sub59(),
+    Sub60(),
+    Sub61(),
+    Sub62(),
+    Sub63(),
+    Sub64(),
+    Sub65(),
+    Sub66(),
+    Sub67(),
+    Sub68(),
+    Sub69(),
+    Sub70(),
+    Sub71(),
+    Sub72(),
+    Sub73(),
+    Sub74(),
+    Sub75(),
+    Sub76(),
+    Sub77(),
+    Sub78(),
+    Sub79(),
+    Sub80(),
+    Sub81(),
+    Sub82(),
+    Sub83(),
+    Sub84(),
+    Sub85(),
+    Sub86(),
+    Sub87(),
+    Sub88(),
+    Sub89(),
+    Sub90(),
+    Sub91(),
+    Sub92(),
+    Sub93(),
+    Sub94(),
+    Sub95(),
+    Sub96(),
+    Sub97(),
+    Sub98(),
+    Sub99(),
+    Sub100(),
+    Sub101(),
+    Sub102(),
+    Sub103(),
+    Sub104(),
+    Sub105(),
+    Sub106(),
+    Sub107(),
+    Sub108(),
+    Sub109(),
+    Sub110(),
+    Sub111(),
+    Sub112(),
+    Sub113(),
+    Sub114(),
+    Sub115(),
+    Sub116(),
+    Sub117(),
+    Sub118(),
+    Sub119(),
+    Sub120(),
+    Sub121(),
+    Sub122(),
+    Sub123(),
+    Sub124(),
+    Sub125(),
+    Sub126(),
+    Sub127(),
+  ];
+}
+
+void incByDynamicDispatch128(Base128 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch128(Base128 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  } else if (base is Sub48) {
+    base.ifThenElseDispatch48(counter);
+  } else if (base is Sub49) {
+    base.ifThenElseDispatch49(counter);
+  } else if (base is Sub50) {
+    base.ifThenElseDispatch50(counter);
+  } else if (base is Sub51) {
+    base.ifThenElseDispatch51(counter);
+  } else if (base is Sub52) {
+    base.ifThenElseDispatch52(counter);
+  } else if (base is Sub53) {
+    base.ifThenElseDispatch53(counter);
+  } else if (base is Sub54) {
+    base.ifThenElseDispatch54(counter);
+  } else if (base is Sub55) {
+    base.ifThenElseDispatch55(counter);
+  } else if (base is Sub56) {
+    base.ifThenElseDispatch56(counter);
+  } else if (base is Sub57) {
+    base.ifThenElseDispatch57(counter);
+  } else if (base is Sub58) {
+    base.ifThenElseDispatch58(counter);
+  } else if (base is Sub59) {
+    base.ifThenElseDispatch59(counter);
+  } else if (base is Sub60) {
+    base.ifThenElseDispatch60(counter);
+  } else if (base is Sub61) {
+    base.ifThenElseDispatch61(counter);
+  } else if (base is Sub62) {
+    base.ifThenElseDispatch62(counter);
+  } else if (base is Sub63) {
+    base.ifThenElseDispatch63(counter);
+  } else if (base is Sub64) {
+    base.ifThenElseDispatch64(counter);
+  } else if (base is Sub65) {
+    base.ifThenElseDispatch65(counter);
+  } else if (base is Sub66) {
+    base.ifThenElseDispatch66(counter);
+  } else if (base is Sub67) {
+    base.ifThenElseDispatch67(counter);
+  } else if (base is Sub68) {
+    base.ifThenElseDispatch68(counter);
+  } else if (base is Sub69) {
+    base.ifThenElseDispatch69(counter);
+  } else if (base is Sub70) {
+    base.ifThenElseDispatch70(counter);
+  } else if (base is Sub71) {
+    base.ifThenElseDispatch71(counter);
+  } else if (base is Sub72) {
+    base.ifThenElseDispatch72(counter);
+  } else if (base is Sub73) {
+    base.ifThenElseDispatch73(counter);
+  } else if (base is Sub74) {
+    base.ifThenElseDispatch74(counter);
+  } else if (base is Sub75) {
+    base.ifThenElseDispatch75(counter);
+  } else if (base is Sub76) {
+    base.ifThenElseDispatch76(counter);
+  } else if (base is Sub77) {
+    base.ifThenElseDispatch77(counter);
+  } else if (base is Sub78) {
+    base.ifThenElseDispatch78(counter);
+  } else if (base is Sub79) {
+    base.ifThenElseDispatch79(counter);
+  } else if (base is Sub80) {
+    base.ifThenElseDispatch80(counter);
+  } else if (base is Sub81) {
+    base.ifThenElseDispatch81(counter);
+  } else if (base is Sub82) {
+    base.ifThenElseDispatch82(counter);
+  } else if (base is Sub83) {
+    base.ifThenElseDispatch83(counter);
+  } else if (base is Sub84) {
+    base.ifThenElseDispatch84(counter);
+  } else if (base is Sub85) {
+    base.ifThenElseDispatch85(counter);
+  } else if (base is Sub86) {
+    base.ifThenElseDispatch86(counter);
+  } else if (base is Sub87) {
+    base.ifThenElseDispatch87(counter);
+  } else if (base is Sub88) {
+    base.ifThenElseDispatch88(counter);
+  } else if (base is Sub89) {
+    base.ifThenElseDispatch89(counter);
+  } else if (base is Sub90) {
+    base.ifThenElseDispatch90(counter);
+  } else if (base is Sub91) {
+    base.ifThenElseDispatch91(counter);
+  } else if (base is Sub92) {
+    base.ifThenElseDispatch92(counter);
+  } else if (base is Sub93) {
+    base.ifThenElseDispatch93(counter);
+  } else if (base is Sub94) {
+    base.ifThenElseDispatch94(counter);
+  } else if (base is Sub95) {
+    base.ifThenElseDispatch95(counter);
+  } else if (base is Sub96) {
+    base.ifThenElseDispatch96(counter);
+  } else if (base is Sub97) {
+    base.ifThenElseDispatch97(counter);
+  } else if (base is Sub98) {
+    base.ifThenElseDispatch98(counter);
+  } else if (base is Sub99) {
+    base.ifThenElseDispatch99(counter);
+  } else if (base is Sub100) {
+    base.ifThenElseDispatch100(counter);
+  } else if (base is Sub101) {
+    base.ifThenElseDispatch101(counter);
+  } else if (base is Sub102) {
+    base.ifThenElseDispatch102(counter);
+  } else if (base is Sub103) {
+    base.ifThenElseDispatch103(counter);
+  } else if (base is Sub104) {
+    base.ifThenElseDispatch104(counter);
+  } else if (base is Sub105) {
+    base.ifThenElseDispatch105(counter);
+  } else if (base is Sub106) {
+    base.ifThenElseDispatch106(counter);
+  } else if (base is Sub107) {
+    base.ifThenElseDispatch107(counter);
+  } else if (base is Sub108) {
+    base.ifThenElseDispatch108(counter);
+  } else if (base is Sub109) {
+    base.ifThenElseDispatch109(counter);
+  } else if (base is Sub110) {
+    base.ifThenElseDispatch110(counter);
+  } else if (base is Sub111) {
+    base.ifThenElseDispatch111(counter);
+  } else if (base is Sub112) {
+    base.ifThenElseDispatch112(counter);
+  } else if (base is Sub113) {
+    base.ifThenElseDispatch113(counter);
+  } else if (base is Sub114) {
+    base.ifThenElseDispatch114(counter);
+  } else if (base is Sub115) {
+    base.ifThenElseDispatch115(counter);
+  } else if (base is Sub116) {
+    base.ifThenElseDispatch116(counter);
+  } else if (base is Sub117) {
+    base.ifThenElseDispatch117(counter);
+  } else if (base is Sub118) {
+    base.ifThenElseDispatch118(counter);
+  } else if (base is Sub119) {
+    base.ifThenElseDispatch119(counter);
+  } else if (base is Sub120) {
+    base.ifThenElseDispatch120(counter);
+  } else if (base is Sub121) {
+    base.ifThenElseDispatch121(counter);
+  } else if (base is Sub122) {
+    base.ifThenElseDispatch122(counter);
+  } else if (base is Sub123) {
+    base.ifThenElseDispatch123(counter);
+  } else if (base is Sub124) {
+    base.ifThenElseDispatch124(counter);
+  } else if (base is Sub125) {
+    base.ifThenElseDispatch125(counter);
+  } else if (base is Sub126) {
+    base.ifThenElseDispatch126(counter);
+  } else if (base is Sub127) {
+    base.ifThenElseDispatch127(counter);
+  }
+}
+
+const Visitor128<void, Counter> visitor = CounterVisitor128();
+
+void incByVisitorDispatch128(Base128 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor128<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+  R visitSub48(Sub48 sub, A arg);
+  R visitSub49(Sub49 sub, A arg);
+  R visitSub50(Sub50 sub, A arg);
+  R visitSub51(Sub51 sub, A arg);
+  R visitSub52(Sub52 sub, A arg);
+  R visitSub53(Sub53 sub, A arg);
+  R visitSub54(Sub54 sub, A arg);
+  R visitSub55(Sub55 sub, A arg);
+  R visitSub56(Sub56 sub, A arg);
+  R visitSub57(Sub57 sub, A arg);
+  R visitSub58(Sub58 sub, A arg);
+  R visitSub59(Sub59 sub, A arg);
+  R visitSub60(Sub60 sub, A arg);
+  R visitSub61(Sub61 sub, A arg);
+  R visitSub62(Sub62 sub, A arg);
+  R visitSub63(Sub63 sub, A arg);
+  R visitSub64(Sub64 sub, A arg);
+  R visitSub65(Sub65 sub, A arg);
+  R visitSub66(Sub66 sub, A arg);
+  R visitSub67(Sub67 sub, A arg);
+  R visitSub68(Sub68 sub, A arg);
+  R visitSub69(Sub69 sub, A arg);
+  R visitSub70(Sub70 sub, A arg);
+  R visitSub71(Sub71 sub, A arg);
+  R visitSub72(Sub72 sub, A arg);
+  R visitSub73(Sub73 sub, A arg);
+  R visitSub74(Sub74 sub, A arg);
+  R visitSub75(Sub75 sub, A arg);
+  R visitSub76(Sub76 sub, A arg);
+  R visitSub77(Sub77 sub, A arg);
+  R visitSub78(Sub78 sub, A arg);
+  R visitSub79(Sub79 sub, A arg);
+  R visitSub80(Sub80 sub, A arg);
+  R visitSub81(Sub81 sub, A arg);
+  R visitSub82(Sub82 sub, A arg);
+  R visitSub83(Sub83 sub, A arg);
+  R visitSub84(Sub84 sub, A arg);
+  R visitSub85(Sub85 sub, A arg);
+  R visitSub86(Sub86 sub, A arg);
+  R visitSub87(Sub87 sub, A arg);
+  R visitSub88(Sub88 sub, A arg);
+  R visitSub89(Sub89 sub, A arg);
+  R visitSub90(Sub90 sub, A arg);
+  R visitSub91(Sub91 sub, A arg);
+  R visitSub92(Sub92 sub, A arg);
+  R visitSub93(Sub93 sub, A arg);
+  R visitSub94(Sub94 sub, A arg);
+  R visitSub95(Sub95 sub, A arg);
+  R visitSub96(Sub96 sub, A arg);
+  R visitSub97(Sub97 sub, A arg);
+  R visitSub98(Sub98 sub, A arg);
+  R visitSub99(Sub99 sub, A arg);
+  R visitSub100(Sub100 sub, A arg);
+  R visitSub101(Sub101 sub, A arg);
+  R visitSub102(Sub102 sub, A arg);
+  R visitSub103(Sub103 sub, A arg);
+  R visitSub104(Sub104 sub, A arg);
+  R visitSub105(Sub105 sub, A arg);
+  R visitSub106(Sub106 sub, A arg);
+  R visitSub107(Sub107 sub, A arg);
+  R visitSub108(Sub108 sub, A arg);
+  R visitSub109(Sub109 sub, A arg);
+  R visitSub110(Sub110 sub, A arg);
+  R visitSub111(Sub111 sub, A arg);
+  R visitSub112(Sub112 sub, A arg);
+  R visitSub113(Sub113 sub, A arg);
+  R visitSub114(Sub114 sub, A arg);
+  R visitSub115(Sub115 sub, A arg);
+  R visitSub116(Sub116 sub, A arg);
+  R visitSub117(Sub117 sub, A arg);
+  R visitSub118(Sub118 sub, A arg);
+  R visitSub119(Sub119 sub, A arg);
+  R visitSub120(Sub120 sub, A arg);
+  R visitSub121(Sub121 sub, A arg);
+  R visitSub122(Sub122 sub, A arg);
+  R visitSub123(Sub123 sub, A arg);
+  R visitSub124(Sub124 sub, A arg);
+  R visitSub125(Sub125 sub, A arg);
+  R visitSub126(Sub126 sub, A arg);
+  R visitSub127(Sub127 sub, A arg);
+}
+
+class CounterVisitor128 implements Visitor128<void, Counter> {
+  const CounterVisitor128();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+
+  @override
+  void visitSub48(Sub48 sub, Counter counter) {
+    sub.visitorDispatch48(counter);
+  }
+
+  @override
+  void visitSub49(Sub49 sub, Counter counter) {
+    sub.visitorDispatch49(counter);
+  }
+
+  @override
+  void visitSub50(Sub50 sub, Counter counter) {
+    sub.visitorDispatch50(counter);
+  }
+
+  @override
+  void visitSub51(Sub51 sub, Counter counter) {
+    sub.visitorDispatch51(counter);
+  }
+
+  @override
+  void visitSub52(Sub52 sub, Counter counter) {
+    sub.visitorDispatch52(counter);
+  }
+
+  @override
+  void visitSub53(Sub53 sub, Counter counter) {
+    sub.visitorDispatch53(counter);
+  }
+
+  @override
+  void visitSub54(Sub54 sub, Counter counter) {
+    sub.visitorDispatch54(counter);
+  }
+
+  @override
+  void visitSub55(Sub55 sub, Counter counter) {
+    sub.visitorDispatch55(counter);
+  }
+
+  @override
+  void visitSub56(Sub56 sub, Counter counter) {
+    sub.visitorDispatch56(counter);
+  }
+
+  @override
+  void visitSub57(Sub57 sub, Counter counter) {
+    sub.visitorDispatch57(counter);
+  }
+
+  @override
+  void visitSub58(Sub58 sub, Counter counter) {
+    sub.visitorDispatch58(counter);
+  }
+
+  @override
+  void visitSub59(Sub59 sub, Counter counter) {
+    sub.visitorDispatch59(counter);
+  }
+
+  @override
+  void visitSub60(Sub60 sub, Counter counter) {
+    sub.visitorDispatch60(counter);
+  }
+
+  @override
+  void visitSub61(Sub61 sub, Counter counter) {
+    sub.visitorDispatch61(counter);
+  }
+
+  @override
+  void visitSub62(Sub62 sub, Counter counter) {
+    sub.visitorDispatch62(counter);
+  }
+
+  @override
+  void visitSub63(Sub63 sub, Counter counter) {
+    sub.visitorDispatch63(counter);
+  }
+
+  @override
+  void visitSub64(Sub64 sub, Counter counter) {
+    sub.visitorDispatch64(counter);
+  }
+
+  @override
+  void visitSub65(Sub65 sub, Counter counter) {
+    sub.visitorDispatch65(counter);
+  }
+
+  @override
+  void visitSub66(Sub66 sub, Counter counter) {
+    sub.visitorDispatch66(counter);
+  }
+
+  @override
+  void visitSub67(Sub67 sub, Counter counter) {
+    sub.visitorDispatch67(counter);
+  }
+
+  @override
+  void visitSub68(Sub68 sub, Counter counter) {
+    sub.visitorDispatch68(counter);
+  }
+
+  @override
+  void visitSub69(Sub69 sub, Counter counter) {
+    sub.visitorDispatch69(counter);
+  }
+
+  @override
+  void visitSub70(Sub70 sub, Counter counter) {
+    sub.visitorDispatch70(counter);
+  }
+
+  @override
+  void visitSub71(Sub71 sub, Counter counter) {
+    sub.visitorDispatch71(counter);
+  }
+
+  @override
+  void visitSub72(Sub72 sub, Counter counter) {
+    sub.visitorDispatch72(counter);
+  }
+
+  @override
+  void visitSub73(Sub73 sub, Counter counter) {
+    sub.visitorDispatch73(counter);
+  }
+
+  @override
+  void visitSub74(Sub74 sub, Counter counter) {
+    sub.visitorDispatch74(counter);
+  }
+
+  @override
+  void visitSub75(Sub75 sub, Counter counter) {
+    sub.visitorDispatch75(counter);
+  }
+
+  @override
+  void visitSub76(Sub76 sub, Counter counter) {
+    sub.visitorDispatch76(counter);
+  }
+
+  @override
+  void visitSub77(Sub77 sub, Counter counter) {
+    sub.visitorDispatch77(counter);
+  }
+
+  @override
+  void visitSub78(Sub78 sub, Counter counter) {
+    sub.visitorDispatch78(counter);
+  }
+
+  @override
+  void visitSub79(Sub79 sub, Counter counter) {
+    sub.visitorDispatch79(counter);
+  }
+
+  @override
+  void visitSub80(Sub80 sub, Counter counter) {
+    sub.visitorDispatch80(counter);
+  }
+
+  @override
+  void visitSub81(Sub81 sub, Counter counter) {
+    sub.visitorDispatch81(counter);
+  }
+
+  @override
+  void visitSub82(Sub82 sub, Counter counter) {
+    sub.visitorDispatch82(counter);
+  }
+
+  @override
+  void visitSub83(Sub83 sub, Counter counter) {
+    sub.visitorDispatch83(counter);
+  }
+
+  @override
+  void visitSub84(Sub84 sub, Counter counter) {
+    sub.visitorDispatch84(counter);
+  }
+
+  @override
+  void visitSub85(Sub85 sub, Counter counter) {
+    sub.visitorDispatch85(counter);
+  }
+
+  @override
+  void visitSub86(Sub86 sub, Counter counter) {
+    sub.visitorDispatch86(counter);
+  }
+
+  @override
+  void visitSub87(Sub87 sub, Counter counter) {
+    sub.visitorDispatch87(counter);
+  }
+
+  @override
+  void visitSub88(Sub88 sub, Counter counter) {
+    sub.visitorDispatch88(counter);
+  }
+
+  @override
+  void visitSub89(Sub89 sub, Counter counter) {
+    sub.visitorDispatch89(counter);
+  }
+
+  @override
+  void visitSub90(Sub90 sub, Counter counter) {
+    sub.visitorDispatch90(counter);
+  }
+
+  @override
+  void visitSub91(Sub91 sub, Counter counter) {
+    sub.visitorDispatch91(counter);
+  }
+
+  @override
+  void visitSub92(Sub92 sub, Counter counter) {
+    sub.visitorDispatch92(counter);
+  }
+
+  @override
+  void visitSub93(Sub93 sub, Counter counter) {
+    sub.visitorDispatch93(counter);
+  }
+
+  @override
+  void visitSub94(Sub94 sub, Counter counter) {
+    sub.visitorDispatch94(counter);
+  }
+
+  @override
+  void visitSub95(Sub95 sub, Counter counter) {
+    sub.visitorDispatch95(counter);
+  }
+
+  @override
+  void visitSub96(Sub96 sub, Counter counter) {
+    sub.visitorDispatch96(counter);
+  }
+
+  @override
+  void visitSub97(Sub97 sub, Counter counter) {
+    sub.visitorDispatch97(counter);
+  }
+
+  @override
+  void visitSub98(Sub98 sub, Counter counter) {
+    sub.visitorDispatch98(counter);
+  }
+
+  @override
+  void visitSub99(Sub99 sub, Counter counter) {
+    sub.visitorDispatch99(counter);
+  }
+
+  @override
+  void visitSub100(Sub100 sub, Counter counter) {
+    sub.visitorDispatch100(counter);
+  }
+
+  @override
+  void visitSub101(Sub101 sub, Counter counter) {
+    sub.visitorDispatch101(counter);
+  }
+
+  @override
+  void visitSub102(Sub102 sub, Counter counter) {
+    sub.visitorDispatch102(counter);
+  }
+
+  @override
+  void visitSub103(Sub103 sub, Counter counter) {
+    sub.visitorDispatch103(counter);
+  }
+
+  @override
+  void visitSub104(Sub104 sub, Counter counter) {
+    sub.visitorDispatch104(counter);
+  }
+
+  @override
+  void visitSub105(Sub105 sub, Counter counter) {
+    sub.visitorDispatch105(counter);
+  }
+
+  @override
+  void visitSub106(Sub106 sub, Counter counter) {
+    sub.visitorDispatch106(counter);
+  }
+
+  @override
+  void visitSub107(Sub107 sub, Counter counter) {
+    sub.visitorDispatch107(counter);
+  }
+
+  @override
+  void visitSub108(Sub108 sub, Counter counter) {
+    sub.visitorDispatch108(counter);
+  }
+
+  @override
+  void visitSub109(Sub109 sub, Counter counter) {
+    sub.visitorDispatch109(counter);
+  }
+
+  @override
+  void visitSub110(Sub110 sub, Counter counter) {
+    sub.visitorDispatch110(counter);
+  }
+
+  @override
+  void visitSub111(Sub111 sub, Counter counter) {
+    sub.visitorDispatch111(counter);
+  }
+
+  @override
+  void visitSub112(Sub112 sub, Counter counter) {
+    sub.visitorDispatch112(counter);
+  }
+
+  @override
+  void visitSub113(Sub113 sub, Counter counter) {
+    sub.visitorDispatch113(counter);
+  }
+
+  @override
+  void visitSub114(Sub114 sub, Counter counter) {
+    sub.visitorDispatch114(counter);
+  }
+
+  @override
+  void visitSub115(Sub115 sub, Counter counter) {
+    sub.visitorDispatch115(counter);
+  }
+
+  @override
+  void visitSub116(Sub116 sub, Counter counter) {
+    sub.visitorDispatch116(counter);
+  }
+
+  @override
+  void visitSub117(Sub117 sub, Counter counter) {
+    sub.visitorDispatch117(counter);
+  }
+
+  @override
+  void visitSub118(Sub118 sub, Counter counter) {
+    sub.visitorDispatch118(counter);
+  }
+
+  @override
+  void visitSub119(Sub119 sub, Counter counter) {
+    sub.visitorDispatch119(counter);
+  }
+
+  @override
+  void visitSub120(Sub120 sub, Counter counter) {
+    sub.visitorDispatch120(counter);
+  }
+
+  @override
+  void visitSub121(Sub121 sub, Counter counter) {
+    sub.visitorDispatch121(counter);
+  }
+
+  @override
+  void visitSub122(Sub122 sub, Counter counter) {
+    sub.visitorDispatch122(counter);
+  }
+
+  @override
+  void visitSub123(Sub123 sub, Counter counter) {
+    sub.visitorDispatch123(counter);
+  }
+
+  @override
+  void visitSub124(Sub124 sub, Counter counter) {
+    sub.visitorDispatch124(counter);
+  }
+
+  @override
+  void visitSub125(Sub125 sub, Counter counter) {
+    sub.visitorDispatch125(counter);
+  }
+
+  @override
+  void visitSub126(Sub126 sub, Counter counter) {
+    sub.visitorDispatch126(counter);
+  }
+
+  @override
+  void visitSub127(Sub127 sub, Counter counter) {
+    sub.visitorDispatch127(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype16.dart b/pkg/front_end/benchmarks/patterns/generated/datatype16.dart
new file mode 100644
index 0000000..995b382
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype16.dart
@@ -0,0 +1,505 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base16 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor16<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base16 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor16<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+List<Base16> createData16() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+  ];
+}
+
+void incByDynamicDispatch16(Base16 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch16(Base16 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  }
+}
+
+const Visitor16<void, Counter> visitor = CounterVisitor16();
+
+void incByVisitorDispatch16(Base16 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor16<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+}
+
+class CounterVisitor16 implements Visitor16<void, Counter> {
+  const CounterVisitor16();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype192.dart b/pkg/front_end/benchmarks/patterns/generated/datatype192.dart
new file mode 100644
index 0000000..fcd4e20
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype192.dart
@@ -0,0 +1,5609 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base192 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor192<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+class Sub48 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub48(this, arg);
+  }
+}
+
+class Sub49 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub49(this, arg);
+  }
+}
+
+class Sub50 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub50(this, arg);
+  }
+}
+
+class Sub51 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub51(this, arg);
+  }
+}
+
+class Sub52 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub52(this, arg);
+  }
+}
+
+class Sub53 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub53(this, arg);
+  }
+}
+
+class Sub54 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub54(this, arg);
+  }
+}
+
+class Sub55 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub55(this, arg);
+  }
+}
+
+class Sub56 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub56(this, arg);
+  }
+}
+
+class Sub57 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub57(this, arg);
+  }
+}
+
+class Sub58 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub58(this, arg);
+  }
+}
+
+class Sub59 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub59(this, arg);
+  }
+}
+
+class Sub60 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub60(this, arg);
+  }
+}
+
+class Sub61 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub61(this, arg);
+  }
+}
+
+class Sub62 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub62(this, arg);
+  }
+}
+
+class Sub63 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub63(this, arg);
+  }
+}
+
+class Sub64 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub64(this, arg);
+  }
+}
+
+class Sub65 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub65(this, arg);
+  }
+}
+
+class Sub66 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub66(this, arg);
+  }
+}
+
+class Sub67 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub67(this, arg);
+  }
+}
+
+class Sub68 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub68(this, arg);
+  }
+}
+
+class Sub69 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub69(this, arg);
+  }
+}
+
+class Sub70 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub70(this, arg);
+  }
+}
+
+class Sub71 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub71(this, arg);
+  }
+}
+
+class Sub72 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub72(this, arg);
+  }
+}
+
+class Sub73 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub73(this, arg);
+  }
+}
+
+class Sub74 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub74(this, arg);
+  }
+}
+
+class Sub75 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub75(this, arg);
+  }
+}
+
+class Sub76 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub76(this, arg);
+  }
+}
+
+class Sub77 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub77(this, arg);
+  }
+}
+
+class Sub78 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub78(this, arg);
+  }
+}
+
+class Sub79 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub79(this, arg);
+  }
+}
+
+class Sub80 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub80(this, arg);
+  }
+}
+
+class Sub81 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub81(this, arg);
+  }
+}
+
+class Sub82 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub82(this, arg);
+  }
+}
+
+class Sub83 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub83(this, arg);
+  }
+}
+
+class Sub84 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub84(this, arg);
+  }
+}
+
+class Sub85 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub85(this, arg);
+  }
+}
+
+class Sub86 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub86(this, arg);
+  }
+}
+
+class Sub87 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub87(this, arg);
+  }
+}
+
+class Sub88 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub88(this, arg);
+  }
+}
+
+class Sub89 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub89(this, arg);
+  }
+}
+
+class Sub90 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub90(this, arg);
+  }
+}
+
+class Sub91 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub91(this, arg);
+  }
+}
+
+class Sub92 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub92(this, arg);
+  }
+}
+
+class Sub93 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub93(this, arg);
+  }
+}
+
+class Sub94 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub94(this, arg);
+  }
+}
+
+class Sub95 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub95(this, arg);
+  }
+}
+
+class Sub96 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub96(this, arg);
+  }
+}
+
+class Sub97 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub97(this, arg);
+  }
+}
+
+class Sub98 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub98(this, arg);
+  }
+}
+
+class Sub99 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub99(this, arg);
+  }
+}
+
+class Sub100 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub100(this, arg);
+  }
+}
+
+class Sub101 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub101(this, arg);
+  }
+}
+
+class Sub102 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub102(this, arg);
+  }
+}
+
+class Sub103 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub103(this, arg);
+  }
+}
+
+class Sub104 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub104(this, arg);
+  }
+}
+
+class Sub105 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub105(this, arg);
+  }
+}
+
+class Sub106 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub106(this, arg);
+  }
+}
+
+class Sub107 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub107(this, arg);
+  }
+}
+
+class Sub108 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub108(this, arg);
+  }
+}
+
+class Sub109 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub109(this, arg);
+  }
+}
+
+class Sub110 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub110(this, arg);
+  }
+}
+
+class Sub111 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub111(this, arg);
+  }
+}
+
+class Sub112 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub112(this, arg);
+  }
+}
+
+class Sub113 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub113(this, arg);
+  }
+}
+
+class Sub114 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub114(this, arg);
+  }
+}
+
+class Sub115 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub115(this, arg);
+  }
+}
+
+class Sub116 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub116(this, arg);
+  }
+}
+
+class Sub117 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub117(this, arg);
+  }
+}
+
+class Sub118 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub118(this, arg);
+  }
+}
+
+class Sub119 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub119(this, arg);
+  }
+}
+
+class Sub120 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub120(this, arg);
+  }
+}
+
+class Sub121 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub121(this, arg);
+  }
+}
+
+class Sub122 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub122(this, arg);
+  }
+}
+
+class Sub123 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub123(this, arg);
+  }
+}
+
+class Sub124 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub124(this, arg);
+  }
+}
+
+class Sub125 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub125(this, arg);
+  }
+}
+
+class Sub126 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub126(this, arg);
+  }
+}
+
+class Sub127 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub127(this, arg);
+  }
+}
+
+class Sub128 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch128(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch128(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub128(this, arg);
+  }
+}
+
+class Sub129 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch129(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch129(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub129(this, arg);
+  }
+}
+
+class Sub130 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch130(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch130(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub130(this, arg);
+  }
+}
+
+class Sub131 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch131(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch131(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub131(this, arg);
+  }
+}
+
+class Sub132 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch132(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch132(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub132(this, arg);
+  }
+}
+
+class Sub133 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch133(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch133(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub133(this, arg);
+  }
+}
+
+class Sub134 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch134(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch134(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub134(this, arg);
+  }
+}
+
+class Sub135 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch135(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch135(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub135(this, arg);
+  }
+}
+
+class Sub136 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch136(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch136(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub136(this, arg);
+  }
+}
+
+class Sub137 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch137(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch137(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub137(this, arg);
+  }
+}
+
+class Sub138 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch138(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch138(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub138(this, arg);
+  }
+}
+
+class Sub139 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch139(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch139(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub139(this, arg);
+  }
+}
+
+class Sub140 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch140(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch140(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub140(this, arg);
+  }
+}
+
+class Sub141 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch141(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch141(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub141(this, arg);
+  }
+}
+
+class Sub142 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch142(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch142(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub142(this, arg);
+  }
+}
+
+class Sub143 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch143(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch143(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub143(this, arg);
+  }
+}
+
+class Sub144 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch144(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch144(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub144(this, arg);
+  }
+}
+
+class Sub145 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch145(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch145(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub145(this, arg);
+  }
+}
+
+class Sub146 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch146(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch146(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub146(this, arg);
+  }
+}
+
+class Sub147 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch147(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch147(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub147(this, arg);
+  }
+}
+
+class Sub148 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch148(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch148(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub148(this, arg);
+  }
+}
+
+class Sub149 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch149(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch149(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub149(this, arg);
+  }
+}
+
+class Sub150 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch150(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch150(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub150(this, arg);
+  }
+}
+
+class Sub151 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch151(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch151(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub151(this, arg);
+  }
+}
+
+class Sub152 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch152(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch152(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub152(this, arg);
+  }
+}
+
+class Sub153 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch153(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch153(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub153(this, arg);
+  }
+}
+
+class Sub154 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch154(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch154(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub154(this, arg);
+  }
+}
+
+class Sub155 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch155(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch155(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub155(this, arg);
+  }
+}
+
+class Sub156 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch156(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch156(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub156(this, arg);
+  }
+}
+
+class Sub157 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch157(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch157(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub157(this, arg);
+  }
+}
+
+class Sub158 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch158(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch158(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub158(this, arg);
+  }
+}
+
+class Sub159 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch159(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch159(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub159(this, arg);
+  }
+}
+
+class Sub160 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch160(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch160(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub160(this, arg);
+  }
+}
+
+class Sub161 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch161(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch161(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub161(this, arg);
+  }
+}
+
+class Sub162 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch162(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch162(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub162(this, arg);
+  }
+}
+
+class Sub163 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch163(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch163(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub163(this, arg);
+  }
+}
+
+class Sub164 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch164(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch164(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub164(this, arg);
+  }
+}
+
+class Sub165 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch165(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch165(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub165(this, arg);
+  }
+}
+
+class Sub166 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch166(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch166(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub166(this, arg);
+  }
+}
+
+class Sub167 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch167(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch167(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub167(this, arg);
+  }
+}
+
+class Sub168 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch168(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch168(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub168(this, arg);
+  }
+}
+
+class Sub169 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch169(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch169(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub169(this, arg);
+  }
+}
+
+class Sub170 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch170(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch170(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub170(this, arg);
+  }
+}
+
+class Sub171 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch171(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch171(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub171(this, arg);
+  }
+}
+
+class Sub172 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch172(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch172(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub172(this, arg);
+  }
+}
+
+class Sub173 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch173(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch173(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub173(this, arg);
+  }
+}
+
+class Sub174 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch174(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch174(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub174(this, arg);
+  }
+}
+
+class Sub175 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch175(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch175(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub175(this, arg);
+  }
+}
+
+class Sub176 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch176(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch176(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub176(this, arg);
+  }
+}
+
+class Sub177 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch177(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch177(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub177(this, arg);
+  }
+}
+
+class Sub178 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch178(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch178(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub178(this, arg);
+  }
+}
+
+class Sub179 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch179(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch179(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub179(this, arg);
+  }
+}
+
+class Sub180 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch180(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch180(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub180(this, arg);
+  }
+}
+
+class Sub181 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch181(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch181(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub181(this, arg);
+  }
+}
+
+class Sub182 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch182(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch182(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub182(this, arg);
+  }
+}
+
+class Sub183 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch183(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch183(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub183(this, arg);
+  }
+}
+
+class Sub184 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch184(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch184(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub184(this, arg);
+  }
+}
+
+class Sub185 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch185(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch185(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub185(this, arg);
+  }
+}
+
+class Sub186 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch186(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch186(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub186(this, arg);
+  }
+}
+
+class Sub187 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch187(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch187(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub187(this, arg);
+  }
+}
+
+class Sub188 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch188(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch188(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub188(this, arg);
+  }
+}
+
+class Sub189 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch189(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch189(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub189(this, arg);
+  }
+}
+
+class Sub190 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch190(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch190(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub190(this, arg);
+  }
+}
+
+class Sub191 extends Base192 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch191(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch191(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor192<R, A> visitor, A arg) {
+    return visitor.visitSub191(this, arg);
+  }
+}
+
+List<Base192> createData192() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+    Sub48(),
+    Sub49(),
+    Sub50(),
+    Sub51(),
+    Sub52(),
+    Sub53(),
+    Sub54(),
+    Sub55(),
+    Sub56(),
+    Sub57(),
+    Sub58(),
+    Sub59(),
+    Sub60(),
+    Sub61(),
+    Sub62(),
+    Sub63(),
+    Sub64(),
+    Sub65(),
+    Sub66(),
+    Sub67(),
+    Sub68(),
+    Sub69(),
+    Sub70(),
+    Sub71(),
+    Sub72(),
+    Sub73(),
+    Sub74(),
+    Sub75(),
+    Sub76(),
+    Sub77(),
+    Sub78(),
+    Sub79(),
+    Sub80(),
+    Sub81(),
+    Sub82(),
+    Sub83(),
+    Sub84(),
+    Sub85(),
+    Sub86(),
+    Sub87(),
+    Sub88(),
+    Sub89(),
+    Sub90(),
+    Sub91(),
+    Sub92(),
+    Sub93(),
+    Sub94(),
+    Sub95(),
+    Sub96(),
+    Sub97(),
+    Sub98(),
+    Sub99(),
+    Sub100(),
+    Sub101(),
+    Sub102(),
+    Sub103(),
+    Sub104(),
+    Sub105(),
+    Sub106(),
+    Sub107(),
+    Sub108(),
+    Sub109(),
+    Sub110(),
+    Sub111(),
+    Sub112(),
+    Sub113(),
+    Sub114(),
+    Sub115(),
+    Sub116(),
+    Sub117(),
+    Sub118(),
+    Sub119(),
+    Sub120(),
+    Sub121(),
+    Sub122(),
+    Sub123(),
+    Sub124(),
+    Sub125(),
+    Sub126(),
+    Sub127(),
+    Sub128(),
+    Sub129(),
+    Sub130(),
+    Sub131(),
+    Sub132(),
+    Sub133(),
+    Sub134(),
+    Sub135(),
+    Sub136(),
+    Sub137(),
+    Sub138(),
+    Sub139(),
+    Sub140(),
+    Sub141(),
+    Sub142(),
+    Sub143(),
+    Sub144(),
+    Sub145(),
+    Sub146(),
+    Sub147(),
+    Sub148(),
+    Sub149(),
+    Sub150(),
+    Sub151(),
+    Sub152(),
+    Sub153(),
+    Sub154(),
+    Sub155(),
+    Sub156(),
+    Sub157(),
+    Sub158(),
+    Sub159(),
+    Sub160(),
+    Sub161(),
+    Sub162(),
+    Sub163(),
+    Sub164(),
+    Sub165(),
+    Sub166(),
+    Sub167(),
+    Sub168(),
+    Sub169(),
+    Sub170(),
+    Sub171(),
+    Sub172(),
+    Sub173(),
+    Sub174(),
+    Sub175(),
+    Sub176(),
+    Sub177(),
+    Sub178(),
+    Sub179(),
+    Sub180(),
+    Sub181(),
+    Sub182(),
+    Sub183(),
+    Sub184(),
+    Sub185(),
+    Sub186(),
+    Sub187(),
+    Sub188(),
+    Sub189(),
+    Sub190(),
+    Sub191(),
+  ];
+}
+
+void incByDynamicDispatch192(Base192 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch192(Base192 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  } else if (base is Sub48) {
+    base.ifThenElseDispatch48(counter);
+  } else if (base is Sub49) {
+    base.ifThenElseDispatch49(counter);
+  } else if (base is Sub50) {
+    base.ifThenElseDispatch50(counter);
+  } else if (base is Sub51) {
+    base.ifThenElseDispatch51(counter);
+  } else if (base is Sub52) {
+    base.ifThenElseDispatch52(counter);
+  } else if (base is Sub53) {
+    base.ifThenElseDispatch53(counter);
+  } else if (base is Sub54) {
+    base.ifThenElseDispatch54(counter);
+  } else if (base is Sub55) {
+    base.ifThenElseDispatch55(counter);
+  } else if (base is Sub56) {
+    base.ifThenElseDispatch56(counter);
+  } else if (base is Sub57) {
+    base.ifThenElseDispatch57(counter);
+  } else if (base is Sub58) {
+    base.ifThenElseDispatch58(counter);
+  } else if (base is Sub59) {
+    base.ifThenElseDispatch59(counter);
+  } else if (base is Sub60) {
+    base.ifThenElseDispatch60(counter);
+  } else if (base is Sub61) {
+    base.ifThenElseDispatch61(counter);
+  } else if (base is Sub62) {
+    base.ifThenElseDispatch62(counter);
+  } else if (base is Sub63) {
+    base.ifThenElseDispatch63(counter);
+  } else if (base is Sub64) {
+    base.ifThenElseDispatch64(counter);
+  } else if (base is Sub65) {
+    base.ifThenElseDispatch65(counter);
+  } else if (base is Sub66) {
+    base.ifThenElseDispatch66(counter);
+  } else if (base is Sub67) {
+    base.ifThenElseDispatch67(counter);
+  } else if (base is Sub68) {
+    base.ifThenElseDispatch68(counter);
+  } else if (base is Sub69) {
+    base.ifThenElseDispatch69(counter);
+  } else if (base is Sub70) {
+    base.ifThenElseDispatch70(counter);
+  } else if (base is Sub71) {
+    base.ifThenElseDispatch71(counter);
+  } else if (base is Sub72) {
+    base.ifThenElseDispatch72(counter);
+  } else if (base is Sub73) {
+    base.ifThenElseDispatch73(counter);
+  } else if (base is Sub74) {
+    base.ifThenElseDispatch74(counter);
+  } else if (base is Sub75) {
+    base.ifThenElseDispatch75(counter);
+  } else if (base is Sub76) {
+    base.ifThenElseDispatch76(counter);
+  } else if (base is Sub77) {
+    base.ifThenElseDispatch77(counter);
+  } else if (base is Sub78) {
+    base.ifThenElseDispatch78(counter);
+  } else if (base is Sub79) {
+    base.ifThenElseDispatch79(counter);
+  } else if (base is Sub80) {
+    base.ifThenElseDispatch80(counter);
+  } else if (base is Sub81) {
+    base.ifThenElseDispatch81(counter);
+  } else if (base is Sub82) {
+    base.ifThenElseDispatch82(counter);
+  } else if (base is Sub83) {
+    base.ifThenElseDispatch83(counter);
+  } else if (base is Sub84) {
+    base.ifThenElseDispatch84(counter);
+  } else if (base is Sub85) {
+    base.ifThenElseDispatch85(counter);
+  } else if (base is Sub86) {
+    base.ifThenElseDispatch86(counter);
+  } else if (base is Sub87) {
+    base.ifThenElseDispatch87(counter);
+  } else if (base is Sub88) {
+    base.ifThenElseDispatch88(counter);
+  } else if (base is Sub89) {
+    base.ifThenElseDispatch89(counter);
+  } else if (base is Sub90) {
+    base.ifThenElseDispatch90(counter);
+  } else if (base is Sub91) {
+    base.ifThenElseDispatch91(counter);
+  } else if (base is Sub92) {
+    base.ifThenElseDispatch92(counter);
+  } else if (base is Sub93) {
+    base.ifThenElseDispatch93(counter);
+  } else if (base is Sub94) {
+    base.ifThenElseDispatch94(counter);
+  } else if (base is Sub95) {
+    base.ifThenElseDispatch95(counter);
+  } else if (base is Sub96) {
+    base.ifThenElseDispatch96(counter);
+  } else if (base is Sub97) {
+    base.ifThenElseDispatch97(counter);
+  } else if (base is Sub98) {
+    base.ifThenElseDispatch98(counter);
+  } else if (base is Sub99) {
+    base.ifThenElseDispatch99(counter);
+  } else if (base is Sub100) {
+    base.ifThenElseDispatch100(counter);
+  } else if (base is Sub101) {
+    base.ifThenElseDispatch101(counter);
+  } else if (base is Sub102) {
+    base.ifThenElseDispatch102(counter);
+  } else if (base is Sub103) {
+    base.ifThenElseDispatch103(counter);
+  } else if (base is Sub104) {
+    base.ifThenElseDispatch104(counter);
+  } else if (base is Sub105) {
+    base.ifThenElseDispatch105(counter);
+  } else if (base is Sub106) {
+    base.ifThenElseDispatch106(counter);
+  } else if (base is Sub107) {
+    base.ifThenElseDispatch107(counter);
+  } else if (base is Sub108) {
+    base.ifThenElseDispatch108(counter);
+  } else if (base is Sub109) {
+    base.ifThenElseDispatch109(counter);
+  } else if (base is Sub110) {
+    base.ifThenElseDispatch110(counter);
+  } else if (base is Sub111) {
+    base.ifThenElseDispatch111(counter);
+  } else if (base is Sub112) {
+    base.ifThenElseDispatch112(counter);
+  } else if (base is Sub113) {
+    base.ifThenElseDispatch113(counter);
+  } else if (base is Sub114) {
+    base.ifThenElseDispatch114(counter);
+  } else if (base is Sub115) {
+    base.ifThenElseDispatch115(counter);
+  } else if (base is Sub116) {
+    base.ifThenElseDispatch116(counter);
+  } else if (base is Sub117) {
+    base.ifThenElseDispatch117(counter);
+  } else if (base is Sub118) {
+    base.ifThenElseDispatch118(counter);
+  } else if (base is Sub119) {
+    base.ifThenElseDispatch119(counter);
+  } else if (base is Sub120) {
+    base.ifThenElseDispatch120(counter);
+  } else if (base is Sub121) {
+    base.ifThenElseDispatch121(counter);
+  } else if (base is Sub122) {
+    base.ifThenElseDispatch122(counter);
+  } else if (base is Sub123) {
+    base.ifThenElseDispatch123(counter);
+  } else if (base is Sub124) {
+    base.ifThenElseDispatch124(counter);
+  } else if (base is Sub125) {
+    base.ifThenElseDispatch125(counter);
+  } else if (base is Sub126) {
+    base.ifThenElseDispatch126(counter);
+  } else if (base is Sub127) {
+    base.ifThenElseDispatch127(counter);
+  } else if (base is Sub128) {
+    base.ifThenElseDispatch128(counter);
+  } else if (base is Sub129) {
+    base.ifThenElseDispatch129(counter);
+  } else if (base is Sub130) {
+    base.ifThenElseDispatch130(counter);
+  } else if (base is Sub131) {
+    base.ifThenElseDispatch131(counter);
+  } else if (base is Sub132) {
+    base.ifThenElseDispatch132(counter);
+  } else if (base is Sub133) {
+    base.ifThenElseDispatch133(counter);
+  } else if (base is Sub134) {
+    base.ifThenElseDispatch134(counter);
+  } else if (base is Sub135) {
+    base.ifThenElseDispatch135(counter);
+  } else if (base is Sub136) {
+    base.ifThenElseDispatch136(counter);
+  } else if (base is Sub137) {
+    base.ifThenElseDispatch137(counter);
+  } else if (base is Sub138) {
+    base.ifThenElseDispatch138(counter);
+  } else if (base is Sub139) {
+    base.ifThenElseDispatch139(counter);
+  } else if (base is Sub140) {
+    base.ifThenElseDispatch140(counter);
+  } else if (base is Sub141) {
+    base.ifThenElseDispatch141(counter);
+  } else if (base is Sub142) {
+    base.ifThenElseDispatch142(counter);
+  } else if (base is Sub143) {
+    base.ifThenElseDispatch143(counter);
+  } else if (base is Sub144) {
+    base.ifThenElseDispatch144(counter);
+  } else if (base is Sub145) {
+    base.ifThenElseDispatch145(counter);
+  } else if (base is Sub146) {
+    base.ifThenElseDispatch146(counter);
+  } else if (base is Sub147) {
+    base.ifThenElseDispatch147(counter);
+  } else if (base is Sub148) {
+    base.ifThenElseDispatch148(counter);
+  } else if (base is Sub149) {
+    base.ifThenElseDispatch149(counter);
+  } else if (base is Sub150) {
+    base.ifThenElseDispatch150(counter);
+  } else if (base is Sub151) {
+    base.ifThenElseDispatch151(counter);
+  } else if (base is Sub152) {
+    base.ifThenElseDispatch152(counter);
+  } else if (base is Sub153) {
+    base.ifThenElseDispatch153(counter);
+  } else if (base is Sub154) {
+    base.ifThenElseDispatch154(counter);
+  } else if (base is Sub155) {
+    base.ifThenElseDispatch155(counter);
+  } else if (base is Sub156) {
+    base.ifThenElseDispatch156(counter);
+  } else if (base is Sub157) {
+    base.ifThenElseDispatch157(counter);
+  } else if (base is Sub158) {
+    base.ifThenElseDispatch158(counter);
+  } else if (base is Sub159) {
+    base.ifThenElseDispatch159(counter);
+  } else if (base is Sub160) {
+    base.ifThenElseDispatch160(counter);
+  } else if (base is Sub161) {
+    base.ifThenElseDispatch161(counter);
+  } else if (base is Sub162) {
+    base.ifThenElseDispatch162(counter);
+  } else if (base is Sub163) {
+    base.ifThenElseDispatch163(counter);
+  } else if (base is Sub164) {
+    base.ifThenElseDispatch164(counter);
+  } else if (base is Sub165) {
+    base.ifThenElseDispatch165(counter);
+  } else if (base is Sub166) {
+    base.ifThenElseDispatch166(counter);
+  } else if (base is Sub167) {
+    base.ifThenElseDispatch167(counter);
+  } else if (base is Sub168) {
+    base.ifThenElseDispatch168(counter);
+  } else if (base is Sub169) {
+    base.ifThenElseDispatch169(counter);
+  } else if (base is Sub170) {
+    base.ifThenElseDispatch170(counter);
+  } else if (base is Sub171) {
+    base.ifThenElseDispatch171(counter);
+  } else if (base is Sub172) {
+    base.ifThenElseDispatch172(counter);
+  } else if (base is Sub173) {
+    base.ifThenElseDispatch173(counter);
+  } else if (base is Sub174) {
+    base.ifThenElseDispatch174(counter);
+  } else if (base is Sub175) {
+    base.ifThenElseDispatch175(counter);
+  } else if (base is Sub176) {
+    base.ifThenElseDispatch176(counter);
+  } else if (base is Sub177) {
+    base.ifThenElseDispatch177(counter);
+  } else if (base is Sub178) {
+    base.ifThenElseDispatch178(counter);
+  } else if (base is Sub179) {
+    base.ifThenElseDispatch179(counter);
+  } else if (base is Sub180) {
+    base.ifThenElseDispatch180(counter);
+  } else if (base is Sub181) {
+    base.ifThenElseDispatch181(counter);
+  } else if (base is Sub182) {
+    base.ifThenElseDispatch182(counter);
+  } else if (base is Sub183) {
+    base.ifThenElseDispatch183(counter);
+  } else if (base is Sub184) {
+    base.ifThenElseDispatch184(counter);
+  } else if (base is Sub185) {
+    base.ifThenElseDispatch185(counter);
+  } else if (base is Sub186) {
+    base.ifThenElseDispatch186(counter);
+  } else if (base is Sub187) {
+    base.ifThenElseDispatch187(counter);
+  } else if (base is Sub188) {
+    base.ifThenElseDispatch188(counter);
+  } else if (base is Sub189) {
+    base.ifThenElseDispatch189(counter);
+  } else if (base is Sub190) {
+    base.ifThenElseDispatch190(counter);
+  } else if (base is Sub191) {
+    base.ifThenElseDispatch191(counter);
+  }
+}
+
+const Visitor192<void, Counter> visitor = CounterVisitor192();
+
+void incByVisitorDispatch192(Base192 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor192<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+  R visitSub48(Sub48 sub, A arg);
+  R visitSub49(Sub49 sub, A arg);
+  R visitSub50(Sub50 sub, A arg);
+  R visitSub51(Sub51 sub, A arg);
+  R visitSub52(Sub52 sub, A arg);
+  R visitSub53(Sub53 sub, A arg);
+  R visitSub54(Sub54 sub, A arg);
+  R visitSub55(Sub55 sub, A arg);
+  R visitSub56(Sub56 sub, A arg);
+  R visitSub57(Sub57 sub, A arg);
+  R visitSub58(Sub58 sub, A arg);
+  R visitSub59(Sub59 sub, A arg);
+  R visitSub60(Sub60 sub, A arg);
+  R visitSub61(Sub61 sub, A arg);
+  R visitSub62(Sub62 sub, A arg);
+  R visitSub63(Sub63 sub, A arg);
+  R visitSub64(Sub64 sub, A arg);
+  R visitSub65(Sub65 sub, A arg);
+  R visitSub66(Sub66 sub, A arg);
+  R visitSub67(Sub67 sub, A arg);
+  R visitSub68(Sub68 sub, A arg);
+  R visitSub69(Sub69 sub, A arg);
+  R visitSub70(Sub70 sub, A arg);
+  R visitSub71(Sub71 sub, A arg);
+  R visitSub72(Sub72 sub, A arg);
+  R visitSub73(Sub73 sub, A arg);
+  R visitSub74(Sub74 sub, A arg);
+  R visitSub75(Sub75 sub, A arg);
+  R visitSub76(Sub76 sub, A arg);
+  R visitSub77(Sub77 sub, A arg);
+  R visitSub78(Sub78 sub, A arg);
+  R visitSub79(Sub79 sub, A arg);
+  R visitSub80(Sub80 sub, A arg);
+  R visitSub81(Sub81 sub, A arg);
+  R visitSub82(Sub82 sub, A arg);
+  R visitSub83(Sub83 sub, A arg);
+  R visitSub84(Sub84 sub, A arg);
+  R visitSub85(Sub85 sub, A arg);
+  R visitSub86(Sub86 sub, A arg);
+  R visitSub87(Sub87 sub, A arg);
+  R visitSub88(Sub88 sub, A arg);
+  R visitSub89(Sub89 sub, A arg);
+  R visitSub90(Sub90 sub, A arg);
+  R visitSub91(Sub91 sub, A arg);
+  R visitSub92(Sub92 sub, A arg);
+  R visitSub93(Sub93 sub, A arg);
+  R visitSub94(Sub94 sub, A arg);
+  R visitSub95(Sub95 sub, A arg);
+  R visitSub96(Sub96 sub, A arg);
+  R visitSub97(Sub97 sub, A arg);
+  R visitSub98(Sub98 sub, A arg);
+  R visitSub99(Sub99 sub, A arg);
+  R visitSub100(Sub100 sub, A arg);
+  R visitSub101(Sub101 sub, A arg);
+  R visitSub102(Sub102 sub, A arg);
+  R visitSub103(Sub103 sub, A arg);
+  R visitSub104(Sub104 sub, A arg);
+  R visitSub105(Sub105 sub, A arg);
+  R visitSub106(Sub106 sub, A arg);
+  R visitSub107(Sub107 sub, A arg);
+  R visitSub108(Sub108 sub, A arg);
+  R visitSub109(Sub109 sub, A arg);
+  R visitSub110(Sub110 sub, A arg);
+  R visitSub111(Sub111 sub, A arg);
+  R visitSub112(Sub112 sub, A arg);
+  R visitSub113(Sub113 sub, A arg);
+  R visitSub114(Sub114 sub, A arg);
+  R visitSub115(Sub115 sub, A arg);
+  R visitSub116(Sub116 sub, A arg);
+  R visitSub117(Sub117 sub, A arg);
+  R visitSub118(Sub118 sub, A arg);
+  R visitSub119(Sub119 sub, A arg);
+  R visitSub120(Sub120 sub, A arg);
+  R visitSub121(Sub121 sub, A arg);
+  R visitSub122(Sub122 sub, A arg);
+  R visitSub123(Sub123 sub, A arg);
+  R visitSub124(Sub124 sub, A arg);
+  R visitSub125(Sub125 sub, A arg);
+  R visitSub126(Sub126 sub, A arg);
+  R visitSub127(Sub127 sub, A arg);
+  R visitSub128(Sub128 sub, A arg);
+  R visitSub129(Sub129 sub, A arg);
+  R visitSub130(Sub130 sub, A arg);
+  R visitSub131(Sub131 sub, A arg);
+  R visitSub132(Sub132 sub, A arg);
+  R visitSub133(Sub133 sub, A arg);
+  R visitSub134(Sub134 sub, A arg);
+  R visitSub135(Sub135 sub, A arg);
+  R visitSub136(Sub136 sub, A arg);
+  R visitSub137(Sub137 sub, A arg);
+  R visitSub138(Sub138 sub, A arg);
+  R visitSub139(Sub139 sub, A arg);
+  R visitSub140(Sub140 sub, A arg);
+  R visitSub141(Sub141 sub, A arg);
+  R visitSub142(Sub142 sub, A arg);
+  R visitSub143(Sub143 sub, A arg);
+  R visitSub144(Sub144 sub, A arg);
+  R visitSub145(Sub145 sub, A arg);
+  R visitSub146(Sub146 sub, A arg);
+  R visitSub147(Sub147 sub, A arg);
+  R visitSub148(Sub148 sub, A arg);
+  R visitSub149(Sub149 sub, A arg);
+  R visitSub150(Sub150 sub, A arg);
+  R visitSub151(Sub151 sub, A arg);
+  R visitSub152(Sub152 sub, A arg);
+  R visitSub153(Sub153 sub, A arg);
+  R visitSub154(Sub154 sub, A arg);
+  R visitSub155(Sub155 sub, A arg);
+  R visitSub156(Sub156 sub, A arg);
+  R visitSub157(Sub157 sub, A arg);
+  R visitSub158(Sub158 sub, A arg);
+  R visitSub159(Sub159 sub, A arg);
+  R visitSub160(Sub160 sub, A arg);
+  R visitSub161(Sub161 sub, A arg);
+  R visitSub162(Sub162 sub, A arg);
+  R visitSub163(Sub163 sub, A arg);
+  R visitSub164(Sub164 sub, A arg);
+  R visitSub165(Sub165 sub, A arg);
+  R visitSub166(Sub166 sub, A arg);
+  R visitSub167(Sub167 sub, A arg);
+  R visitSub168(Sub168 sub, A arg);
+  R visitSub169(Sub169 sub, A arg);
+  R visitSub170(Sub170 sub, A arg);
+  R visitSub171(Sub171 sub, A arg);
+  R visitSub172(Sub172 sub, A arg);
+  R visitSub173(Sub173 sub, A arg);
+  R visitSub174(Sub174 sub, A arg);
+  R visitSub175(Sub175 sub, A arg);
+  R visitSub176(Sub176 sub, A arg);
+  R visitSub177(Sub177 sub, A arg);
+  R visitSub178(Sub178 sub, A arg);
+  R visitSub179(Sub179 sub, A arg);
+  R visitSub180(Sub180 sub, A arg);
+  R visitSub181(Sub181 sub, A arg);
+  R visitSub182(Sub182 sub, A arg);
+  R visitSub183(Sub183 sub, A arg);
+  R visitSub184(Sub184 sub, A arg);
+  R visitSub185(Sub185 sub, A arg);
+  R visitSub186(Sub186 sub, A arg);
+  R visitSub187(Sub187 sub, A arg);
+  R visitSub188(Sub188 sub, A arg);
+  R visitSub189(Sub189 sub, A arg);
+  R visitSub190(Sub190 sub, A arg);
+  R visitSub191(Sub191 sub, A arg);
+}
+
+class CounterVisitor192 implements Visitor192<void, Counter> {
+  const CounterVisitor192();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+
+  @override
+  void visitSub48(Sub48 sub, Counter counter) {
+    sub.visitorDispatch48(counter);
+  }
+
+  @override
+  void visitSub49(Sub49 sub, Counter counter) {
+    sub.visitorDispatch49(counter);
+  }
+
+  @override
+  void visitSub50(Sub50 sub, Counter counter) {
+    sub.visitorDispatch50(counter);
+  }
+
+  @override
+  void visitSub51(Sub51 sub, Counter counter) {
+    sub.visitorDispatch51(counter);
+  }
+
+  @override
+  void visitSub52(Sub52 sub, Counter counter) {
+    sub.visitorDispatch52(counter);
+  }
+
+  @override
+  void visitSub53(Sub53 sub, Counter counter) {
+    sub.visitorDispatch53(counter);
+  }
+
+  @override
+  void visitSub54(Sub54 sub, Counter counter) {
+    sub.visitorDispatch54(counter);
+  }
+
+  @override
+  void visitSub55(Sub55 sub, Counter counter) {
+    sub.visitorDispatch55(counter);
+  }
+
+  @override
+  void visitSub56(Sub56 sub, Counter counter) {
+    sub.visitorDispatch56(counter);
+  }
+
+  @override
+  void visitSub57(Sub57 sub, Counter counter) {
+    sub.visitorDispatch57(counter);
+  }
+
+  @override
+  void visitSub58(Sub58 sub, Counter counter) {
+    sub.visitorDispatch58(counter);
+  }
+
+  @override
+  void visitSub59(Sub59 sub, Counter counter) {
+    sub.visitorDispatch59(counter);
+  }
+
+  @override
+  void visitSub60(Sub60 sub, Counter counter) {
+    sub.visitorDispatch60(counter);
+  }
+
+  @override
+  void visitSub61(Sub61 sub, Counter counter) {
+    sub.visitorDispatch61(counter);
+  }
+
+  @override
+  void visitSub62(Sub62 sub, Counter counter) {
+    sub.visitorDispatch62(counter);
+  }
+
+  @override
+  void visitSub63(Sub63 sub, Counter counter) {
+    sub.visitorDispatch63(counter);
+  }
+
+  @override
+  void visitSub64(Sub64 sub, Counter counter) {
+    sub.visitorDispatch64(counter);
+  }
+
+  @override
+  void visitSub65(Sub65 sub, Counter counter) {
+    sub.visitorDispatch65(counter);
+  }
+
+  @override
+  void visitSub66(Sub66 sub, Counter counter) {
+    sub.visitorDispatch66(counter);
+  }
+
+  @override
+  void visitSub67(Sub67 sub, Counter counter) {
+    sub.visitorDispatch67(counter);
+  }
+
+  @override
+  void visitSub68(Sub68 sub, Counter counter) {
+    sub.visitorDispatch68(counter);
+  }
+
+  @override
+  void visitSub69(Sub69 sub, Counter counter) {
+    sub.visitorDispatch69(counter);
+  }
+
+  @override
+  void visitSub70(Sub70 sub, Counter counter) {
+    sub.visitorDispatch70(counter);
+  }
+
+  @override
+  void visitSub71(Sub71 sub, Counter counter) {
+    sub.visitorDispatch71(counter);
+  }
+
+  @override
+  void visitSub72(Sub72 sub, Counter counter) {
+    sub.visitorDispatch72(counter);
+  }
+
+  @override
+  void visitSub73(Sub73 sub, Counter counter) {
+    sub.visitorDispatch73(counter);
+  }
+
+  @override
+  void visitSub74(Sub74 sub, Counter counter) {
+    sub.visitorDispatch74(counter);
+  }
+
+  @override
+  void visitSub75(Sub75 sub, Counter counter) {
+    sub.visitorDispatch75(counter);
+  }
+
+  @override
+  void visitSub76(Sub76 sub, Counter counter) {
+    sub.visitorDispatch76(counter);
+  }
+
+  @override
+  void visitSub77(Sub77 sub, Counter counter) {
+    sub.visitorDispatch77(counter);
+  }
+
+  @override
+  void visitSub78(Sub78 sub, Counter counter) {
+    sub.visitorDispatch78(counter);
+  }
+
+  @override
+  void visitSub79(Sub79 sub, Counter counter) {
+    sub.visitorDispatch79(counter);
+  }
+
+  @override
+  void visitSub80(Sub80 sub, Counter counter) {
+    sub.visitorDispatch80(counter);
+  }
+
+  @override
+  void visitSub81(Sub81 sub, Counter counter) {
+    sub.visitorDispatch81(counter);
+  }
+
+  @override
+  void visitSub82(Sub82 sub, Counter counter) {
+    sub.visitorDispatch82(counter);
+  }
+
+  @override
+  void visitSub83(Sub83 sub, Counter counter) {
+    sub.visitorDispatch83(counter);
+  }
+
+  @override
+  void visitSub84(Sub84 sub, Counter counter) {
+    sub.visitorDispatch84(counter);
+  }
+
+  @override
+  void visitSub85(Sub85 sub, Counter counter) {
+    sub.visitorDispatch85(counter);
+  }
+
+  @override
+  void visitSub86(Sub86 sub, Counter counter) {
+    sub.visitorDispatch86(counter);
+  }
+
+  @override
+  void visitSub87(Sub87 sub, Counter counter) {
+    sub.visitorDispatch87(counter);
+  }
+
+  @override
+  void visitSub88(Sub88 sub, Counter counter) {
+    sub.visitorDispatch88(counter);
+  }
+
+  @override
+  void visitSub89(Sub89 sub, Counter counter) {
+    sub.visitorDispatch89(counter);
+  }
+
+  @override
+  void visitSub90(Sub90 sub, Counter counter) {
+    sub.visitorDispatch90(counter);
+  }
+
+  @override
+  void visitSub91(Sub91 sub, Counter counter) {
+    sub.visitorDispatch91(counter);
+  }
+
+  @override
+  void visitSub92(Sub92 sub, Counter counter) {
+    sub.visitorDispatch92(counter);
+  }
+
+  @override
+  void visitSub93(Sub93 sub, Counter counter) {
+    sub.visitorDispatch93(counter);
+  }
+
+  @override
+  void visitSub94(Sub94 sub, Counter counter) {
+    sub.visitorDispatch94(counter);
+  }
+
+  @override
+  void visitSub95(Sub95 sub, Counter counter) {
+    sub.visitorDispatch95(counter);
+  }
+
+  @override
+  void visitSub96(Sub96 sub, Counter counter) {
+    sub.visitorDispatch96(counter);
+  }
+
+  @override
+  void visitSub97(Sub97 sub, Counter counter) {
+    sub.visitorDispatch97(counter);
+  }
+
+  @override
+  void visitSub98(Sub98 sub, Counter counter) {
+    sub.visitorDispatch98(counter);
+  }
+
+  @override
+  void visitSub99(Sub99 sub, Counter counter) {
+    sub.visitorDispatch99(counter);
+  }
+
+  @override
+  void visitSub100(Sub100 sub, Counter counter) {
+    sub.visitorDispatch100(counter);
+  }
+
+  @override
+  void visitSub101(Sub101 sub, Counter counter) {
+    sub.visitorDispatch101(counter);
+  }
+
+  @override
+  void visitSub102(Sub102 sub, Counter counter) {
+    sub.visitorDispatch102(counter);
+  }
+
+  @override
+  void visitSub103(Sub103 sub, Counter counter) {
+    sub.visitorDispatch103(counter);
+  }
+
+  @override
+  void visitSub104(Sub104 sub, Counter counter) {
+    sub.visitorDispatch104(counter);
+  }
+
+  @override
+  void visitSub105(Sub105 sub, Counter counter) {
+    sub.visitorDispatch105(counter);
+  }
+
+  @override
+  void visitSub106(Sub106 sub, Counter counter) {
+    sub.visitorDispatch106(counter);
+  }
+
+  @override
+  void visitSub107(Sub107 sub, Counter counter) {
+    sub.visitorDispatch107(counter);
+  }
+
+  @override
+  void visitSub108(Sub108 sub, Counter counter) {
+    sub.visitorDispatch108(counter);
+  }
+
+  @override
+  void visitSub109(Sub109 sub, Counter counter) {
+    sub.visitorDispatch109(counter);
+  }
+
+  @override
+  void visitSub110(Sub110 sub, Counter counter) {
+    sub.visitorDispatch110(counter);
+  }
+
+  @override
+  void visitSub111(Sub111 sub, Counter counter) {
+    sub.visitorDispatch111(counter);
+  }
+
+  @override
+  void visitSub112(Sub112 sub, Counter counter) {
+    sub.visitorDispatch112(counter);
+  }
+
+  @override
+  void visitSub113(Sub113 sub, Counter counter) {
+    sub.visitorDispatch113(counter);
+  }
+
+  @override
+  void visitSub114(Sub114 sub, Counter counter) {
+    sub.visitorDispatch114(counter);
+  }
+
+  @override
+  void visitSub115(Sub115 sub, Counter counter) {
+    sub.visitorDispatch115(counter);
+  }
+
+  @override
+  void visitSub116(Sub116 sub, Counter counter) {
+    sub.visitorDispatch116(counter);
+  }
+
+  @override
+  void visitSub117(Sub117 sub, Counter counter) {
+    sub.visitorDispatch117(counter);
+  }
+
+  @override
+  void visitSub118(Sub118 sub, Counter counter) {
+    sub.visitorDispatch118(counter);
+  }
+
+  @override
+  void visitSub119(Sub119 sub, Counter counter) {
+    sub.visitorDispatch119(counter);
+  }
+
+  @override
+  void visitSub120(Sub120 sub, Counter counter) {
+    sub.visitorDispatch120(counter);
+  }
+
+  @override
+  void visitSub121(Sub121 sub, Counter counter) {
+    sub.visitorDispatch121(counter);
+  }
+
+  @override
+  void visitSub122(Sub122 sub, Counter counter) {
+    sub.visitorDispatch122(counter);
+  }
+
+  @override
+  void visitSub123(Sub123 sub, Counter counter) {
+    sub.visitorDispatch123(counter);
+  }
+
+  @override
+  void visitSub124(Sub124 sub, Counter counter) {
+    sub.visitorDispatch124(counter);
+  }
+
+  @override
+  void visitSub125(Sub125 sub, Counter counter) {
+    sub.visitorDispatch125(counter);
+  }
+
+  @override
+  void visitSub126(Sub126 sub, Counter counter) {
+    sub.visitorDispatch126(counter);
+  }
+
+  @override
+  void visitSub127(Sub127 sub, Counter counter) {
+    sub.visitorDispatch127(counter);
+  }
+
+  @override
+  void visitSub128(Sub128 sub, Counter counter) {
+    sub.visitorDispatch128(counter);
+  }
+
+  @override
+  void visitSub129(Sub129 sub, Counter counter) {
+    sub.visitorDispatch129(counter);
+  }
+
+  @override
+  void visitSub130(Sub130 sub, Counter counter) {
+    sub.visitorDispatch130(counter);
+  }
+
+  @override
+  void visitSub131(Sub131 sub, Counter counter) {
+    sub.visitorDispatch131(counter);
+  }
+
+  @override
+  void visitSub132(Sub132 sub, Counter counter) {
+    sub.visitorDispatch132(counter);
+  }
+
+  @override
+  void visitSub133(Sub133 sub, Counter counter) {
+    sub.visitorDispatch133(counter);
+  }
+
+  @override
+  void visitSub134(Sub134 sub, Counter counter) {
+    sub.visitorDispatch134(counter);
+  }
+
+  @override
+  void visitSub135(Sub135 sub, Counter counter) {
+    sub.visitorDispatch135(counter);
+  }
+
+  @override
+  void visitSub136(Sub136 sub, Counter counter) {
+    sub.visitorDispatch136(counter);
+  }
+
+  @override
+  void visitSub137(Sub137 sub, Counter counter) {
+    sub.visitorDispatch137(counter);
+  }
+
+  @override
+  void visitSub138(Sub138 sub, Counter counter) {
+    sub.visitorDispatch138(counter);
+  }
+
+  @override
+  void visitSub139(Sub139 sub, Counter counter) {
+    sub.visitorDispatch139(counter);
+  }
+
+  @override
+  void visitSub140(Sub140 sub, Counter counter) {
+    sub.visitorDispatch140(counter);
+  }
+
+  @override
+  void visitSub141(Sub141 sub, Counter counter) {
+    sub.visitorDispatch141(counter);
+  }
+
+  @override
+  void visitSub142(Sub142 sub, Counter counter) {
+    sub.visitorDispatch142(counter);
+  }
+
+  @override
+  void visitSub143(Sub143 sub, Counter counter) {
+    sub.visitorDispatch143(counter);
+  }
+
+  @override
+  void visitSub144(Sub144 sub, Counter counter) {
+    sub.visitorDispatch144(counter);
+  }
+
+  @override
+  void visitSub145(Sub145 sub, Counter counter) {
+    sub.visitorDispatch145(counter);
+  }
+
+  @override
+  void visitSub146(Sub146 sub, Counter counter) {
+    sub.visitorDispatch146(counter);
+  }
+
+  @override
+  void visitSub147(Sub147 sub, Counter counter) {
+    sub.visitorDispatch147(counter);
+  }
+
+  @override
+  void visitSub148(Sub148 sub, Counter counter) {
+    sub.visitorDispatch148(counter);
+  }
+
+  @override
+  void visitSub149(Sub149 sub, Counter counter) {
+    sub.visitorDispatch149(counter);
+  }
+
+  @override
+  void visitSub150(Sub150 sub, Counter counter) {
+    sub.visitorDispatch150(counter);
+  }
+
+  @override
+  void visitSub151(Sub151 sub, Counter counter) {
+    sub.visitorDispatch151(counter);
+  }
+
+  @override
+  void visitSub152(Sub152 sub, Counter counter) {
+    sub.visitorDispatch152(counter);
+  }
+
+  @override
+  void visitSub153(Sub153 sub, Counter counter) {
+    sub.visitorDispatch153(counter);
+  }
+
+  @override
+  void visitSub154(Sub154 sub, Counter counter) {
+    sub.visitorDispatch154(counter);
+  }
+
+  @override
+  void visitSub155(Sub155 sub, Counter counter) {
+    sub.visitorDispatch155(counter);
+  }
+
+  @override
+  void visitSub156(Sub156 sub, Counter counter) {
+    sub.visitorDispatch156(counter);
+  }
+
+  @override
+  void visitSub157(Sub157 sub, Counter counter) {
+    sub.visitorDispatch157(counter);
+  }
+
+  @override
+  void visitSub158(Sub158 sub, Counter counter) {
+    sub.visitorDispatch158(counter);
+  }
+
+  @override
+  void visitSub159(Sub159 sub, Counter counter) {
+    sub.visitorDispatch159(counter);
+  }
+
+  @override
+  void visitSub160(Sub160 sub, Counter counter) {
+    sub.visitorDispatch160(counter);
+  }
+
+  @override
+  void visitSub161(Sub161 sub, Counter counter) {
+    sub.visitorDispatch161(counter);
+  }
+
+  @override
+  void visitSub162(Sub162 sub, Counter counter) {
+    sub.visitorDispatch162(counter);
+  }
+
+  @override
+  void visitSub163(Sub163 sub, Counter counter) {
+    sub.visitorDispatch163(counter);
+  }
+
+  @override
+  void visitSub164(Sub164 sub, Counter counter) {
+    sub.visitorDispatch164(counter);
+  }
+
+  @override
+  void visitSub165(Sub165 sub, Counter counter) {
+    sub.visitorDispatch165(counter);
+  }
+
+  @override
+  void visitSub166(Sub166 sub, Counter counter) {
+    sub.visitorDispatch166(counter);
+  }
+
+  @override
+  void visitSub167(Sub167 sub, Counter counter) {
+    sub.visitorDispatch167(counter);
+  }
+
+  @override
+  void visitSub168(Sub168 sub, Counter counter) {
+    sub.visitorDispatch168(counter);
+  }
+
+  @override
+  void visitSub169(Sub169 sub, Counter counter) {
+    sub.visitorDispatch169(counter);
+  }
+
+  @override
+  void visitSub170(Sub170 sub, Counter counter) {
+    sub.visitorDispatch170(counter);
+  }
+
+  @override
+  void visitSub171(Sub171 sub, Counter counter) {
+    sub.visitorDispatch171(counter);
+  }
+
+  @override
+  void visitSub172(Sub172 sub, Counter counter) {
+    sub.visitorDispatch172(counter);
+  }
+
+  @override
+  void visitSub173(Sub173 sub, Counter counter) {
+    sub.visitorDispatch173(counter);
+  }
+
+  @override
+  void visitSub174(Sub174 sub, Counter counter) {
+    sub.visitorDispatch174(counter);
+  }
+
+  @override
+  void visitSub175(Sub175 sub, Counter counter) {
+    sub.visitorDispatch175(counter);
+  }
+
+  @override
+  void visitSub176(Sub176 sub, Counter counter) {
+    sub.visitorDispatch176(counter);
+  }
+
+  @override
+  void visitSub177(Sub177 sub, Counter counter) {
+    sub.visitorDispatch177(counter);
+  }
+
+  @override
+  void visitSub178(Sub178 sub, Counter counter) {
+    sub.visitorDispatch178(counter);
+  }
+
+  @override
+  void visitSub179(Sub179 sub, Counter counter) {
+    sub.visitorDispatch179(counter);
+  }
+
+  @override
+  void visitSub180(Sub180 sub, Counter counter) {
+    sub.visitorDispatch180(counter);
+  }
+
+  @override
+  void visitSub181(Sub181 sub, Counter counter) {
+    sub.visitorDispatch181(counter);
+  }
+
+  @override
+  void visitSub182(Sub182 sub, Counter counter) {
+    sub.visitorDispatch182(counter);
+  }
+
+  @override
+  void visitSub183(Sub183 sub, Counter counter) {
+    sub.visitorDispatch183(counter);
+  }
+
+  @override
+  void visitSub184(Sub184 sub, Counter counter) {
+    sub.visitorDispatch184(counter);
+  }
+
+  @override
+  void visitSub185(Sub185 sub, Counter counter) {
+    sub.visitorDispatch185(counter);
+  }
+
+  @override
+  void visitSub186(Sub186 sub, Counter counter) {
+    sub.visitorDispatch186(counter);
+  }
+
+  @override
+  void visitSub187(Sub187 sub, Counter counter) {
+    sub.visitorDispatch187(counter);
+  }
+
+  @override
+  void visitSub188(Sub188 sub, Counter counter) {
+    sub.visitorDispatch188(counter);
+  }
+
+  @override
+  void visitSub189(Sub189 sub, Counter counter) {
+    sub.visitorDispatch189(counter);
+  }
+
+  @override
+  void visitSub190(Sub190 sub, Counter counter) {
+    sub.visitorDispatch190(counter);
+  }
+
+  @override
+  void visitSub191(Sub191 sub, Counter counter) {
+    sub.visitorDispatch191(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype2.dart b/pkg/front_end/benchmarks/patterns/generated/datatype2.dart
new file mode 100644
index 0000000..7ccaec3
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype2.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base2 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor2<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base2 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor2<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base2 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor2<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+List<Base2> createData2() {
+  return [
+    Sub0(),
+    Sub1(),
+  ];
+}
+
+void incByDynamicDispatch2(Base2 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch2(Base2 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  }
+}
+
+const Visitor2<void, Counter> visitor = CounterVisitor2();
+
+void incByVisitorDispatch2(Base2 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor2<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+}
+
+class CounterVisitor2 implements Visitor2<void, Counter> {
+  const CounterVisitor2();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype24.dart b/pkg/front_end/benchmarks/patterns/generated/datatype24.dart
new file mode 100644
index 0000000..a17a6b7
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype24.dart
@@ -0,0 +1,737 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base24 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor24<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base24 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor24<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+List<Base24> createData24() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+  ];
+}
+
+void incByDynamicDispatch24(Base24 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch24(Base24 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  }
+}
+
+const Visitor24<void, Counter> visitor = CounterVisitor24();
+
+void incByVisitorDispatch24(Base24 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor24<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+}
+
+class CounterVisitor24 implements Visitor24<void, Counter> {
+  const CounterVisitor24();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype256.dart b/pkg/front_end/benchmarks/patterns/generated/datatype256.dart
new file mode 100644
index 0000000..cfdee4a
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype256.dart
@@ -0,0 +1,7465 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base256 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor256<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+class Sub48 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub48(this, arg);
+  }
+}
+
+class Sub49 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub49(this, arg);
+  }
+}
+
+class Sub50 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub50(this, arg);
+  }
+}
+
+class Sub51 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub51(this, arg);
+  }
+}
+
+class Sub52 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub52(this, arg);
+  }
+}
+
+class Sub53 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub53(this, arg);
+  }
+}
+
+class Sub54 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub54(this, arg);
+  }
+}
+
+class Sub55 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub55(this, arg);
+  }
+}
+
+class Sub56 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub56(this, arg);
+  }
+}
+
+class Sub57 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub57(this, arg);
+  }
+}
+
+class Sub58 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub58(this, arg);
+  }
+}
+
+class Sub59 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub59(this, arg);
+  }
+}
+
+class Sub60 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub60(this, arg);
+  }
+}
+
+class Sub61 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub61(this, arg);
+  }
+}
+
+class Sub62 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub62(this, arg);
+  }
+}
+
+class Sub63 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub63(this, arg);
+  }
+}
+
+class Sub64 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub64(this, arg);
+  }
+}
+
+class Sub65 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub65(this, arg);
+  }
+}
+
+class Sub66 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub66(this, arg);
+  }
+}
+
+class Sub67 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub67(this, arg);
+  }
+}
+
+class Sub68 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub68(this, arg);
+  }
+}
+
+class Sub69 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub69(this, arg);
+  }
+}
+
+class Sub70 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub70(this, arg);
+  }
+}
+
+class Sub71 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub71(this, arg);
+  }
+}
+
+class Sub72 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub72(this, arg);
+  }
+}
+
+class Sub73 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub73(this, arg);
+  }
+}
+
+class Sub74 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub74(this, arg);
+  }
+}
+
+class Sub75 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub75(this, arg);
+  }
+}
+
+class Sub76 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub76(this, arg);
+  }
+}
+
+class Sub77 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub77(this, arg);
+  }
+}
+
+class Sub78 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub78(this, arg);
+  }
+}
+
+class Sub79 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub79(this, arg);
+  }
+}
+
+class Sub80 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub80(this, arg);
+  }
+}
+
+class Sub81 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub81(this, arg);
+  }
+}
+
+class Sub82 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub82(this, arg);
+  }
+}
+
+class Sub83 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub83(this, arg);
+  }
+}
+
+class Sub84 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub84(this, arg);
+  }
+}
+
+class Sub85 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub85(this, arg);
+  }
+}
+
+class Sub86 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub86(this, arg);
+  }
+}
+
+class Sub87 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub87(this, arg);
+  }
+}
+
+class Sub88 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub88(this, arg);
+  }
+}
+
+class Sub89 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub89(this, arg);
+  }
+}
+
+class Sub90 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub90(this, arg);
+  }
+}
+
+class Sub91 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub91(this, arg);
+  }
+}
+
+class Sub92 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub92(this, arg);
+  }
+}
+
+class Sub93 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub93(this, arg);
+  }
+}
+
+class Sub94 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub94(this, arg);
+  }
+}
+
+class Sub95 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub95(this, arg);
+  }
+}
+
+class Sub96 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch96(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub96(this, arg);
+  }
+}
+
+class Sub97 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch97(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub97(this, arg);
+  }
+}
+
+class Sub98 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch98(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub98(this, arg);
+  }
+}
+
+class Sub99 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch99(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub99(this, arg);
+  }
+}
+
+class Sub100 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch100(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub100(this, arg);
+  }
+}
+
+class Sub101 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch101(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub101(this, arg);
+  }
+}
+
+class Sub102 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch102(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub102(this, arg);
+  }
+}
+
+class Sub103 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch103(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub103(this, arg);
+  }
+}
+
+class Sub104 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch104(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub104(this, arg);
+  }
+}
+
+class Sub105 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch105(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub105(this, arg);
+  }
+}
+
+class Sub106 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch106(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub106(this, arg);
+  }
+}
+
+class Sub107 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch107(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub107(this, arg);
+  }
+}
+
+class Sub108 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch108(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub108(this, arg);
+  }
+}
+
+class Sub109 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch109(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub109(this, arg);
+  }
+}
+
+class Sub110 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch110(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub110(this, arg);
+  }
+}
+
+class Sub111 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch111(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub111(this, arg);
+  }
+}
+
+class Sub112 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch112(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub112(this, arg);
+  }
+}
+
+class Sub113 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch113(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub113(this, arg);
+  }
+}
+
+class Sub114 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch114(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub114(this, arg);
+  }
+}
+
+class Sub115 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch115(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub115(this, arg);
+  }
+}
+
+class Sub116 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch116(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub116(this, arg);
+  }
+}
+
+class Sub117 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch117(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub117(this, arg);
+  }
+}
+
+class Sub118 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch118(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub118(this, arg);
+  }
+}
+
+class Sub119 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch119(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub119(this, arg);
+  }
+}
+
+class Sub120 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch120(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub120(this, arg);
+  }
+}
+
+class Sub121 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch121(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub121(this, arg);
+  }
+}
+
+class Sub122 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch122(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub122(this, arg);
+  }
+}
+
+class Sub123 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch123(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub123(this, arg);
+  }
+}
+
+class Sub124 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch124(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub124(this, arg);
+  }
+}
+
+class Sub125 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch125(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub125(this, arg);
+  }
+}
+
+class Sub126 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch126(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub126(this, arg);
+  }
+}
+
+class Sub127 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch127(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub127(this, arg);
+  }
+}
+
+class Sub128 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch128(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch128(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub128(this, arg);
+  }
+}
+
+class Sub129 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch129(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch129(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub129(this, arg);
+  }
+}
+
+class Sub130 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch130(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch130(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub130(this, arg);
+  }
+}
+
+class Sub131 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch131(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch131(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub131(this, arg);
+  }
+}
+
+class Sub132 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch132(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch132(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub132(this, arg);
+  }
+}
+
+class Sub133 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch133(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch133(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub133(this, arg);
+  }
+}
+
+class Sub134 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch134(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch134(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub134(this, arg);
+  }
+}
+
+class Sub135 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch135(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch135(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub135(this, arg);
+  }
+}
+
+class Sub136 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch136(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch136(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub136(this, arg);
+  }
+}
+
+class Sub137 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch137(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch137(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub137(this, arg);
+  }
+}
+
+class Sub138 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch138(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch138(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub138(this, arg);
+  }
+}
+
+class Sub139 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch139(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch139(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub139(this, arg);
+  }
+}
+
+class Sub140 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch140(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch140(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub140(this, arg);
+  }
+}
+
+class Sub141 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch141(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch141(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub141(this, arg);
+  }
+}
+
+class Sub142 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch142(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch142(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub142(this, arg);
+  }
+}
+
+class Sub143 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch143(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch143(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub143(this, arg);
+  }
+}
+
+class Sub144 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch144(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch144(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub144(this, arg);
+  }
+}
+
+class Sub145 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch145(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch145(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub145(this, arg);
+  }
+}
+
+class Sub146 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch146(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch146(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub146(this, arg);
+  }
+}
+
+class Sub147 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch147(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch147(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub147(this, arg);
+  }
+}
+
+class Sub148 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch148(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch148(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub148(this, arg);
+  }
+}
+
+class Sub149 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch149(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch149(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub149(this, arg);
+  }
+}
+
+class Sub150 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch150(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch150(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub150(this, arg);
+  }
+}
+
+class Sub151 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch151(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch151(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub151(this, arg);
+  }
+}
+
+class Sub152 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch152(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch152(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub152(this, arg);
+  }
+}
+
+class Sub153 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch153(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch153(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub153(this, arg);
+  }
+}
+
+class Sub154 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch154(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch154(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub154(this, arg);
+  }
+}
+
+class Sub155 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch155(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch155(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub155(this, arg);
+  }
+}
+
+class Sub156 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch156(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch156(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub156(this, arg);
+  }
+}
+
+class Sub157 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch157(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch157(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub157(this, arg);
+  }
+}
+
+class Sub158 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch158(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch158(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub158(this, arg);
+  }
+}
+
+class Sub159 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch159(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch159(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub159(this, arg);
+  }
+}
+
+class Sub160 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch160(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch160(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub160(this, arg);
+  }
+}
+
+class Sub161 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch161(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch161(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub161(this, arg);
+  }
+}
+
+class Sub162 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch162(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch162(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub162(this, arg);
+  }
+}
+
+class Sub163 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch163(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch163(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub163(this, arg);
+  }
+}
+
+class Sub164 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch164(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch164(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub164(this, arg);
+  }
+}
+
+class Sub165 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch165(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch165(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub165(this, arg);
+  }
+}
+
+class Sub166 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch166(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch166(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub166(this, arg);
+  }
+}
+
+class Sub167 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch167(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch167(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub167(this, arg);
+  }
+}
+
+class Sub168 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch168(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch168(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub168(this, arg);
+  }
+}
+
+class Sub169 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch169(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch169(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub169(this, arg);
+  }
+}
+
+class Sub170 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch170(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch170(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub170(this, arg);
+  }
+}
+
+class Sub171 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch171(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch171(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub171(this, arg);
+  }
+}
+
+class Sub172 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch172(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch172(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub172(this, arg);
+  }
+}
+
+class Sub173 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch173(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch173(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub173(this, arg);
+  }
+}
+
+class Sub174 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch174(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch174(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub174(this, arg);
+  }
+}
+
+class Sub175 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch175(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch175(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub175(this, arg);
+  }
+}
+
+class Sub176 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch176(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch176(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub176(this, arg);
+  }
+}
+
+class Sub177 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch177(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch177(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub177(this, arg);
+  }
+}
+
+class Sub178 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch178(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch178(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub178(this, arg);
+  }
+}
+
+class Sub179 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch179(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch179(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub179(this, arg);
+  }
+}
+
+class Sub180 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch180(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch180(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub180(this, arg);
+  }
+}
+
+class Sub181 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch181(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch181(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub181(this, arg);
+  }
+}
+
+class Sub182 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch182(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch182(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub182(this, arg);
+  }
+}
+
+class Sub183 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch183(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch183(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub183(this, arg);
+  }
+}
+
+class Sub184 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch184(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch184(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub184(this, arg);
+  }
+}
+
+class Sub185 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch185(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch185(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub185(this, arg);
+  }
+}
+
+class Sub186 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch186(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch186(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub186(this, arg);
+  }
+}
+
+class Sub187 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch187(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch187(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub187(this, arg);
+  }
+}
+
+class Sub188 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch188(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch188(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub188(this, arg);
+  }
+}
+
+class Sub189 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch189(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch189(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub189(this, arg);
+  }
+}
+
+class Sub190 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch190(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch190(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub190(this, arg);
+  }
+}
+
+class Sub191 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch191(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch191(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub191(this, arg);
+  }
+}
+
+class Sub192 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch192(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch192(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub192(this, arg);
+  }
+}
+
+class Sub193 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch193(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch193(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub193(this, arg);
+  }
+}
+
+class Sub194 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch194(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch194(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub194(this, arg);
+  }
+}
+
+class Sub195 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch195(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch195(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub195(this, arg);
+  }
+}
+
+class Sub196 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch196(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch196(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub196(this, arg);
+  }
+}
+
+class Sub197 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch197(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch197(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub197(this, arg);
+  }
+}
+
+class Sub198 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch198(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch198(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub198(this, arg);
+  }
+}
+
+class Sub199 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch199(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch199(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub199(this, arg);
+  }
+}
+
+class Sub200 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch200(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch200(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub200(this, arg);
+  }
+}
+
+class Sub201 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch201(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch201(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub201(this, arg);
+  }
+}
+
+class Sub202 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch202(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch202(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub202(this, arg);
+  }
+}
+
+class Sub203 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch203(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch203(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub203(this, arg);
+  }
+}
+
+class Sub204 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch204(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch204(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub204(this, arg);
+  }
+}
+
+class Sub205 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch205(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch205(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub205(this, arg);
+  }
+}
+
+class Sub206 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch206(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch206(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub206(this, arg);
+  }
+}
+
+class Sub207 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch207(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch207(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub207(this, arg);
+  }
+}
+
+class Sub208 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch208(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch208(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub208(this, arg);
+  }
+}
+
+class Sub209 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch209(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch209(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub209(this, arg);
+  }
+}
+
+class Sub210 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch210(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch210(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub210(this, arg);
+  }
+}
+
+class Sub211 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch211(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch211(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub211(this, arg);
+  }
+}
+
+class Sub212 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch212(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch212(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub212(this, arg);
+  }
+}
+
+class Sub213 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch213(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch213(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub213(this, arg);
+  }
+}
+
+class Sub214 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch214(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch214(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub214(this, arg);
+  }
+}
+
+class Sub215 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch215(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch215(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub215(this, arg);
+  }
+}
+
+class Sub216 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch216(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch216(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub216(this, arg);
+  }
+}
+
+class Sub217 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch217(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch217(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub217(this, arg);
+  }
+}
+
+class Sub218 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch218(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch218(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub218(this, arg);
+  }
+}
+
+class Sub219 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch219(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch219(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub219(this, arg);
+  }
+}
+
+class Sub220 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch220(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch220(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub220(this, arg);
+  }
+}
+
+class Sub221 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch221(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch221(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub221(this, arg);
+  }
+}
+
+class Sub222 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch222(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch222(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub222(this, arg);
+  }
+}
+
+class Sub223 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch223(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch223(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub223(this, arg);
+  }
+}
+
+class Sub224 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch224(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch224(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub224(this, arg);
+  }
+}
+
+class Sub225 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch225(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch225(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub225(this, arg);
+  }
+}
+
+class Sub226 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch226(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch226(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub226(this, arg);
+  }
+}
+
+class Sub227 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch227(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch227(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub227(this, arg);
+  }
+}
+
+class Sub228 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch228(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch228(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub228(this, arg);
+  }
+}
+
+class Sub229 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch229(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch229(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub229(this, arg);
+  }
+}
+
+class Sub230 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch230(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch230(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub230(this, arg);
+  }
+}
+
+class Sub231 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch231(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch231(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub231(this, arg);
+  }
+}
+
+class Sub232 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch232(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch232(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub232(this, arg);
+  }
+}
+
+class Sub233 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch233(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch233(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub233(this, arg);
+  }
+}
+
+class Sub234 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch234(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch234(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub234(this, arg);
+  }
+}
+
+class Sub235 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch235(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch235(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub235(this, arg);
+  }
+}
+
+class Sub236 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch236(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch236(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub236(this, arg);
+  }
+}
+
+class Sub237 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch237(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch237(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub237(this, arg);
+  }
+}
+
+class Sub238 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch238(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch238(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub238(this, arg);
+  }
+}
+
+class Sub239 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch239(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch239(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub239(this, arg);
+  }
+}
+
+class Sub240 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch240(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch240(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub240(this, arg);
+  }
+}
+
+class Sub241 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch241(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch241(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub241(this, arg);
+  }
+}
+
+class Sub242 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch242(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch242(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub242(this, arg);
+  }
+}
+
+class Sub243 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch243(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch243(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub243(this, arg);
+  }
+}
+
+class Sub244 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch244(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch244(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub244(this, arg);
+  }
+}
+
+class Sub245 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch245(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch245(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub245(this, arg);
+  }
+}
+
+class Sub246 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch246(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch246(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub246(this, arg);
+  }
+}
+
+class Sub247 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch247(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch247(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub247(this, arg);
+  }
+}
+
+class Sub248 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch248(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch248(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub248(this, arg);
+  }
+}
+
+class Sub249 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch249(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch249(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub249(this, arg);
+  }
+}
+
+class Sub250 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch250(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch250(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub250(this, arg);
+  }
+}
+
+class Sub251 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch251(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch251(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub251(this, arg);
+  }
+}
+
+class Sub252 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch252(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch252(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub252(this, arg);
+  }
+}
+
+class Sub253 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch253(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch253(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub253(this, arg);
+  }
+}
+
+class Sub254 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch254(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch254(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub254(this, arg);
+  }
+}
+
+class Sub255 extends Base256 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch255(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch255(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor256<R, A> visitor, A arg) {
+    return visitor.visitSub255(this, arg);
+  }
+}
+
+List<Base256> createData256() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+    Sub48(),
+    Sub49(),
+    Sub50(),
+    Sub51(),
+    Sub52(),
+    Sub53(),
+    Sub54(),
+    Sub55(),
+    Sub56(),
+    Sub57(),
+    Sub58(),
+    Sub59(),
+    Sub60(),
+    Sub61(),
+    Sub62(),
+    Sub63(),
+    Sub64(),
+    Sub65(),
+    Sub66(),
+    Sub67(),
+    Sub68(),
+    Sub69(),
+    Sub70(),
+    Sub71(),
+    Sub72(),
+    Sub73(),
+    Sub74(),
+    Sub75(),
+    Sub76(),
+    Sub77(),
+    Sub78(),
+    Sub79(),
+    Sub80(),
+    Sub81(),
+    Sub82(),
+    Sub83(),
+    Sub84(),
+    Sub85(),
+    Sub86(),
+    Sub87(),
+    Sub88(),
+    Sub89(),
+    Sub90(),
+    Sub91(),
+    Sub92(),
+    Sub93(),
+    Sub94(),
+    Sub95(),
+    Sub96(),
+    Sub97(),
+    Sub98(),
+    Sub99(),
+    Sub100(),
+    Sub101(),
+    Sub102(),
+    Sub103(),
+    Sub104(),
+    Sub105(),
+    Sub106(),
+    Sub107(),
+    Sub108(),
+    Sub109(),
+    Sub110(),
+    Sub111(),
+    Sub112(),
+    Sub113(),
+    Sub114(),
+    Sub115(),
+    Sub116(),
+    Sub117(),
+    Sub118(),
+    Sub119(),
+    Sub120(),
+    Sub121(),
+    Sub122(),
+    Sub123(),
+    Sub124(),
+    Sub125(),
+    Sub126(),
+    Sub127(),
+    Sub128(),
+    Sub129(),
+    Sub130(),
+    Sub131(),
+    Sub132(),
+    Sub133(),
+    Sub134(),
+    Sub135(),
+    Sub136(),
+    Sub137(),
+    Sub138(),
+    Sub139(),
+    Sub140(),
+    Sub141(),
+    Sub142(),
+    Sub143(),
+    Sub144(),
+    Sub145(),
+    Sub146(),
+    Sub147(),
+    Sub148(),
+    Sub149(),
+    Sub150(),
+    Sub151(),
+    Sub152(),
+    Sub153(),
+    Sub154(),
+    Sub155(),
+    Sub156(),
+    Sub157(),
+    Sub158(),
+    Sub159(),
+    Sub160(),
+    Sub161(),
+    Sub162(),
+    Sub163(),
+    Sub164(),
+    Sub165(),
+    Sub166(),
+    Sub167(),
+    Sub168(),
+    Sub169(),
+    Sub170(),
+    Sub171(),
+    Sub172(),
+    Sub173(),
+    Sub174(),
+    Sub175(),
+    Sub176(),
+    Sub177(),
+    Sub178(),
+    Sub179(),
+    Sub180(),
+    Sub181(),
+    Sub182(),
+    Sub183(),
+    Sub184(),
+    Sub185(),
+    Sub186(),
+    Sub187(),
+    Sub188(),
+    Sub189(),
+    Sub190(),
+    Sub191(),
+    Sub192(),
+    Sub193(),
+    Sub194(),
+    Sub195(),
+    Sub196(),
+    Sub197(),
+    Sub198(),
+    Sub199(),
+    Sub200(),
+    Sub201(),
+    Sub202(),
+    Sub203(),
+    Sub204(),
+    Sub205(),
+    Sub206(),
+    Sub207(),
+    Sub208(),
+    Sub209(),
+    Sub210(),
+    Sub211(),
+    Sub212(),
+    Sub213(),
+    Sub214(),
+    Sub215(),
+    Sub216(),
+    Sub217(),
+    Sub218(),
+    Sub219(),
+    Sub220(),
+    Sub221(),
+    Sub222(),
+    Sub223(),
+    Sub224(),
+    Sub225(),
+    Sub226(),
+    Sub227(),
+    Sub228(),
+    Sub229(),
+    Sub230(),
+    Sub231(),
+    Sub232(),
+    Sub233(),
+    Sub234(),
+    Sub235(),
+    Sub236(),
+    Sub237(),
+    Sub238(),
+    Sub239(),
+    Sub240(),
+    Sub241(),
+    Sub242(),
+    Sub243(),
+    Sub244(),
+    Sub245(),
+    Sub246(),
+    Sub247(),
+    Sub248(),
+    Sub249(),
+    Sub250(),
+    Sub251(),
+    Sub252(),
+    Sub253(),
+    Sub254(),
+    Sub255(),
+  ];
+}
+
+void incByDynamicDispatch256(Base256 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch256(Base256 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  } else if (base is Sub48) {
+    base.ifThenElseDispatch48(counter);
+  } else if (base is Sub49) {
+    base.ifThenElseDispatch49(counter);
+  } else if (base is Sub50) {
+    base.ifThenElseDispatch50(counter);
+  } else if (base is Sub51) {
+    base.ifThenElseDispatch51(counter);
+  } else if (base is Sub52) {
+    base.ifThenElseDispatch52(counter);
+  } else if (base is Sub53) {
+    base.ifThenElseDispatch53(counter);
+  } else if (base is Sub54) {
+    base.ifThenElseDispatch54(counter);
+  } else if (base is Sub55) {
+    base.ifThenElseDispatch55(counter);
+  } else if (base is Sub56) {
+    base.ifThenElseDispatch56(counter);
+  } else if (base is Sub57) {
+    base.ifThenElseDispatch57(counter);
+  } else if (base is Sub58) {
+    base.ifThenElseDispatch58(counter);
+  } else if (base is Sub59) {
+    base.ifThenElseDispatch59(counter);
+  } else if (base is Sub60) {
+    base.ifThenElseDispatch60(counter);
+  } else if (base is Sub61) {
+    base.ifThenElseDispatch61(counter);
+  } else if (base is Sub62) {
+    base.ifThenElseDispatch62(counter);
+  } else if (base is Sub63) {
+    base.ifThenElseDispatch63(counter);
+  } else if (base is Sub64) {
+    base.ifThenElseDispatch64(counter);
+  } else if (base is Sub65) {
+    base.ifThenElseDispatch65(counter);
+  } else if (base is Sub66) {
+    base.ifThenElseDispatch66(counter);
+  } else if (base is Sub67) {
+    base.ifThenElseDispatch67(counter);
+  } else if (base is Sub68) {
+    base.ifThenElseDispatch68(counter);
+  } else if (base is Sub69) {
+    base.ifThenElseDispatch69(counter);
+  } else if (base is Sub70) {
+    base.ifThenElseDispatch70(counter);
+  } else if (base is Sub71) {
+    base.ifThenElseDispatch71(counter);
+  } else if (base is Sub72) {
+    base.ifThenElseDispatch72(counter);
+  } else if (base is Sub73) {
+    base.ifThenElseDispatch73(counter);
+  } else if (base is Sub74) {
+    base.ifThenElseDispatch74(counter);
+  } else if (base is Sub75) {
+    base.ifThenElseDispatch75(counter);
+  } else if (base is Sub76) {
+    base.ifThenElseDispatch76(counter);
+  } else if (base is Sub77) {
+    base.ifThenElseDispatch77(counter);
+  } else if (base is Sub78) {
+    base.ifThenElseDispatch78(counter);
+  } else if (base is Sub79) {
+    base.ifThenElseDispatch79(counter);
+  } else if (base is Sub80) {
+    base.ifThenElseDispatch80(counter);
+  } else if (base is Sub81) {
+    base.ifThenElseDispatch81(counter);
+  } else if (base is Sub82) {
+    base.ifThenElseDispatch82(counter);
+  } else if (base is Sub83) {
+    base.ifThenElseDispatch83(counter);
+  } else if (base is Sub84) {
+    base.ifThenElseDispatch84(counter);
+  } else if (base is Sub85) {
+    base.ifThenElseDispatch85(counter);
+  } else if (base is Sub86) {
+    base.ifThenElseDispatch86(counter);
+  } else if (base is Sub87) {
+    base.ifThenElseDispatch87(counter);
+  } else if (base is Sub88) {
+    base.ifThenElseDispatch88(counter);
+  } else if (base is Sub89) {
+    base.ifThenElseDispatch89(counter);
+  } else if (base is Sub90) {
+    base.ifThenElseDispatch90(counter);
+  } else if (base is Sub91) {
+    base.ifThenElseDispatch91(counter);
+  } else if (base is Sub92) {
+    base.ifThenElseDispatch92(counter);
+  } else if (base is Sub93) {
+    base.ifThenElseDispatch93(counter);
+  } else if (base is Sub94) {
+    base.ifThenElseDispatch94(counter);
+  } else if (base is Sub95) {
+    base.ifThenElseDispatch95(counter);
+  } else if (base is Sub96) {
+    base.ifThenElseDispatch96(counter);
+  } else if (base is Sub97) {
+    base.ifThenElseDispatch97(counter);
+  } else if (base is Sub98) {
+    base.ifThenElseDispatch98(counter);
+  } else if (base is Sub99) {
+    base.ifThenElseDispatch99(counter);
+  } else if (base is Sub100) {
+    base.ifThenElseDispatch100(counter);
+  } else if (base is Sub101) {
+    base.ifThenElseDispatch101(counter);
+  } else if (base is Sub102) {
+    base.ifThenElseDispatch102(counter);
+  } else if (base is Sub103) {
+    base.ifThenElseDispatch103(counter);
+  } else if (base is Sub104) {
+    base.ifThenElseDispatch104(counter);
+  } else if (base is Sub105) {
+    base.ifThenElseDispatch105(counter);
+  } else if (base is Sub106) {
+    base.ifThenElseDispatch106(counter);
+  } else if (base is Sub107) {
+    base.ifThenElseDispatch107(counter);
+  } else if (base is Sub108) {
+    base.ifThenElseDispatch108(counter);
+  } else if (base is Sub109) {
+    base.ifThenElseDispatch109(counter);
+  } else if (base is Sub110) {
+    base.ifThenElseDispatch110(counter);
+  } else if (base is Sub111) {
+    base.ifThenElseDispatch111(counter);
+  } else if (base is Sub112) {
+    base.ifThenElseDispatch112(counter);
+  } else if (base is Sub113) {
+    base.ifThenElseDispatch113(counter);
+  } else if (base is Sub114) {
+    base.ifThenElseDispatch114(counter);
+  } else if (base is Sub115) {
+    base.ifThenElseDispatch115(counter);
+  } else if (base is Sub116) {
+    base.ifThenElseDispatch116(counter);
+  } else if (base is Sub117) {
+    base.ifThenElseDispatch117(counter);
+  } else if (base is Sub118) {
+    base.ifThenElseDispatch118(counter);
+  } else if (base is Sub119) {
+    base.ifThenElseDispatch119(counter);
+  } else if (base is Sub120) {
+    base.ifThenElseDispatch120(counter);
+  } else if (base is Sub121) {
+    base.ifThenElseDispatch121(counter);
+  } else if (base is Sub122) {
+    base.ifThenElseDispatch122(counter);
+  } else if (base is Sub123) {
+    base.ifThenElseDispatch123(counter);
+  } else if (base is Sub124) {
+    base.ifThenElseDispatch124(counter);
+  } else if (base is Sub125) {
+    base.ifThenElseDispatch125(counter);
+  } else if (base is Sub126) {
+    base.ifThenElseDispatch126(counter);
+  } else if (base is Sub127) {
+    base.ifThenElseDispatch127(counter);
+  } else if (base is Sub128) {
+    base.ifThenElseDispatch128(counter);
+  } else if (base is Sub129) {
+    base.ifThenElseDispatch129(counter);
+  } else if (base is Sub130) {
+    base.ifThenElseDispatch130(counter);
+  } else if (base is Sub131) {
+    base.ifThenElseDispatch131(counter);
+  } else if (base is Sub132) {
+    base.ifThenElseDispatch132(counter);
+  } else if (base is Sub133) {
+    base.ifThenElseDispatch133(counter);
+  } else if (base is Sub134) {
+    base.ifThenElseDispatch134(counter);
+  } else if (base is Sub135) {
+    base.ifThenElseDispatch135(counter);
+  } else if (base is Sub136) {
+    base.ifThenElseDispatch136(counter);
+  } else if (base is Sub137) {
+    base.ifThenElseDispatch137(counter);
+  } else if (base is Sub138) {
+    base.ifThenElseDispatch138(counter);
+  } else if (base is Sub139) {
+    base.ifThenElseDispatch139(counter);
+  } else if (base is Sub140) {
+    base.ifThenElseDispatch140(counter);
+  } else if (base is Sub141) {
+    base.ifThenElseDispatch141(counter);
+  } else if (base is Sub142) {
+    base.ifThenElseDispatch142(counter);
+  } else if (base is Sub143) {
+    base.ifThenElseDispatch143(counter);
+  } else if (base is Sub144) {
+    base.ifThenElseDispatch144(counter);
+  } else if (base is Sub145) {
+    base.ifThenElseDispatch145(counter);
+  } else if (base is Sub146) {
+    base.ifThenElseDispatch146(counter);
+  } else if (base is Sub147) {
+    base.ifThenElseDispatch147(counter);
+  } else if (base is Sub148) {
+    base.ifThenElseDispatch148(counter);
+  } else if (base is Sub149) {
+    base.ifThenElseDispatch149(counter);
+  } else if (base is Sub150) {
+    base.ifThenElseDispatch150(counter);
+  } else if (base is Sub151) {
+    base.ifThenElseDispatch151(counter);
+  } else if (base is Sub152) {
+    base.ifThenElseDispatch152(counter);
+  } else if (base is Sub153) {
+    base.ifThenElseDispatch153(counter);
+  } else if (base is Sub154) {
+    base.ifThenElseDispatch154(counter);
+  } else if (base is Sub155) {
+    base.ifThenElseDispatch155(counter);
+  } else if (base is Sub156) {
+    base.ifThenElseDispatch156(counter);
+  } else if (base is Sub157) {
+    base.ifThenElseDispatch157(counter);
+  } else if (base is Sub158) {
+    base.ifThenElseDispatch158(counter);
+  } else if (base is Sub159) {
+    base.ifThenElseDispatch159(counter);
+  } else if (base is Sub160) {
+    base.ifThenElseDispatch160(counter);
+  } else if (base is Sub161) {
+    base.ifThenElseDispatch161(counter);
+  } else if (base is Sub162) {
+    base.ifThenElseDispatch162(counter);
+  } else if (base is Sub163) {
+    base.ifThenElseDispatch163(counter);
+  } else if (base is Sub164) {
+    base.ifThenElseDispatch164(counter);
+  } else if (base is Sub165) {
+    base.ifThenElseDispatch165(counter);
+  } else if (base is Sub166) {
+    base.ifThenElseDispatch166(counter);
+  } else if (base is Sub167) {
+    base.ifThenElseDispatch167(counter);
+  } else if (base is Sub168) {
+    base.ifThenElseDispatch168(counter);
+  } else if (base is Sub169) {
+    base.ifThenElseDispatch169(counter);
+  } else if (base is Sub170) {
+    base.ifThenElseDispatch170(counter);
+  } else if (base is Sub171) {
+    base.ifThenElseDispatch171(counter);
+  } else if (base is Sub172) {
+    base.ifThenElseDispatch172(counter);
+  } else if (base is Sub173) {
+    base.ifThenElseDispatch173(counter);
+  } else if (base is Sub174) {
+    base.ifThenElseDispatch174(counter);
+  } else if (base is Sub175) {
+    base.ifThenElseDispatch175(counter);
+  } else if (base is Sub176) {
+    base.ifThenElseDispatch176(counter);
+  } else if (base is Sub177) {
+    base.ifThenElseDispatch177(counter);
+  } else if (base is Sub178) {
+    base.ifThenElseDispatch178(counter);
+  } else if (base is Sub179) {
+    base.ifThenElseDispatch179(counter);
+  } else if (base is Sub180) {
+    base.ifThenElseDispatch180(counter);
+  } else if (base is Sub181) {
+    base.ifThenElseDispatch181(counter);
+  } else if (base is Sub182) {
+    base.ifThenElseDispatch182(counter);
+  } else if (base is Sub183) {
+    base.ifThenElseDispatch183(counter);
+  } else if (base is Sub184) {
+    base.ifThenElseDispatch184(counter);
+  } else if (base is Sub185) {
+    base.ifThenElseDispatch185(counter);
+  } else if (base is Sub186) {
+    base.ifThenElseDispatch186(counter);
+  } else if (base is Sub187) {
+    base.ifThenElseDispatch187(counter);
+  } else if (base is Sub188) {
+    base.ifThenElseDispatch188(counter);
+  } else if (base is Sub189) {
+    base.ifThenElseDispatch189(counter);
+  } else if (base is Sub190) {
+    base.ifThenElseDispatch190(counter);
+  } else if (base is Sub191) {
+    base.ifThenElseDispatch191(counter);
+  } else if (base is Sub192) {
+    base.ifThenElseDispatch192(counter);
+  } else if (base is Sub193) {
+    base.ifThenElseDispatch193(counter);
+  } else if (base is Sub194) {
+    base.ifThenElseDispatch194(counter);
+  } else if (base is Sub195) {
+    base.ifThenElseDispatch195(counter);
+  } else if (base is Sub196) {
+    base.ifThenElseDispatch196(counter);
+  } else if (base is Sub197) {
+    base.ifThenElseDispatch197(counter);
+  } else if (base is Sub198) {
+    base.ifThenElseDispatch198(counter);
+  } else if (base is Sub199) {
+    base.ifThenElseDispatch199(counter);
+  } else if (base is Sub200) {
+    base.ifThenElseDispatch200(counter);
+  } else if (base is Sub201) {
+    base.ifThenElseDispatch201(counter);
+  } else if (base is Sub202) {
+    base.ifThenElseDispatch202(counter);
+  } else if (base is Sub203) {
+    base.ifThenElseDispatch203(counter);
+  } else if (base is Sub204) {
+    base.ifThenElseDispatch204(counter);
+  } else if (base is Sub205) {
+    base.ifThenElseDispatch205(counter);
+  } else if (base is Sub206) {
+    base.ifThenElseDispatch206(counter);
+  } else if (base is Sub207) {
+    base.ifThenElseDispatch207(counter);
+  } else if (base is Sub208) {
+    base.ifThenElseDispatch208(counter);
+  } else if (base is Sub209) {
+    base.ifThenElseDispatch209(counter);
+  } else if (base is Sub210) {
+    base.ifThenElseDispatch210(counter);
+  } else if (base is Sub211) {
+    base.ifThenElseDispatch211(counter);
+  } else if (base is Sub212) {
+    base.ifThenElseDispatch212(counter);
+  } else if (base is Sub213) {
+    base.ifThenElseDispatch213(counter);
+  } else if (base is Sub214) {
+    base.ifThenElseDispatch214(counter);
+  } else if (base is Sub215) {
+    base.ifThenElseDispatch215(counter);
+  } else if (base is Sub216) {
+    base.ifThenElseDispatch216(counter);
+  } else if (base is Sub217) {
+    base.ifThenElseDispatch217(counter);
+  } else if (base is Sub218) {
+    base.ifThenElseDispatch218(counter);
+  } else if (base is Sub219) {
+    base.ifThenElseDispatch219(counter);
+  } else if (base is Sub220) {
+    base.ifThenElseDispatch220(counter);
+  } else if (base is Sub221) {
+    base.ifThenElseDispatch221(counter);
+  } else if (base is Sub222) {
+    base.ifThenElseDispatch222(counter);
+  } else if (base is Sub223) {
+    base.ifThenElseDispatch223(counter);
+  } else if (base is Sub224) {
+    base.ifThenElseDispatch224(counter);
+  } else if (base is Sub225) {
+    base.ifThenElseDispatch225(counter);
+  } else if (base is Sub226) {
+    base.ifThenElseDispatch226(counter);
+  } else if (base is Sub227) {
+    base.ifThenElseDispatch227(counter);
+  } else if (base is Sub228) {
+    base.ifThenElseDispatch228(counter);
+  } else if (base is Sub229) {
+    base.ifThenElseDispatch229(counter);
+  } else if (base is Sub230) {
+    base.ifThenElseDispatch230(counter);
+  } else if (base is Sub231) {
+    base.ifThenElseDispatch231(counter);
+  } else if (base is Sub232) {
+    base.ifThenElseDispatch232(counter);
+  } else if (base is Sub233) {
+    base.ifThenElseDispatch233(counter);
+  } else if (base is Sub234) {
+    base.ifThenElseDispatch234(counter);
+  } else if (base is Sub235) {
+    base.ifThenElseDispatch235(counter);
+  } else if (base is Sub236) {
+    base.ifThenElseDispatch236(counter);
+  } else if (base is Sub237) {
+    base.ifThenElseDispatch237(counter);
+  } else if (base is Sub238) {
+    base.ifThenElseDispatch238(counter);
+  } else if (base is Sub239) {
+    base.ifThenElseDispatch239(counter);
+  } else if (base is Sub240) {
+    base.ifThenElseDispatch240(counter);
+  } else if (base is Sub241) {
+    base.ifThenElseDispatch241(counter);
+  } else if (base is Sub242) {
+    base.ifThenElseDispatch242(counter);
+  } else if (base is Sub243) {
+    base.ifThenElseDispatch243(counter);
+  } else if (base is Sub244) {
+    base.ifThenElseDispatch244(counter);
+  } else if (base is Sub245) {
+    base.ifThenElseDispatch245(counter);
+  } else if (base is Sub246) {
+    base.ifThenElseDispatch246(counter);
+  } else if (base is Sub247) {
+    base.ifThenElseDispatch247(counter);
+  } else if (base is Sub248) {
+    base.ifThenElseDispatch248(counter);
+  } else if (base is Sub249) {
+    base.ifThenElseDispatch249(counter);
+  } else if (base is Sub250) {
+    base.ifThenElseDispatch250(counter);
+  } else if (base is Sub251) {
+    base.ifThenElseDispatch251(counter);
+  } else if (base is Sub252) {
+    base.ifThenElseDispatch252(counter);
+  } else if (base is Sub253) {
+    base.ifThenElseDispatch253(counter);
+  } else if (base is Sub254) {
+    base.ifThenElseDispatch254(counter);
+  } else if (base is Sub255) {
+    base.ifThenElseDispatch255(counter);
+  }
+}
+
+const Visitor256<void, Counter> visitor = CounterVisitor256();
+
+void incByVisitorDispatch256(Base256 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor256<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+  R visitSub48(Sub48 sub, A arg);
+  R visitSub49(Sub49 sub, A arg);
+  R visitSub50(Sub50 sub, A arg);
+  R visitSub51(Sub51 sub, A arg);
+  R visitSub52(Sub52 sub, A arg);
+  R visitSub53(Sub53 sub, A arg);
+  R visitSub54(Sub54 sub, A arg);
+  R visitSub55(Sub55 sub, A arg);
+  R visitSub56(Sub56 sub, A arg);
+  R visitSub57(Sub57 sub, A arg);
+  R visitSub58(Sub58 sub, A arg);
+  R visitSub59(Sub59 sub, A arg);
+  R visitSub60(Sub60 sub, A arg);
+  R visitSub61(Sub61 sub, A arg);
+  R visitSub62(Sub62 sub, A arg);
+  R visitSub63(Sub63 sub, A arg);
+  R visitSub64(Sub64 sub, A arg);
+  R visitSub65(Sub65 sub, A arg);
+  R visitSub66(Sub66 sub, A arg);
+  R visitSub67(Sub67 sub, A arg);
+  R visitSub68(Sub68 sub, A arg);
+  R visitSub69(Sub69 sub, A arg);
+  R visitSub70(Sub70 sub, A arg);
+  R visitSub71(Sub71 sub, A arg);
+  R visitSub72(Sub72 sub, A arg);
+  R visitSub73(Sub73 sub, A arg);
+  R visitSub74(Sub74 sub, A arg);
+  R visitSub75(Sub75 sub, A arg);
+  R visitSub76(Sub76 sub, A arg);
+  R visitSub77(Sub77 sub, A arg);
+  R visitSub78(Sub78 sub, A arg);
+  R visitSub79(Sub79 sub, A arg);
+  R visitSub80(Sub80 sub, A arg);
+  R visitSub81(Sub81 sub, A arg);
+  R visitSub82(Sub82 sub, A arg);
+  R visitSub83(Sub83 sub, A arg);
+  R visitSub84(Sub84 sub, A arg);
+  R visitSub85(Sub85 sub, A arg);
+  R visitSub86(Sub86 sub, A arg);
+  R visitSub87(Sub87 sub, A arg);
+  R visitSub88(Sub88 sub, A arg);
+  R visitSub89(Sub89 sub, A arg);
+  R visitSub90(Sub90 sub, A arg);
+  R visitSub91(Sub91 sub, A arg);
+  R visitSub92(Sub92 sub, A arg);
+  R visitSub93(Sub93 sub, A arg);
+  R visitSub94(Sub94 sub, A arg);
+  R visitSub95(Sub95 sub, A arg);
+  R visitSub96(Sub96 sub, A arg);
+  R visitSub97(Sub97 sub, A arg);
+  R visitSub98(Sub98 sub, A arg);
+  R visitSub99(Sub99 sub, A arg);
+  R visitSub100(Sub100 sub, A arg);
+  R visitSub101(Sub101 sub, A arg);
+  R visitSub102(Sub102 sub, A arg);
+  R visitSub103(Sub103 sub, A arg);
+  R visitSub104(Sub104 sub, A arg);
+  R visitSub105(Sub105 sub, A arg);
+  R visitSub106(Sub106 sub, A arg);
+  R visitSub107(Sub107 sub, A arg);
+  R visitSub108(Sub108 sub, A arg);
+  R visitSub109(Sub109 sub, A arg);
+  R visitSub110(Sub110 sub, A arg);
+  R visitSub111(Sub111 sub, A arg);
+  R visitSub112(Sub112 sub, A arg);
+  R visitSub113(Sub113 sub, A arg);
+  R visitSub114(Sub114 sub, A arg);
+  R visitSub115(Sub115 sub, A arg);
+  R visitSub116(Sub116 sub, A arg);
+  R visitSub117(Sub117 sub, A arg);
+  R visitSub118(Sub118 sub, A arg);
+  R visitSub119(Sub119 sub, A arg);
+  R visitSub120(Sub120 sub, A arg);
+  R visitSub121(Sub121 sub, A arg);
+  R visitSub122(Sub122 sub, A arg);
+  R visitSub123(Sub123 sub, A arg);
+  R visitSub124(Sub124 sub, A arg);
+  R visitSub125(Sub125 sub, A arg);
+  R visitSub126(Sub126 sub, A arg);
+  R visitSub127(Sub127 sub, A arg);
+  R visitSub128(Sub128 sub, A arg);
+  R visitSub129(Sub129 sub, A arg);
+  R visitSub130(Sub130 sub, A arg);
+  R visitSub131(Sub131 sub, A arg);
+  R visitSub132(Sub132 sub, A arg);
+  R visitSub133(Sub133 sub, A arg);
+  R visitSub134(Sub134 sub, A arg);
+  R visitSub135(Sub135 sub, A arg);
+  R visitSub136(Sub136 sub, A arg);
+  R visitSub137(Sub137 sub, A arg);
+  R visitSub138(Sub138 sub, A arg);
+  R visitSub139(Sub139 sub, A arg);
+  R visitSub140(Sub140 sub, A arg);
+  R visitSub141(Sub141 sub, A arg);
+  R visitSub142(Sub142 sub, A arg);
+  R visitSub143(Sub143 sub, A arg);
+  R visitSub144(Sub144 sub, A arg);
+  R visitSub145(Sub145 sub, A arg);
+  R visitSub146(Sub146 sub, A arg);
+  R visitSub147(Sub147 sub, A arg);
+  R visitSub148(Sub148 sub, A arg);
+  R visitSub149(Sub149 sub, A arg);
+  R visitSub150(Sub150 sub, A arg);
+  R visitSub151(Sub151 sub, A arg);
+  R visitSub152(Sub152 sub, A arg);
+  R visitSub153(Sub153 sub, A arg);
+  R visitSub154(Sub154 sub, A arg);
+  R visitSub155(Sub155 sub, A arg);
+  R visitSub156(Sub156 sub, A arg);
+  R visitSub157(Sub157 sub, A arg);
+  R visitSub158(Sub158 sub, A arg);
+  R visitSub159(Sub159 sub, A arg);
+  R visitSub160(Sub160 sub, A arg);
+  R visitSub161(Sub161 sub, A arg);
+  R visitSub162(Sub162 sub, A arg);
+  R visitSub163(Sub163 sub, A arg);
+  R visitSub164(Sub164 sub, A arg);
+  R visitSub165(Sub165 sub, A arg);
+  R visitSub166(Sub166 sub, A arg);
+  R visitSub167(Sub167 sub, A arg);
+  R visitSub168(Sub168 sub, A arg);
+  R visitSub169(Sub169 sub, A arg);
+  R visitSub170(Sub170 sub, A arg);
+  R visitSub171(Sub171 sub, A arg);
+  R visitSub172(Sub172 sub, A arg);
+  R visitSub173(Sub173 sub, A arg);
+  R visitSub174(Sub174 sub, A arg);
+  R visitSub175(Sub175 sub, A arg);
+  R visitSub176(Sub176 sub, A arg);
+  R visitSub177(Sub177 sub, A arg);
+  R visitSub178(Sub178 sub, A arg);
+  R visitSub179(Sub179 sub, A arg);
+  R visitSub180(Sub180 sub, A arg);
+  R visitSub181(Sub181 sub, A arg);
+  R visitSub182(Sub182 sub, A arg);
+  R visitSub183(Sub183 sub, A arg);
+  R visitSub184(Sub184 sub, A arg);
+  R visitSub185(Sub185 sub, A arg);
+  R visitSub186(Sub186 sub, A arg);
+  R visitSub187(Sub187 sub, A arg);
+  R visitSub188(Sub188 sub, A arg);
+  R visitSub189(Sub189 sub, A arg);
+  R visitSub190(Sub190 sub, A arg);
+  R visitSub191(Sub191 sub, A arg);
+  R visitSub192(Sub192 sub, A arg);
+  R visitSub193(Sub193 sub, A arg);
+  R visitSub194(Sub194 sub, A arg);
+  R visitSub195(Sub195 sub, A arg);
+  R visitSub196(Sub196 sub, A arg);
+  R visitSub197(Sub197 sub, A arg);
+  R visitSub198(Sub198 sub, A arg);
+  R visitSub199(Sub199 sub, A arg);
+  R visitSub200(Sub200 sub, A arg);
+  R visitSub201(Sub201 sub, A arg);
+  R visitSub202(Sub202 sub, A arg);
+  R visitSub203(Sub203 sub, A arg);
+  R visitSub204(Sub204 sub, A arg);
+  R visitSub205(Sub205 sub, A arg);
+  R visitSub206(Sub206 sub, A arg);
+  R visitSub207(Sub207 sub, A arg);
+  R visitSub208(Sub208 sub, A arg);
+  R visitSub209(Sub209 sub, A arg);
+  R visitSub210(Sub210 sub, A arg);
+  R visitSub211(Sub211 sub, A arg);
+  R visitSub212(Sub212 sub, A arg);
+  R visitSub213(Sub213 sub, A arg);
+  R visitSub214(Sub214 sub, A arg);
+  R visitSub215(Sub215 sub, A arg);
+  R visitSub216(Sub216 sub, A arg);
+  R visitSub217(Sub217 sub, A arg);
+  R visitSub218(Sub218 sub, A arg);
+  R visitSub219(Sub219 sub, A arg);
+  R visitSub220(Sub220 sub, A arg);
+  R visitSub221(Sub221 sub, A arg);
+  R visitSub222(Sub222 sub, A arg);
+  R visitSub223(Sub223 sub, A arg);
+  R visitSub224(Sub224 sub, A arg);
+  R visitSub225(Sub225 sub, A arg);
+  R visitSub226(Sub226 sub, A arg);
+  R visitSub227(Sub227 sub, A arg);
+  R visitSub228(Sub228 sub, A arg);
+  R visitSub229(Sub229 sub, A arg);
+  R visitSub230(Sub230 sub, A arg);
+  R visitSub231(Sub231 sub, A arg);
+  R visitSub232(Sub232 sub, A arg);
+  R visitSub233(Sub233 sub, A arg);
+  R visitSub234(Sub234 sub, A arg);
+  R visitSub235(Sub235 sub, A arg);
+  R visitSub236(Sub236 sub, A arg);
+  R visitSub237(Sub237 sub, A arg);
+  R visitSub238(Sub238 sub, A arg);
+  R visitSub239(Sub239 sub, A arg);
+  R visitSub240(Sub240 sub, A arg);
+  R visitSub241(Sub241 sub, A arg);
+  R visitSub242(Sub242 sub, A arg);
+  R visitSub243(Sub243 sub, A arg);
+  R visitSub244(Sub244 sub, A arg);
+  R visitSub245(Sub245 sub, A arg);
+  R visitSub246(Sub246 sub, A arg);
+  R visitSub247(Sub247 sub, A arg);
+  R visitSub248(Sub248 sub, A arg);
+  R visitSub249(Sub249 sub, A arg);
+  R visitSub250(Sub250 sub, A arg);
+  R visitSub251(Sub251 sub, A arg);
+  R visitSub252(Sub252 sub, A arg);
+  R visitSub253(Sub253 sub, A arg);
+  R visitSub254(Sub254 sub, A arg);
+  R visitSub255(Sub255 sub, A arg);
+}
+
+class CounterVisitor256 implements Visitor256<void, Counter> {
+  const CounterVisitor256();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+
+  @override
+  void visitSub48(Sub48 sub, Counter counter) {
+    sub.visitorDispatch48(counter);
+  }
+
+  @override
+  void visitSub49(Sub49 sub, Counter counter) {
+    sub.visitorDispatch49(counter);
+  }
+
+  @override
+  void visitSub50(Sub50 sub, Counter counter) {
+    sub.visitorDispatch50(counter);
+  }
+
+  @override
+  void visitSub51(Sub51 sub, Counter counter) {
+    sub.visitorDispatch51(counter);
+  }
+
+  @override
+  void visitSub52(Sub52 sub, Counter counter) {
+    sub.visitorDispatch52(counter);
+  }
+
+  @override
+  void visitSub53(Sub53 sub, Counter counter) {
+    sub.visitorDispatch53(counter);
+  }
+
+  @override
+  void visitSub54(Sub54 sub, Counter counter) {
+    sub.visitorDispatch54(counter);
+  }
+
+  @override
+  void visitSub55(Sub55 sub, Counter counter) {
+    sub.visitorDispatch55(counter);
+  }
+
+  @override
+  void visitSub56(Sub56 sub, Counter counter) {
+    sub.visitorDispatch56(counter);
+  }
+
+  @override
+  void visitSub57(Sub57 sub, Counter counter) {
+    sub.visitorDispatch57(counter);
+  }
+
+  @override
+  void visitSub58(Sub58 sub, Counter counter) {
+    sub.visitorDispatch58(counter);
+  }
+
+  @override
+  void visitSub59(Sub59 sub, Counter counter) {
+    sub.visitorDispatch59(counter);
+  }
+
+  @override
+  void visitSub60(Sub60 sub, Counter counter) {
+    sub.visitorDispatch60(counter);
+  }
+
+  @override
+  void visitSub61(Sub61 sub, Counter counter) {
+    sub.visitorDispatch61(counter);
+  }
+
+  @override
+  void visitSub62(Sub62 sub, Counter counter) {
+    sub.visitorDispatch62(counter);
+  }
+
+  @override
+  void visitSub63(Sub63 sub, Counter counter) {
+    sub.visitorDispatch63(counter);
+  }
+
+  @override
+  void visitSub64(Sub64 sub, Counter counter) {
+    sub.visitorDispatch64(counter);
+  }
+
+  @override
+  void visitSub65(Sub65 sub, Counter counter) {
+    sub.visitorDispatch65(counter);
+  }
+
+  @override
+  void visitSub66(Sub66 sub, Counter counter) {
+    sub.visitorDispatch66(counter);
+  }
+
+  @override
+  void visitSub67(Sub67 sub, Counter counter) {
+    sub.visitorDispatch67(counter);
+  }
+
+  @override
+  void visitSub68(Sub68 sub, Counter counter) {
+    sub.visitorDispatch68(counter);
+  }
+
+  @override
+  void visitSub69(Sub69 sub, Counter counter) {
+    sub.visitorDispatch69(counter);
+  }
+
+  @override
+  void visitSub70(Sub70 sub, Counter counter) {
+    sub.visitorDispatch70(counter);
+  }
+
+  @override
+  void visitSub71(Sub71 sub, Counter counter) {
+    sub.visitorDispatch71(counter);
+  }
+
+  @override
+  void visitSub72(Sub72 sub, Counter counter) {
+    sub.visitorDispatch72(counter);
+  }
+
+  @override
+  void visitSub73(Sub73 sub, Counter counter) {
+    sub.visitorDispatch73(counter);
+  }
+
+  @override
+  void visitSub74(Sub74 sub, Counter counter) {
+    sub.visitorDispatch74(counter);
+  }
+
+  @override
+  void visitSub75(Sub75 sub, Counter counter) {
+    sub.visitorDispatch75(counter);
+  }
+
+  @override
+  void visitSub76(Sub76 sub, Counter counter) {
+    sub.visitorDispatch76(counter);
+  }
+
+  @override
+  void visitSub77(Sub77 sub, Counter counter) {
+    sub.visitorDispatch77(counter);
+  }
+
+  @override
+  void visitSub78(Sub78 sub, Counter counter) {
+    sub.visitorDispatch78(counter);
+  }
+
+  @override
+  void visitSub79(Sub79 sub, Counter counter) {
+    sub.visitorDispatch79(counter);
+  }
+
+  @override
+  void visitSub80(Sub80 sub, Counter counter) {
+    sub.visitorDispatch80(counter);
+  }
+
+  @override
+  void visitSub81(Sub81 sub, Counter counter) {
+    sub.visitorDispatch81(counter);
+  }
+
+  @override
+  void visitSub82(Sub82 sub, Counter counter) {
+    sub.visitorDispatch82(counter);
+  }
+
+  @override
+  void visitSub83(Sub83 sub, Counter counter) {
+    sub.visitorDispatch83(counter);
+  }
+
+  @override
+  void visitSub84(Sub84 sub, Counter counter) {
+    sub.visitorDispatch84(counter);
+  }
+
+  @override
+  void visitSub85(Sub85 sub, Counter counter) {
+    sub.visitorDispatch85(counter);
+  }
+
+  @override
+  void visitSub86(Sub86 sub, Counter counter) {
+    sub.visitorDispatch86(counter);
+  }
+
+  @override
+  void visitSub87(Sub87 sub, Counter counter) {
+    sub.visitorDispatch87(counter);
+  }
+
+  @override
+  void visitSub88(Sub88 sub, Counter counter) {
+    sub.visitorDispatch88(counter);
+  }
+
+  @override
+  void visitSub89(Sub89 sub, Counter counter) {
+    sub.visitorDispatch89(counter);
+  }
+
+  @override
+  void visitSub90(Sub90 sub, Counter counter) {
+    sub.visitorDispatch90(counter);
+  }
+
+  @override
+  void visitSub91(Sub91 sub, Counter counter) {
+    sub.visitorDispatch91(counter);
+  }
+
+  @override
+  void visitSub92(Sub92 sub, Counter counter) {
+    sub.visitorDispatch92(counter);
+  }
+
+  @override
+  void visitSub93(Sub93 sub, Counter counter) {
+    sub.visitorDispatch93(counter);
+  }
+
+  @override
+  void visitSub94(Sub94 sub, Counter counter) {
+    sub.visitorDispatch94(counter);
+  }
+
+  @override
+  void visitSub95(Sub95 sub, Counter counter) {
+    sub.visitorDispatch95(counter);
+  }
+
+  @override
+  void visitSub96(Sub96 sub, Counter counter) {
+    sub.visitorDispatch96(counter);
+  }
+
+  @override
+  void visitSub97(Sub97 sub, Counter counter) {
+    sub.visitorDispatch97(counter);
+  }
+
+  @override
+  void visitSub98(Sub98 sub, Counter counter) {
+    sub.visitorDispatch98(counter);
+  }
+
+  @override
+  void visitSub99(Sub99 sub, Counter counter) {
+    sub.visitorDispatch99(counter);
+  }
+
+  @override
+  void visitSub100(Sub100 sub, Counter counter) {
+    sub.visitorDispatch100(counter);
+  }
+
+  @override
+  void visitSub101(Sub101 sub, Counter counter) {
+    sub.visitorDispatch101(counter);
+  }
+
+  @override
+  void visitSub102(Sub102 sub, Counter counter) {
+    sub.visitorDispatch102(counter);
+  }
+
+  @override
+  void visitSub103(Sub103 sub, Counter counter) {
+    sub.visitorDispatch103(counter);
+  }
+
+  @override
+  void visitSub104(Sub104 sub, Counter counter) {
+    sub.visitorDispatch104(counter);
+  }
+
+  @override
+  void visitSub105(Sub105 sub, Counter counter) {
+    sub.visitorDispatch105(counter);
+  }
+
+  @override
+  void visitSub106(Sub106 sub, Counter counter) {
+    sub.visitorDispatch106(counter);
+  }
+
+  @override
+  void visitSub107(Sub107 sub, Counter counter) {
+    sub.visitorDispatch107(counter);
+  }
+
+  @override
+  void visitSub108(Sub108 sub, Counter counter) {
+    sub.visitorDispatch108(counter);
+  }
+
+  @override
+  void visitSub109(Sub109 sub, Counter counter) {
+    sub.visitorDispatch109(counter);
+  }
+
+  @override
+  void visitSub110(Sub110 sub, Counter counter) {
+    sub.visitorDispatch110(counter);
+  }
+
+  @override
+  void visitSub111(Sub111 sub, Counter counter) {
+    sub.visitorDispatch111(counter);
+  }
+
+  @override
+  void visitSub112(Sub112 sub, Counter counter) {
+    sub.visitorDispatch112(counter);
+  }
+
+  @override
+  void visitSub113(Sub113 sub, Counter counter) {
+    sub.visitorDispatch113(counter);
+  }
+
+  @override
+  void visitSub114(Sub114 sub, Counter counter) {
+    sub.visitorDispatch114(counter);
+  }
+
+  @override
+  void visitSub115(Sub115 sub, Counter counter) {
+    sub.visitorDispatch115(counter);
+  }
+
+  @override
+  void visitSub116(Sub116 sub, Counter counter) {
+    sub.visitorDispatch116(counter);
+  }
+
+  @override
+  void visitSub117(Sub117 sub, Counter counter) {
+    sub.visitorDispatch117(counter);
+  }
+
+  @override
+  void visitSub118(Sub118 sub, Counter counter) {
+    sub.visitorDispatch118(counter);
+  }
+
+  @override
+  void visitSub119(Sub119 sub, Counter counter) {
+    sub.visitorDispatch119(counter);
+  }
+
+  @override
+  void visitSub120(Sub120 sub, Counter counter) {
+    sub.visitorDispatch120(counter);
+  }
+
+  @override
+  void visitSub121(Sub121 sub, Counter counter) {
+    sub.visitorDispatch121(counter);
+  }
+
+  @override
+  void visitSub122(Sub122 sub, Counter counter) {
+    sub.visitorDispatch122(counter);
+  }
+
+  @override
+  void visitSub123(Sub123 sub, Counter counter) {
+    sub.visitorDispatch123(counter);
+  }
+
+  @override
+  void visitSub124(Sub124 sub, Counter counter) {
+    sub.visitorDispatch124(counter);
+  }
+
+  @override
+  void visitSub125(Sub125 sub, Counter counter) {
+    sub.visitorDispatch125(counter);
+  }
+
+  @override
+  void visitSub126(Sub126 sub, Counter counter) {
+    sub.visitorDispatch126(counter);
+  }
+
+  @override
+  void visitSub127(Sub127 sub, Counter counter) {
+    sub.visitorDispatch127(counter);
+  }
+
+  @override
+  void visitSub128(Sub128 sub, Counter counter) {
+    sub.visitorDispatch128(counter);
+  }
+
+  @override
+  void visitSub129(Sub129 sub, Counter counter) {
+    sub.visitorDispatch129(counter);
+  }
+
+  @override
+  void visitSub130(Sub130 sub, Counter counter) {
+    sub.visitorDispatch130(counter);
+  }
+
+  @override
+  void visitSub131(Sub131 sub, Counter counter) {
+    sub.visitorDispatch131(counter);
+  }
+
+  @override
+  void visitSub132(Sub132 sub, Counter counter) {
+    sub.visitorDispatch132(counter);
+  }
+
+  @override
+  void visitSub133(Sub133 sub, Counter counter) {
+    sub.visitorDispatch133(counter);
+  }
+
+  @override
+  void visitSub134(Sub134 sub, Counter counter) {
+    sub.visitorDispatch134(counter);
+  }
+
+  @override
+  void visitSub135(Sub135 sub, Counter counter) {
+    sub.visitorDispatch135(counter);
+  }
+
+  @override
+  void visitSub136(Sub136 sub, Counter counter) {
+    sub.visitorDispatch136(counter);
+  }
+
+  @override
+  void visitSub137(Sub137 sub, Counter counter) {
+    sub.visitorDispatch137(counter);
+  }
+
+  @override
+  void visitSub138(Sub138 sub, Counter counter) {
+    sub.visitorDispatch138(counter);
+  }
+
+  @override
+  void visitSub139(Sub139 sub, Counter counter) {
+    sub.visitorDispatch139(counter);
+  }
+
+  @override
+  void visitSub140(Sub140 sub, Counter counter) {
+    sub.visitorDispatch140(counter);
+  }
+
+  @override
+  void visitSub141(Sub141 sub, Counter counter) {
+    sub.visitorDispatch141(counter);
+  }
+
+  @override
+  void visitSub142(Sub142 sub, Counter counter) {
+    sub.visitorDispatch142(counter);
+  }
+
+  @override
+  void visitSub143(Sub143 sub, Counter counter) {
+    sub.visitorDispatch143(counter);
+  }
+
+  @override
+  void visitSub144(Sub144 sub, Counter counter) {
+    sub.visitorDispatch144(counter);
+  }
+
+  @override
+  void visitSub145(Sub145 sub, Counter counter) {
+    sub.visitorDispatch145(counter);
+  }
+
+  @override
+  void visitSub146(Sub146 sub, Counter counter) {
+    sub.visitorDispatch146(counter);
+  }
+
+  @override
+  void visitSub147(Sub147 sub, Counter counter) {
+    sub.visitorDispatch147(counter);
+  }
+
+  @override
+  void visitSub148(Sub148 sub, Counter counter) {
+    sub.visitorDispatch148(counter);
+  }
+
+  @override
+  void visitSub149(Sub149 sub, Counter counter) {
+    sub.visitorDispatch149(counter);
+  }
+
+  @override
+  void visitSub150(Sub150 sub, Counter counter) {
+    sub.visitorDispatch150(counter);
+  }
+
+  @override
+  void visitSub151(Sub151 sub, Counter counter) {
+    sub.visitorDispatch151(counter);
+  }
+
+  @override
+  void visitSub152(Sub152 sub, Counter counter) {
+    sub.visitorDispatch152(counter);
+  }
+
+  @override
+  void visitSub153(Sub153 sub, Counter counter) {
+    sub.visitorDispatch153(counter);
+  }
+
+  @override
+  void visitSub154(Sub154 sub, Counter counter) {
+    sub.visitorDispatch154(counter);
+  }
+
+  @override
+  void visitSub155(Sub155 sub, Counter counter) {
+    sub.visitorDispatch155(counter);
+  }
+
+  @override
+  void visitSub156(Sub156 sub, Counter counter) {
+    sub.visitorDispatch156(counter);
+  }
+
+  @override
+  void visitSub157(Sub157 sub, Counter counter) {
+    sub.visitorDispatch157(counter);
+  }
+
+  @override
+  void visitSub158(Sub158 sub, Counter counter) {
+    sub.visitorDispatch158(counter);
+  }
+
+  @override
+  void visitSub159(Sub159 sub, Counter counter) {
+    sub.visitorDispatch159(counter);
+  }
+
+  @override
+  void visitSub160(Sub160 sub, Counter counter) {
+    sub.visitorDispatch160(counter);
+  }
+
+  @override
+  void visitSub161(Sub161 sub, Counter counter) {
+    sub.visitorDispatch161(counter);
+  }
+
+  @override
+  void visitSub162(Sub162 sub, Counter counter) {
+    sub.visitorDispatch162(counter);
+  }
+
+  @override
+  void visitSub163(Sub163 sub, Counter counter) {
+    sub.visitorDispatch163(counter);
+  }
+
+  @override
+  void visitSub164(Sub164 sub, Counter counter) {
+    sub.visitorDispatch164(counter);
+  }
+
+  @override
+  void visitSub165(Sub165 sub, Counter counter) {
+    sub.visitorDispatch165(counter);
+  }
+
+  @override
+  void visitSub166(Sub166 sub, Counter counter) {
+    sub.visitorDispatch166(counter);
+  }
+
+  @override
+  void visitSub167(Sub167 sub, Counter counter) {
+    sub.visitorDispatch167(counter);
+  }
+
+  @override
+  void visitSub168(Sub168 sub, Counter counter) {
+    sub.visitorDispatch168(counter);
+  }
+
+  @override
+  void visitSub169(Sub169 sub, Counter counter) {
+    sub.visitorDispatch169(counter);
+  }
+
+  @override
+  void visitSub170(Sub170 sub, Counter counter) {
+    sub.visitorDispatch170(counter);
+  }
+
+  @override
+  void visitSub171(Sub171 sub, Counter counter) {
+    sub.visitorDispatch171(counter);
+  }
+
+  @override
+  void visitSub172(Sub172 sub, Counter counter) {
+    sub.visitorDispatch172(counter);
+  }
+
+  @override
+  void visitSub173(Sub173 sub, Counter counter) {
+    sub.visitorDispatch173(counter);
+  }
+
+  @override
+  void visitSub174(Sub174 sub, Counter counter) {
+    sub.visitorDispatch174(counter);
+  }
+
+  @override
+  void visitSub175(Sub175 sub, Counter counter) {
+    sub.visitorDispatch175(counter);
+  }
+
+  @override
+  void visitSub176(Sub176 sub, Counter counter) {
+    sub.visitorDispatch176(counter);
+  }
+
+  @override
+  void visitSub177(Sub177 sub, Counter counter) {
+    sub.visitorDispatch177(counter);
+  }
+
+  @override
+  void visitSub178(Sub178 sub, Counter counter) {
+    sub.visitorDispatch178(counter);
+  }
+
+  @override
+  void visitSub179(Sub179 sub, Counter counter) {
+    sub.visitorDispatch179(counter);
+  }
+
+  @override
+  void visitSub180(Sub180 sub, Counter counter) {
+    sub.visitorDispatch180(counter);
+  }
+
+  @override
+  void visitSub181(Sub181 sub, Counter counter) {
+    sub.visitorDispatch181(counter);
+  }
+
+  @override
+  void visitSub182(Sub182 sub, Counter counter) {
+    sub.visitorDispatch182(counter);
+  }
+
+  @override
+  void visitSub183(Sub183 sub, Counter counter) {
+    sub.visitorDispatch183(counter);
+  }
+
+  @override
+  void visitSub184(Sub184 sub, Counter counter) {
+    sub.visitorDispatch184(counter);
+  }
+
+  @override
+  void visitSub185(Sub185 sub, Counter counter) {
+    sub.visitorDispatch185(counter);
+  }
+
+  @override
+  void visitSub186(Sub186 sub, Counter counter) {
+    sub.visitorDispatch186(counter);
+  }
+
+  @override
+  void visitSub187(Sub187 sub, Counter counter) {
+    sub.visitorDispatch187(counter);
+  }
+
+  @override
+  void visitSub188(Sub188 sub, Counter counter) {
+    sub.visitorDispatch188(counter);
+  }
+
+  @override
+  void visitSub189(Sub189 sub, Counter counter) {
+    sub.visitorDispatch189(counter);
+  }
+
+  @override
+  void visitSub190(Sub190 sub, Counter counter) {
+    sub.visitorDispatch190(counter);
+  }
+
+  @override
+  void visitSub191(Sub191 sub, Counter counter) {
+    sub.visitorDispatch191(counter);
+  }
+
+  @override
+  void visitSub192(Sub192 sub, Counter counter) {
+    sub.visitorDispatch192(counter);
+  }
+
+  @override
+  void visitSub193(Sub193 sub, Counter counter) {
+    sub.visitorDispatch193(counter);
+  }
+
+  @override
+  void visitSub194(Sub194 sub, Counter counter) {
+    sub.visitorDispatch194(counter);
+  }
+
+  @override
+  void visitSub195(Sub195 sub, Counter counter) {
+    sub.visitorDispatch195(counter);
+  }
+
+  @override
+  void visitSub196(Sub196 sub, Counter counter) {
+    sub.visitorDispatch196(counter);
+  }
+
+  @override
+  void visitSub197(Sub197 sub, Counter counter) {
+    sub.visitorDispatch197(counter);
+  }
+
+  @override
+  void visitSub198(Sub198 sub, Counter counter) {
+    sub.visitorDispatch198(counter);
+  }
+
+  @override
+  void visitSub199(Sub199 sub, Counter counter) {
+    sub.visitorDispatch199(counter);
+  }
+
+  @override
+  void visitSub200(Sub200 sub, Counter counter) {
+    sub.visitorDispatch200(counter);
+  }
+
+  @override
+  void visitSub201(Sub201 sub, Counter counter) {
+    sub.visitorDispatch201(counter);
+  }
+
+  @override
+  void visitSub202(Sub202 sub, Counter counter) {
+    sub.visitorDispatch202(counter);
+  }
+
+  @override
+  void visitSub203(Sub203 sub, Counter counter) {
+    sub.visitorDispatch203(counter);
+  }
+
+  @override
+  void visitSub204(Sub204 sub, Counter counter) {
+    sub.visitorDispatch204(counter);
+  }
+
+  @override
+  void visitSub205(Sub205 sub, Counter counter) {
+    sub.visitorDispatch205(counter);
+  }
+
+  @override
+  void visitSub206(Sub206 sub, Counter counter) {
+    sub.visitorDispatch206(counter);
+  }
+
+  @override
+  void visitSub207(Sub207 sub, Counter counter) {
+    sub.visitorDispatch207(counter);
+  }
+
+  @override
+  void visitSub208(Sub208 sub, Counter counter) {
+    sub.visitorDispatch208(counter);
+  }
+
+  @override
+  void visitSub209(Sub209 sub, Counter counter) {
+    sub.visitorDispatch209(counter);
+  }
+
+  @override
+  void visitSub210(Sub210 sub, Counter counter) {
+    sub.visitorDispatch210(counter);
+  }
+
+  @override
+  void visitSub211(Sub211 sub, Counter counter) {
+    sub.visitorDispatch211(counter);
+  }
+
+  @override
+  void visitSub212(Sub212 sub, Counter counter) {
+    sub.visitorDispatch212(counter);
+  }
+
+  @override
+  void visitSub213(Sub213 sub, Counter counter) {
+    sub.visitorDispatch213(counter);
+  }
+
+  @override
+  void visitSub214(Sub214 sub, Counter counter) {
+    sub.visitorDispatch214(counter);
+  }
+
+  @override
+  void visitSub215(Sub215 sub, Counter counter) {
+    sub.visitorDispatch215(counter);
+  }
+
+  @override
+  void visitSub216(Sub216 sub, Counter counter) {
+    sub.visitorDispatch216(counter);
+  }
+
+  @override
+  void visitSub217(Sub217 sub, Counter counter) {
+    sub.visitorDispatch217(counter);
+  }
+
+  @override
+  void visitSub218(Sub218 sub, Counter counter) {
+    sub.visitorDispatch218(counter);
+  }
+
+  @override
+  void visitSub219(Sub219 sub, Counter counter) {
+    sub.visitorDispatch219(counter);
+  }
+
+  @override
+  void visitSub220(Sub220 sub, Counter counter) {
+    sub.visitorDispatch220(counter);
+  }
+
+  @override
+  void visitSub221(Sub221 sub, Counter counter) {
+    sub.visitorDispatch221(counter);
+  }
+
+  @override
+  void visitSub222(Sub222 sub, Counter counter) {
+    sub.visitorDispatch222(counter);
+  }
+
+  @override
+  void visitSub223(Sub223 sub, Counter counter) {
+    sub.visitorDispatch223(counter);
+  }
+
+  @override
+  void visitSub224(Sub224 sub, Counter counter) {
+    sub.visitorDispatch224(counter);
+  }
+
+  @override
+  void visitSub225(Sub225 sub, Counter counter) {
+    sub.visitorDispatch225(counter);
+  }
+
+  @override
+  void visitSub226(Sub226 sub, Counter counter) {
+    sub.visitorDispatch226(counter);
+  }
+
+  @override
+  void visitSub227(Sub227 sub, Counter counter) {
+    sub.visitorDispatch227(counter);
+  }
+
+  @override
+  void visitSub228(Sub228 sub, Counter counter) {
+    sub.visitorDispatch228(counter);
+  }
+
+  @override
+  void visitSub229(Sub229 sub, Counter counter) {
+    sub.visitorDispatch229(counter);
+  }
+
+  @override
+  void visitSub230(Sub230 sub, Counter counter) {
+    sub.visitorDispatch230(counter);
+  }
+
+  @override
+  void visitSub231(Sub231 sub, Counter counter) {
+    sub.visitorDispatch231(counter);
+  }
+
+  @override
+  void visitSub232(Sub232 sub, Counter counter) {
+    sub.visitorDispatch232(counter);
+  }
+
+  @override
+  void visitSub233(Sub233 sub, Counter counter) {
+    sub.visitorDispatch233(counter);
+  }
+
+  @override
+  void visitSub234(Sub234 sub, Counter counter) {
+    sub.visitorDispatch234(counter);
+  }
+
+  @override
+  void visitSub235(Sub235 sub, Counter counter) {
+    sub.visitorDispatch235(counter);
+  }
+
+  @override
+  void visitSub236(Sub236 sub, Counter counter) {
+    sub.visitorDispatch236(counter);
+  }
+
+  @override
+  void visitSub237(Sub237 sub, Counter counter) {
+    sub.visitorDispatch237(counter);
+  }
+
+  @override
+  void visitSub238(Sub238 sub, Counter counter) {
+    sub.visitorDispatch238(counter);
+  }
+
+  @override
+  void visitSub239(Sub239 sub, Counter counter) {
+    sub.visitorDispatch239(counter);
+  }
+
+  @override
+  void visitSub240(Sub240 sub, Counter counter) {
+    sub.visitorDispatch240(counter);
+  }
+
+  @override
+  void visitSub241(Sub241 sub, Counter counter) {
+    sub.visitorDispatch241(counter);
+  }
+
+  @override
+  void visitSub242(Sub242 sub, Counter counter) {
+    sub.visitorDispatch242(counter);
+  }
+
+  @override
+  void visitSub243(Sub243 sub, Counter counter) {
+    sub.visitorDispatch243(counter);
+  }
+
+  @override
+  void visitSub244(Sub244 sub, Counter counter) {
+    sub.visitorDispatch244(counter);
+  }
+
+  @override
+  void visitSub245(Sub245 sub, Counter counter) {
+    sub.visitorDispatch245(counter);
+  }
+
+  @override
+  void visitSub246(Sub246 sub, Counter counter) {
+    sub.visitorDispatch246(counter);
+  }
+
+  @override
+  void visitSub247(Sub247 sub, Counter counter) {
+    sub.visitorDispatch247(counter);
+  }
+
+  @override
+  void visitSub248(Sub248 sub, Counter counter) {
+    sub.visitorDispatch248(counter);
+  }
+
+  @override
+  void visitSub249(Sub249 sub, Counter counter) {
+    sub.visitorDispatch249(counter);
+  }
+
+  @override
+  void visitSub250(Sub250 sub, Counter counter) {
+    sub.visitorDispatch250(counter);
+  }
+
+  @override
+  void visitSub251(Sub251 sub, Counter counter) {
+    sub.visitorDispatch251(counter);
+  }
+
+  @override
+  void visitSub252(Sub252 sub, Counter counter) {
+    sub.visitorDispatch252(counter);
+  }
+
+  @override
+  void visitSub253(Sub253 sub, Counter counter) {
+    sub.visitorDispatch253(counter);
+  }
+
+  @override
+  void visitSub254(Sub254 sub, Counter counter) {
+    sub.visitorDispatch254(counter);
+  }
+
+  @override
+  void visitSub255(Sub255 sub, Counter counter) {
+    sub.visitorDispatch255(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype3.dart b/pkg/front_end/benchmarks/patterns/generated/datatype3.dart
new file mode 100644
index 0000000..80a3a52
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype3.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base3 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor3<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base3 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor3<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base3 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor3<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base3 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor3<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+List<Base3> createData3() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+  ];
+}
+
+void incByDynamicDispatch3(Base3 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch3(Base3 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  }
+}
+
+const Visitor3<void, Counter> visitor = CounterVisitor3();
+
+void incByVisitorDispatch3(Base3 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor3<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+}
+
+class CounterVisitor3 implements Visitor3<void, Counter> {
+  const CounterVisitor3();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype32.dart b/pkg/front_end/benchmarks/patterns/generated/datatype32.dart
new file mode 100644
index 0000000..02660ac
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype32.dart
@@ -0,0 +1,969 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base32 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor32<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base32 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor32<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+List<Base32> createData32() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+  ];
+}
+
+void incByDynamicDispatch32(Base32 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch32(Base32 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  }
+}
+
+const Visitor32<void, Counter> visitor = CounterVisitor32();
+
+void incByVisitorDispatch32(Base32 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor32<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+}
+
+class CounterVisitor32 implements Visitor32<void, Counter> {
+  const CounterVisitor32();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype4.dart b/pkg/front_end/benchmarks/patterns/generated/datatype4.dart
new file mode 100644
index 0000000..3e93dc2
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype4.dart
@@ -0,0 +1,157 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base4 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor4<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base4 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor4<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base4 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor4<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base4 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor4<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base4 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor4<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+List<Base4> createData4() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+  ];
+}
+
+void incByDynamicDispatch4(Base4 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch4(Base4 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  }
+}
+
+const Visitor4<void, Counter> visitor = CounterVisitor4();
+
+void incByVisitorDispatch4(Base4 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor4<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+}
+
+class CounterVisitor4 implements Visitor4<void, Counter> {
+  const CounterVisitor4();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype48.dart b/pkg/front_end/benchmarks/patterns/generated/datatype48.dart
new file mode 100644
index 0000000..d107aee
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype48.dart
@@ -0,0 +1,1433 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base48 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor48<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base48 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor48<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+List<Base48> createData48() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+  ];
+}
+
+void incByDynamicDispatch48(Base48 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch48(Base48 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  }
+}
+
+const Visitor48<void, Counter> visitor = CounterVisitor48();
+
+void incByVisitorDispatch48(Base48 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor48<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+}
+
+class CounterVisitor48 implements Visitor48<void, Counter> {
+  const CounterVisitor48();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype5.dart b/pkg/front_end/benchmarks/patterns/generated/datatype5.dart
new file mode 100644
index 0000000..6a75a54
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype5.dart
@@ -0,0 +1,186 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base5 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor5<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base5 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor5<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base5 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor5<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base5 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor5<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base5 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor5<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base5 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor5<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+List<Base5> createData5() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+  ];
+}
+
+void incByDynamicDispatch5(Base5 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch5(Base5 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  }
+}
+
+const Visitor5<void, Counter> visitor = CounterVisitor5();
+
+void incByVisitorDispatch5(Base5 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor5<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+}
+
+class CounterVisitor5 implements Visitor5<void, Counter> {
+  const CounterVisitor5();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype6.dart b/pkg/front_end/benchmarks/patterns/generated/datatype6.dart
new file mode 100644
index 0000000..4530c93
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype6.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base6 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor6<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base6 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor6<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+List<Base6> createData6() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+  ];
+}
+
+void incByDynamicDispatch6(Base6 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch6(Base6 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  }
+}
+
+const Visitor6<void, Counter> visitor = CounterVisitor6();
+
+void incByVisitorDispatch6(Base6 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor6<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+}
+
+class CounterVisitor6 implements Visitor6<void, Counter> {
+  const CounterVisitor6();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype64.dart b/pkg/front_end/benchmarks/patterns/generated/datatype64.dart
new file mode 100644
index 0000000..ef6d9cb
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype64.dart
@@ -0,0 +1,1897 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base64 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor64<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+class Sub48 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub48(this, arg);
+  }
+}
+
+class Sub49 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub49(this, arg);
+  }
+}
+
+class Sub50 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub50(this, arg);
+  }
+}
+
+class Sub51 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub51(this, arg);
+  }
+}
+
+class Sub52 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub52(this, arg);
+  }
+}
+
+class Sub53 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub53(this, arg);
+  }
+}
+
+class Sub54 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub54(this, arg);
+  }
+}
+
+class Sub55 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub55(this, arg);
+  }
+}
+
+class Sub56 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub56(this, arg);
+  }
+}
+
+class Sub57 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub57(this, arg);
+  }
+}
+
+class Sub58 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub58(this, arg);
+  }
+}
+
+class Sub59 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub59(this, arg);
+  }
+}
+
+class Sub60 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub60(this, arg);
+  }
+}
+
+class Sub61 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub61(this, arg);
+  }
+}
+
+class Sub62 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub62(this, arg);
+  }
+}
+
+class Sub63 extends Base64 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor64<R, A> visitor, A arg) {
+    return visitor.visitSub63(this, arg);
+  }
+}
+
+List<Base64> createData64() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+    Sub48(),
+    Sub49(),
+    Sub50(),
+    Sub51(),
+    Sub52(),
+    Sub53(),
+    Sub54(),
+    Sub55(),
+    Sub56(),
+    Sub57(),
+    Sub58(),
+    Sub59(),
+    Sub60(),
+    Sub61(),
+    Sub62(),
+    Sub63(),
+  ];
+}
+
+void incByDynamicDispatch64(Base64 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch64(Base64 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  } else if (base is Sub48) {
+    base.ifThenElseDispatch48(counter);
+  } else if (base is Sub49) {
+    base.ifThenElseDispatch49(counter);
+  } else if (base is Sub50) {
+    base.ifThenElseDispatch50(counter);
+  } else if (base is Sub51) {
+    base.ifThenElseDispatch51(counter);
+  } else if (base is Sub52) {
+    base.ifThenElseDispatch52(counter);
+  } else if (base is Sub53) {
+    base.ifThenElseDispatch53(counter);
+  } else if (base is Sub54) {
+    base.ifThenElseDispatch54(counter);
+  } else if (base is Sub55) {
+    base.ifThenElseDispatch55(counter);
+  } else if (base is Sub56) {
+    base.ifThenElseDispatch56(counter);
+  } else if (base is Sub57) {
+    base.ifThenElseDispatch57(counter);
+  } else if (base is Sub58) {
+    base.ifThenElseDispatch58(counter);
+  } else if (base is Sub59) {
+    base.ifThenElseDispatch59(counter);
+  } else if (base is Sub60) {
+    base.ifThenElseDispatch60(counter);
+  } else if (base is Sub61) {
+    base.ifThenElseDispatch61(counter);
+  } else if (base is Sub62) {
+    base.ifThenElseDispatch62(counter);
+  } else if (base is Sub63) {
+    base.ifThenElseDispatch63(counter);
+  }
+}
+
+const Visitor64<void, Counter> visitor = CounterVisitor64();
+
+void incByVisitorDispatch64(Base64 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor64<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+  R visitSub48(Sub48 sub, A arg);
+  R visitSub49(Sub49 sub, A arg);
+  R visitSub50(Sub50 sub, A arg);
+  R visitSub51(Sub51 sub, A arg);
+  R visitSub52(Sub52 sub, A arg);
+  R visitSub53(Sub53 sub, A arg);
+  R visitSub54(Sub54 sub, A arg);
+  R visitSub55(Sub55 sub, A arg);
+  R visitSub56(Sub56 sub, A arg);
+  R visitSub57(Sub57 sub, A arg);
+  R visitSub58(Sub58 sub, A arg);
+  R visitSub59(Sub59 sub, A arg);
+  R visitSub60(Sub60 sub, A arg);
+  R visitSub61(Sub61 sub, A arg);
+  R visitSub62(Sub62 sub, A arg);
+  R visitSub63(Sub63 sub, A arg);
+}
+
+class CounterVisitor64 implements Visitor64<void, Counter> {
+  const CounterVisitor64();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+
+  @override
+  void visitSub48(Sub48 sub, Counter counter) {
+    sub.visitorDispatch48(counter);
+  }
+
+  @override
+  void visitSub49(Sub49 sub, Counter counter) {
+    sub.visitorDispatch49(counter);
+  }
+
+  @override
+  void visitSub50(Sub50 sub, Counter counter) {
+    sub.visitorDispatch50(counter);
+  }
+
+  @override
+  void visitSub51(Sub51 sub, Counter counter) {
+    sub.visitorDispatch51(counter);
+  }
+
+  @override
+  void visitSub52(Sub52 sub, Counter counter) {
+    sub.visitorDispatch52(counter);
+  }
+
+  @override
+  void visitSub53(Sub53 sub, Counter counter) {
+    sub.visitorDispatch53(counter);
+  }
+
+  @override
+  void visitSub54(Sub54 sub, Counter counter) {
+    sub.visitorDispatch54(counter);
+  }
+
+  @override
+  void visitSub55(Sub55 sub, Counter counter) {
+    sub.visitorDispatch55(counter);
+  }
+
+  @override
+  void visitSub56(Sub56 sub, Counter counter) {
+    sub.visitorDispatch56(counter);
+  }
+
+  @override
+  void visitSub57(Sub57 sub, Counter counter) {
+    sub.visitorDispatch57(counter);
+  }
+
+  @override
+  void visitSub58(Sub58 sub, Counter counter) {
+    sub.visitorDispatch58(counter);
+  }
+
+  @override
+  void visitSub59(Sub59 sub, Counter counter) {
+    sub.visitorDispatch59(counter);
+  }
+
+  @override
+  void visitSub60(Sub60 sub, Counter counter) {
+    sub.visitorDispatch60(counter);
+  }
+
+  @override
+  void visitSub61(Sub61 sub, Counter counter) {
+    sub.visitorDispatch61(counter);
+  }
+
+  @override
+  void visitSub62(Sub62 sub, Counter counter) {
+    sub.visitorDispatch62(counter);
+  }
+
+  @override
+  void visitSub63(Sub63 sub, Counter counter) {
+    sub.visitorDispatch63(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype7.dart b/pkg/front_end/benchmarks/patterns/generated/datatype7.dart
new file mode 100644
index 0000000..640791b
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype7.dart
@@ -0,0 +1,244 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base7 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor7<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base7 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor7<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+List<Base7> createData7() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+  ];
+}
+
+void incByDynamicDispatch7(Base7 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch7(Base7 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  }
+}
+
+const Visitor7<void, Counter> visitor = CounterVisitor7();
+
+void incByVisitorDispatch7(Base7 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor7<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+}
+
+class CounterVisitor7 implements Visitor7<void, Counter> {
+  const CounterVisitor7();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype8.dart b/pkg/front_end/benchmarks/patterns/generated/datatype8.dart
new file mode 100644
index 0000000..8360237
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype8.dart
@@ -0,0 +1,273 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base8 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor8<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base8 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor8<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+List<Base8> createData8() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+  ];
+}
+
+void incByDynamicDispatch8(Base8 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch8(Base8 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  }
+}
+
+const Visitor8<void, Counter> visitor = CounterVisitor8();
+
+void incByVisitorDispatch8(Base8 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor8<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+}
+
+class CounterVisitor8 implements Visitor8<void, Counter> {
+  const CounterVisitor8();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/generated/datatype96.dart b/pkg/front_end/benchmarks/patterns/generated/datatype96.dart
new file mode 100644
index 0000000..41d89e5
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/generated/datatype96.dart
@@ -0,0 +1,2825 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated by
+//
+//   pkg/front_end/benchmarks/patterns/generate_datatypes.dart
+
+import '../test_datatypes.dart';
+
+abstract class Base96 {
+  void dynamicDispatch(Counter counter);
+
+  R accept<R, A>(Visitor96<R, A> visitor, A arg);
+}
+
+class Sub0 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch0(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub0(this, arg);
+  }
+}
+
+class Sub1 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch1(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub1(this, arg);
+  }
+}
+
+class Sub2 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch2(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub2(this, arg);
+  }
+}
+
+class Sub3 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch3(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub3(this, arg);
+  }
+}
+
+class Sub4 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch4(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub4(this, arg);
+  }
+}
+
+class Sub5 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch5(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub5(this, arg);
+  }
+}
+
+class Sub6 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch6(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub6(this, arg);
+  }
+}
+
+class Sub7 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch7(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub7(this, arg);
+  }
+}
+
+class Sub8 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch8(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub8(this, arg);
+  }
+}
+
+class Sub9 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch9(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub9(this, arg);
+  }
+}
+
+class Sub10 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch10(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub10(this, arg);
+  }
+}
+
+class Sub11 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch11(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub11(this, arg);
+  }
+}
+
+class Sub12 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch12(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub12(this, arg);
+  }
+}
+
+class Sub13 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch13(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub13(this, arg);
+  }
+}
+
+class Sub14 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch14(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub14(this, arg);
+  }
+}
+
+class Sub15 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch15(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub15(this, arg);
+  }
+}
+
+class Sub16 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch16(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub16(this, arg);
+  }
+}
+
+class Sub17 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch17(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub17(this, arg);
+  }
+}
+
+class Sub18 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch18(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub18(this, arg);
+  }
+}
+
+class Sub19 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch19(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub19(this, arg);
+  }
+}
+
+class Sub20 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch20(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub20(this, arg);
+  }
+}
+
+class Sub21 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch21(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub21(this, arg);
+  }
+}
+
+class Sub22 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch22(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub22(this, arg);
+  }
+}
+
+class Sub23 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch23(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub23(this, arg);
+  }
+}
+
+class Sub24 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch24(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub24(this, arg);
+  }
+}
+
+class Sub25 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch25(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub25(this, arg);
+  }
+}
+
+class Sub26 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch26(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub26(this, arg);
+  }
+}
+
+class Sub27 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch27(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub27(this, arg);
+  }
+}
+
+class Sub28 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch28(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub28(this, arg);
+  }
+}
+
+class Sub29 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch29(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub29(this, arg);
+  }
+}
+
+class Sub30 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch30(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub30(this, arg);
+  }
+}
+
+class Sub31 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch31(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub31(this, arg);
+  }
+}
+
+class Sub32 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch32(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub32(this, arg);
+  }
+}
+
+class Sub33 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch33(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub33(this, arg);
+  }
+}
+
+class Sub34 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch34(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub34(this, arg);
+  }
+}
+
+class Sub35 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch35(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub35(this, arg);
+  }
+}
+
+class Sub36 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch36(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub36(this, arg);
+  }
+}
+
+class Sub37 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch37(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub37(this, arg);
+  }
+}
+
+class Sub38 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch38(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub38(this, arg);
+  }
+}
+
+class Sub39 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch39(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub39(this, arg);
+  }
+}
+
+class Sub40 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch40(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub40(this, arg);
+  }
+}
+
+class Sub41 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch41(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub41(this, arg);
+  }
+}
+
+class Sub42 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch42(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub42(this, arg);
+  }
+}
+
+class Sub43 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch43(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub43(this, arg);
+  }
+}
+
+class Sub44 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch44(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub44(this, arg);
+  }
+}
+
+class Sub45 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch45(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub45(this, arg);
+  }
+}
+
+class Sub46 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch46(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub46(this, arg);
+  }
+}
+
+class Sub47 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch47(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub47(this, arg);
+  }
+}
+
+class Sub48 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch48(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub48(this, arg);
+  }
+}
+
+class Sub49 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch49(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub49(this, arg);
+  }
+}
+
+class Sub50 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch50(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub50(this, arg);
+  }
+}
+
+class Sub51 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch51(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub51(this, arg);
+  }
+}
+
+class Sub52 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch52(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub52(this, arg);
+  }
+}
+
+class Sub53 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch53(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub53(this, arg);
+  }
+}
+
+class Sub54 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch54(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub54(this, arg);
+  }
+}
+
+class Sub55 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch55(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub55(this, arg);
+  }
+}
+
+class Sub56 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch56(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub56(this, arg);
+  }
+}
+
+class Sub57 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch57(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub57(this, arg);
+  }
+}
+
+class Sub58 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch58(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub58(this, arg);
+  }
+}
+
+class Sub59 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch59(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub59(this, arg);
+  }
+}
+
+class Sub60 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch60(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub60(this, arg);
+  }
+}
+
+class Sub61 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch61(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub61(this, arg);
+  }
+}
+
+class Sub62 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch62(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub62(this, arg);
+  }
+}
+
+class Sub63 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch63(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub63(this, arg);
+  }
+}
+
+class Sub64 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch64(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub64(this, arg);
+  }
+}
+
+class Sub65 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch65(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub65(this, arg);
+  }
+}
+
+class Sub66 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch66(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub66(this, arg);
+  }
+}
+
+class Sub67 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch67(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub67(this, arg);
+  }
+}
+
+class Sub68 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch68(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub68(this, arg);
+  }
+}
+
+class Sub69 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch69(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub69(this, arg);
+  }
+}
+
+class Sub70 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch70(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub70(this, arg);
+  }
+}
+
+class Sub71 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch71(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub71(this, arg);
+  }
+}
+
+class Sub72 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch72(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub72(this, arg);
+  }
+}
+
+class Sub73 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch73(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub73(this, arg);
+  }
+}
+
+class Sub74 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch74(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub74(this, arg);
+  }
+}
+
+class Sub75 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch75(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub75(this, arg);
+  }
+}
+
+class Sub76 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch76(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub76(this, arg);
+  }
+}
+
+class Sub77 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch77(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub77(this, arg);
+  }
+}
+
+class Sub78 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch78(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub78(this, arg);
+  }
+}
+
+class Sub79 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch79(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub79(this, arg);
+  }
+}
+
+class Sub80 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch80(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub80(this, arg);
+  }
+}
+
+class Sub81 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch81(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub81(this, arg);
+  }
+}
+
+class Sub82 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch82(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub82(this, arg);
+  }
+}
+
+class Sub83 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch83(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub83(this, arg);
+  }
+}
+
+class Sub84 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch84(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub84(this, arg);
+  }
+}
+
+class Sub85 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch85(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub85(this, arg);
+  }
+}
+
+class Sub86 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch86(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub86(this, arg);
+  }
+}
+
+class Sub87 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch87(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub87(this, arg);
+  }
+}
+
+class Sub88 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch88(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub88(this, arg);
+  }
+}
+
+class Sub89 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch89(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub89(this, arg);
+  }
+}
+
+class Sub90 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch90(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub90(this, arg);
+  }
+}
+
+class Sub91 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch91(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub91(this, arg);
+  }
+}
+
+class Sub92 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch92(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub92(this, arg);
+  }
+}
+
+class Sub93 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch93(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub93(this, arg);
+  }
+}
+
+class Sub94 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch94(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub94(this, arg);
+  }
+}
+
+class Sub95 extends Base96 {
+  @override
+  void dynamicDispatch(Counter counter) {
+    counter.inc();
+  }
+
+  void ifThenElseDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  void visitorDispatch95(Counter counter) {
+    counter.inc();
+  }
+
+  @override
+  R accept<R, A>(Visitor96<R, A> visitor, A arg) {
+    return visitor.visitSub95(this, arg);
+  }
+}
+
+List<Base96> createData96() {
+  return [
+    Sub0(),
+    Sub1(),
+    Sub2(),
+    Sub3(),
+    Sub4(),
+    Sub5(),
+    Sub6(),
+    Sub7(),
+    Sub8(),
+    Sub9(),
+    Sub10(),
+    Sub11(),
+    Sub12(),
+    Sub13(),
+    Sub14(),
+    Sub15(),
+    Sub16(),
+    Sub17(),
+    Sub18(),
+    Sub19(),
+    Sub20(),
+    Sub21(),
+    Sub22(),
+    Sub23(),
+    Sub24(),
+    Sub25(),
+    Sub26(),
+    Sub27(),
+    Sub28(),
+    Sub29(),
+    Sub30(),
+    Sub31(),
+    Sub32(),
+    Sub33(),
+    Sub34(),
+    Sub35(),
+    Sub36(),
+    Sub37(),
+    Sub38(),
+    Sub39(),
+    Sub40(),
+    Sub41(),
+    Sub42(),
+    Sub43(),
+    Sub44(),
+    Sub45(),
+    Sub46(),
+    Sub47(),
+    Sub48(),
+    Sub49(),
+    Sub50(),
+    Sub51(),
+    Sub52(),
+    Sub53(),
+    Sub54(),
+    Sub55(),
+    Sub56(),
+    Sub57(),
+    Sub58(),
+    Sub59(),
+    Sub60(),
+    Sub61(),
+    Sub62(),
+    Sub63(),
+    Sub64(),
+    Sub65(),
+    Sub66(),
+    Sub67(),
+    Sub68(),
+    Sub69(),
+    Sub70(),
+    Sub71(),
+    Sub72(),
+    Sub73(),
+    Sub74(),
+    Sub75(),
+    Sub76(),
+    Sub77(),
+    Sub78(),
+    Sub79(),
+    Sub80(),
+    Sub81(),
+    Sub82(),
+    Sub83(),
+    Sub84(),
+    Sub85(),
+    Sub86(),
+    Sub87(),
+    Sub88(),
+    Sub89(),
+    Sub90(),
+    Sub91(),
+    Sub92(),
+    Sub93(),
+    Sub94(),
+    Sub95(),
+  ];
+}
+
+void incByDynamicDispatch96(Base96 base, Counter counter) {
+  base.dynamicDispatch(counter);
+}
+
+void incByIfThenElseDispatch96(Base96 base, Counter counter) {
+  if (base is Sub0) {
+    base.ifThenElseDispatch0(counter);
+  } else if (base is Sub1) {
+    base.ifThenElseDispatch1(counter);
+  } else if (base is Sub2) {
+    base.ifThenElseDispatch2(counter);
+  } else if (base is Sub3) {
+    base.ifThenElseDispatch3(counter);
+  } else if (base is Sub4) {
+    base.ifThenElseDispatch4(counter);
+  } else if (base is Sub5) {
+    base.ifThenElseDispatch5(counter);
+  } else if (base is Sub6) {
+    base.ifThenElseDispatch6(counter);
+  } else if (base is Sub7) {
+    base.ifThenElseDispatch7(counter);
+  } else if (base is Sub8) {
+    base.ifThenElseDispatch8(counter);
+  } else if (base is Sub9) {
+    base.ifThenElseDispatch9(counter);
+  } else if (base is Sub10) {
+    base.ifThenElseDispatch10(counter);
+  } else if (base is Sub11) {
+    base.ifThenElseDispatch11(counter);
+  } else if (base is Sub12) {
+    base.ifThenElseDispatch12(counter);
+  } else if (base is Sub13) {
+    base.ifThenElseDispatch13(counter);
+  } else if (base is Sub14) {
+    base.ifThenElseDispatch14(counter);
+  } else if (base is Sub15) {
+    base.ifThenElseDispatch15(counter);
+  } else if (base is Sub16) {
+    base.ifThenElseDispatch16(counter);
+  } else if (base is Sub17) {
+    base.ifThenElseDispatch17(counter);
+  } else if (base is Sub18) {
+    base.ifThenElseDispatch18(counter);
+  } else if (base is Sub19) {
+    base.ifThenElseDispatch19(counter);
+  } else if (base is Sub20) {
+    base.ifThenElseDispatch20(counter);
+  } else if (base is Sub21) {
+    base.ifThenElseDispatch21(counter);
+  } else if (base is Sub22) {
+    base.ifThenElseDispatch22(counter);
+  } else if (base is Sub23) {
+    base.ifThenElseDispatch23(counter);
+  } else if (base is Sub24) {
+    base.ifThenElseDispatch24(counter);
+  } else if (base is Sub25) {
+    base.ifThenElseDispatch25(counter);
+  } else if (base is Sub26) {
+    base.ifThenElseDispatch26(counter);
+  } else if (base is Sub27) {
+    base.ifThenElseDispatch27(counter);
+  } else if (base is Sub28) {
+    base.ifThenElseDispatch28(counter);
+  } else if (base is Sub29) {
+    base.ifThenElseDispatch29(counter);
+  } else if (base is Sub30) {
+    base.ifThenElseDispatch30(counter);
+  } else if (base is Sub31) {
+    base.ifThenElseDispatch31(counter);
+  } else if (base is Sub32) {
+    base.ifThenElseDispatch32(counter);
+  } else if (base is Sub33) {
+    base.ifThenElseDispatch33(counter);
+  } else if (base is Sub34) {
+    base.ifThenElseDispatch34(counter);
+  } else if (base is Sub35) {
+    base.ifThenElseDispatch35(counter);
+  } else if (base is Sub36) {
+    base.ifThenElseDispatch36(counter);
+  } else if (base is Sub37) {
+    base.ifThenElseDispatch37(counter);
+  } else if (base is Sub38) {
+    base.ifThenElseDispatch38(counter);
+  } else if (base is Sub39) {
+    base.ifThenElseDispatch39(counter);
+  } else if (base is Sub40) {
+    base.ifThenElseDispatch40(counter);
+  } else if (base is Sub41) {
+    base.ifThenElseDispatch41(counter);
+  } else if (base is Sub42) {
+    base.ifThenElseDispatch42(counter);
+  } else if (base is Sub43) {
+    base.ifThenElseDispatch43(counter);
+  } else if (base is Sub44) {
+    base.ifThenElseDispatch44(counter);
+  } else if (base is Sub45) {
+    base.ifThenElseDispatch45(counter);
+  } else if (base is Sub46) {
+    base.ifThenElseDispatch46(counter);
+  } else if (base is Sub47) {
+    base.ifThenElseDispatch47(counter);
+  } else if (base is Sub48) {
+    base.ifThenElseDispatch48(counter);
+  } else if (base is Sub49) {
+    base.ifThenElseDispatch49(counter);
+  } else if (base is Sub50) {
+    base.ifThenElseDispatch50(counter);
+  } else if (base is Sub51) {
+    base.ifThenElseDispatch51(counter);
+  } else if (base is Sub52) {
+    base.ifThenElseDispatch52(counter);
+  } else if (base is Sub53) {
+    base.ifThenElseDispatch53(counter);
+  } else if (base is Sub54) {
+    base.ifThenElseDispatch54(counter);
+  } else if (base is Sub55) {
+    base.ifThenElseDispatch55(counter);
+  } else if (base is Sub56) {
+    base.ifThenElseDispatch56(counter);
+  } else if (base is Sub57) {
+    base.ifThenElseDispatch57(counter);
+  } else if (base is Sub58) {
+    base.ifThenElseDispatch58(counter);
+  } else if (base is Sub59) {
+    base.ifThenElseDispatch59(counter);
+  } else if (base is Sub60) {
+    base.ifThenElseDispatch60(counter);
+  } else if (base is Sub61) {
+    base.ifThenElseDispatch61(counter);
+  } else if (base is Sub62) {
+    base.ifThenElseDispatch62(counter);
+  } else if (base is Sub63) {
+    base.ifThenElseDispatch63(counter);
+  } else if (base is Sub64) {
+    base.ifThenElseDispatch64(counter);
+  } else if (base is Sub65) {
+    base.ifThenElseDispatch65(counter);
+  } else if (base is Sub66) {
+    base.ifThenElseDispatch66(counter);
+  } else if (base is Sub67) {
+    base.ifThenElseDispatch67(counter);
+  } else if (base is Sub68) {
+    base.ifThenElseDispatch68(counter);
+  } else if (base is Sub69) {
+    base.ifThenElseDispatch69(counter);
+  } else if (base is Sub70) {
+    base.ifThenElseDispatch70(counter);
+  } else if (base is Sub71) {
+    base.ifThenElseDispatch71(counter);
+  } else if (base is Sub72) {
+    base.ifThenElseDispatch72(counter);
+  } else if (base is Sub73) {
+    base.ifThenElseDispatch73(counter);
+  } else if (base is Sub74) {
+    base.ifThenElseDispatch74(counter);
+  } else if (base is Sub75) {
+    base.ifThenElseDispatch75(counter);
+  } else if (base is Sub76) {
+    base.ifThenElseDispatch76(counter);
+  } else if (base is Sub77) {
+    base.ifThenElseDispatch77(counter);
+  } else if (base is Sub78) {
+    base.ifThenElseDispatch78(counter);
+  } else if (base is Sub79) {
+    base.ifThenElseDispatch79(counter);
+  } else if (base is Sub80) {
+    base.ifThenElseDispatch80(counter);
+  } else if (base is Sub81) {
+    base.ifThenElseDispatch81(counter);
+  } else if (base is Sub82) {
+    base.ifThenElseDispatch82(counter);
+  } else if (base is Sub83) {
+    base.ifThenElseDispatch83(counter);
+  } else if (base is Sub84) {
+    base.ifThenElseDispatch84(counter);
+  } else if (base is Sub85) {
+    base.ifThenElseDispatch85(counter);
+  } else if (base is Sub86) {
+    base.ifThenElseDispatch86(counter);
+  } else if (base is Sub87) {
+    base.ifThenElseDispatch87(counter);
+  } else if (base is Sub88) {
+    base.ifThenElseDispatch88(counter);
+  } else if (base is Sub89) {
+    base.ifThenElseDispatch89(counter);
+  } else if (base is Sub90) {
+    base.ifThenElseDispatch90(counter);
+  } else if (base is Sub91) {
+    base.ifThenElseDispatch91(counter);
+  } else if (base is Sub92) {
+    base.ifThenElseDispatch92(counter);
+  } else if (base is Sub93) {
+    base.ifThenElseDispatch93(counter);
+  } else if (base is Sub94) {
+    base.ifThenElseDispatch94(counter);
+  } else if (base is Sub95) {
+    base.ifThenElseDispatch95(counter);
+  }
+}
+
+const Visitor96<void, Counter> visitor = CounterVisitor96();
+
+void incByVisitorDispatch96(Base96 base, Counter counter) {
+  base.accept(visitor, counter);
+}
+
+abstract class Visitor96<R, A> {
+  R visitSub0(Sub0 sub, A arg);
+  R visitSub1(Sub1 sub, A arg);
+  R visitSub2(Sub2 sub, A arg);
+  R visitSub3(Sub3 sub, A arg);
+  R visitSub4(Sub4 sub, A arg);
+  R visitSub5(Sub5 sub, A arg);
+  R visitSub6(Sub6 sub, A arg);
+  R visitSub7(Sub7 sub, A arg);
+  R visitSub8(Sub8 sub, A arg);
+  R visitSub9(Sub9 sub, A arg);
+  R visitSub10(Sub10 sub, A arg);
+  R visitSub11(Sub11 sub, A arg);
+  R visitSub12(Sub12 sub, A arg);
+  R visitSub13(Sub13 sub, A arg);
+  R visitSub14(Sub14 sub, A arg);
+  R visitSub15(Sub15 sub, A arg);
+  R visitSub16(Sub16 sub, A arg);
+  R visitSub17(Sub17 sub, A arg);
+  R visitSub18(Sub18 sub, A arg);
+  R visitSub19(Sub19 sub, A arg);
+  R visitSub20(Sub20 sub, A arg);
+  R visitSub21(Sub21 sub, A arg);
+  R visitSub22(Sub22 sub, A arg);
+  R visitSub23(Sub23 sub, A arg);
+  R visitSub24(Sub24 sub, A arg);
+  R visitSub25(Sub25 sub, A arg);
+  R visitSub26(Sub26 sub, A arg);
+  R visitSub27(Sub27 sub, A arg);
+  R visitSub28(Sub28 sub, A arg);
+  R visitSub29(Sub29 sub, A arg);
+  R visitSub30(Sub30 sub, A arg);
+  R visitSub31(Sub31 sub, A arg);
+  R visitSub32(Sub32 sub, A arg);
+  R visitSub33(Sub33 sub, A arg);
+  R visitSub34(Sub34 sub, A arg);
+  R visitSub35(Sub35 sub, A arg);
+  R visitSub36(Sub36 sub, A arg);
+  R visitSub37(Sub37 sub, A arg);
+  R visitSub38(Sub38 sub, A arg);
+  R visitSub39(Sub39 sub, A arg);
+  R visitSub40(Sub40 sub, A arg);
+  R visitSub41(Sub41 sub, A arg);
+  R visitSub42(Sub42 sub, A arg);
+  R visitSub43(Sub43 sub, A arg);
+  R visitSub44(Sub44 sub, A arg);
+  R visitSub45(Sub45 sub, A arg);
+  R visitSub46(Sub46 sub, A arg);
+  R visitSub47(Sub47 sub, A arg);
+  R visitSub48(Sub48 sub, A arg);
+  R visitSub49(Sub49 sub, A arg);
+  R visitSub50(Sub50 sub, A arg);
+  R visitSub51(Sub51 sub, A arg);
+  R visitSub52(Sub52 sub, A arg);
+  R visitSub53(Sub53 sub, A arg);
+  R visitSub54(Sub54 sub, A arg);
+  R visitSub55(Sub55 sub, A arg);
+  R visitSub56(Sub56 sub, A arg);
+  R visitSub57(Sub57 sub, A arg);
+  R visitSub58(Sub58 sub, A arg);
+  R visitSub59(Sub59 sub, A arg);
+  R visitSub60(Sub60 sub, A arg);
+  R visitSub61(Sub61 sub, A arg);
+  R visitSub62(Sub62 sub, A arg);
+  R visitSub63(Sub63 sub, A arg);
+  R visitSub64(Sub64 sub, A arg);
+  R visitSub65(Sub65 sub, A arg);
+  R visitSub66(Sub66 sub, A arg);
+  R visitSub67(Sub67 sub, A arg);
+  R visitSub68(Sub68 sub, A arg);
+  R visitSub69(Sub69 sub, A arg);
+  R visitSub70(Sub70 sub, A arg);
+  R visitSub71(Sub71 sub, A arg);
+  R visitSub72(Sub72 sub, A arg);
+  R visitSub73(Sub73 sub, A arg);
+  R visitSub74(Sub74 sub, A arg);
+  R visitSub75(Sub75 sub, A arg);
+  R visitSub76(Sub76 sub, A arg);
+  R visitSub77(Sub77 sub, A arg);
+  R visitSub78(Sub78 sub, A arg);
+  R visitSub79(Sub79 sub, A arg);
+  R visitSub80(Sub80 sub, A arg);
+  R visitSub81(Sub81 sub, A arg);
+  R visitSub82(Sub82 sub, A arg);
+  R visitSub83(Sub83 sub, A arg);
+  R visitSub84(Sub84 sub, A arg);
+  R visitSub85(Sub85 sub, A arg);
+  R visitSub86(Sub86 sub, A arg);
+  R visitSub87(Sub87 sub, A arg);
+  R visitSub88(Sub88 sub, A arg);
+  R visitSub89(Sub89 sub, A arg);
+  R visitSub90(Sub90 sub, A arg);
+  R visitSub91(Sub91 sub, A arg);
+  R visitSub92(Sub92 sub, A arg);
+  R visitSub93(Sub93 sub, A arg);
+  R visitSub94(Sub94 sub, A arg);
+  R visitSub95(Sub95 sub, A arg);
+}
+
+class CounterVisitor96 implements Visitor96<void, Counter> {
+  const CounterVisitor96();
+
+  @override
+  void visitSub0(Sub0 sub, Counter counter) {
+    sub.visitorDispatch0(counter);
+  }
+
+  @override
+  void visitSub1(Sub1 sub, Counter counter) {
+    sub.visitorDispatch1(counter);
+  }
+
+  @override
+  void visitSub2(Sub2 sub, Counter counter) {
+    sub.visitorDispatch2(counter);
+  }
+
+  @override
+  void visitSub3(Sub3 sub, Counter counter) {
+    sub.visitorDispatch3(counter);
+  }
+
+  @override
+  void visitSub4(Sub4 sub, Counter counter) {
+    sub.visitorDispatch4(counter);
+  }
+
+  @override
+  void visitSub5(Sub5 sub, Counter counter) {
+    sub.visitorDispatch5(counter);
+  }
+
+  @override
+  void visitSub6(Sub6 sub, Counter counter) {
+    sub.visitorDispatch6(counter);
+  }
+
+  @override
+  void visitSub7(Sub7 sub, Counter counter) {
+    sub.visitorDispatch7(counter);
+  }
+
+  @override
+  void visitSub8(Sub8 sub, Counter counter) {
+    sub.visitorDispatch8(counter);
+  }
+
+  @override
+  void visitSub9(Sub9 sub, Counter counter) {
+    sub.visitorDispatch9(counter);
+  }
+
+  @override
+  void visitSub10(Sub10 sub, Counter counter) {
+    sub.visitorDispatch10(counter);
+  }
+
+  @override
+  void visitSub11(Sub11 sub, Counter counter) {
+    sub.visitorDispatch11(counter);
+  }
+
+  @override
+  void visitSub12(Sub12 sub, Counter counter) {
+    sub.visitorDispatch12(counter);
+  }
+
+  @override
+  void visitSub13(Sub13 sub, Counter counter) {
+    sub.visitorDispatch13(counter);
+  }
+
+  @override
+  void visitSub14(Sub14 sub, Counter counter) {
+    sub.visitorDispatch14(counter);
+  }
+
+  @override
+  void visitSub15(Sub15 sub, Counter counter) {
+    sub.visitorDispatch15(counter);
+  }
+
+  @override
+  void visitSub16(Sub16 sub, Counter counter) {
+    sub.visitorDispatch16(counter);
+  }
+
+  @override
+  void visitSub17(Sub17 sub, Counter counter) {
+    sub.visitorDispatch17(counter);
+  }
+
+  @override
+  void visitSub18(Sub18 sub, Counter counter) {
+    sub.visitorDispatch18(counter);
+  }
+
+  @override
+  void visitSub19(Sub19 sub, Counter counter) {
+    sub.visitorDispatch19(counter);
+  }
+
+  @override
+  void visitSub20(Sub20 sub, Counter counter) {
+    sub.visitorDispatch20(counter);
+  }
+
+  @override
+  void visitSub21(Sub21 sub, Counter counter) {
+    sub.visitorDispatch21(counter);
+  }
+
+  @override
+  void visitSub22(Sub22 sub, Counter counter) {
+    sub.visitorDispatch22(counter);
+  }
+
+  @override
+  void visitSub23(Sub23 sub, Counter counter) {
+    sub.visitorDispatch23(counter);
+  }
+
+  @override
+  void visitSub24(Sub24 sub, Counter counter) {
+    sub.visitorDispatch24(counter);
+  }
+
+  @override
+  void visitSub25(Sub25 sub, Counter counter) {
+    sub.visitorDispatch25(counter);
+  }
+
+  @override
+  void visitSub26(Sub26 sub, Counter counter) {
+    sub.visitorDispatch26(counter);
+  }
+
+  @override
+  void visitSub27(Sub27 sub, Counter counter) {
+    sub.visitorDispatch27(counter);
+  }
+
+  @override
+  void visitSub28(Sub28 sub, Counter counter) {
+    sub.visitorDispatch28(counter);
+  }
+
+  @override
+  void visitSub29(Sub29 sub, Counter counter) {
+    sub.visitorDispatch29(counter);
+  }
+
+  @override
+  void visitSub30(Sub30 sub, Counter counter) {
+    sub.visitorDispatch30(counter);
+  }
+
+  @override
+  void visitSub31(Sub31 sub, Counter counter) {
+    sub.visitorDispatch31(counter);
+  }
+
+  @override
+  void visitSub32(Sub32 sub, Counter counter) {
+    sub.visitorDispatch32(counter);
+  }
+
+  @override
+  void visitSub33(Sub33 sub, Counter counter) {
+    sub.visitorDispatch33(counter);
+  }
+
+  @override
+  void visitSub34(Sub34 sub, Counter counter) {
+    sub.visitorDispatch34(counter);
+  }
+
+  @override
+  void visitSub35(Sub35 sub, Counter counter) {
+    sub.visitorDispatch35(counter);
+  }
+
+  @override
+  void visitSub36(Sub36 sub, Counter counter) {
+    sub.visitorDispatch36(counter);
+  }
+
+  @override
+  void visitSub37(Sub37 sub, Counter counter) {
+    sub.visitorDispatch37(counter);
+  }
+
+  @override
+  void visitSub38(Sub38 sub, Counter counter) {
+    sub.visitorDispatch38(counter);
+  }
+
+  @override
+  void visitSub39(Sub39 sub, Counter counter) {
+    sub.visitorDispatch39(counter);
+  }
+
+  @override
+  void visitSub40(Sub40 sub, Counter counter) {
+    sub.visitorDispatch40(counter);
+  }
+
+  @override
+  void visitSub41(Sub41 sub, Counter counter) {
+    sub.visitorDispatch41(counter);
+  }
+
+  @override
+  void visitSub42(Sub42 sub, Counter counter) {
+    sub.visitorDispatch42(counter);
+  }
+
+  @override
+  void visitSub43(Sub43 sub, Counter counter) {
+    sub.visitorDispatch43(counter);
+  }
+
+  @override
+  void visitSub44(Sub44 sub, Counter counter) {
+    sub.visitorDispatch44(counter);
+  }
+
+  @override
+  void visitSub45(Sub45 sub, Counter counter) {
+    sub.visitorDispatch45(counter);
+  }
+
+  @override
+  void visitSub46(Sub46 sub, Counter counter) {
+    sub.visitorDispatch46(counter);
+  }
+
+  @override
+  void visitSub47(Sub47 sub, Counter counter) {
+    sub.visitorDispatch47(counter);
+  }
+
+  @override
+  void visitSub48(Sub48 sub, Counter counter) {
+    sub.visitorDispatch48(counter);
+  }
+
+  @override
+  void visitSub49(Sub49 sub, Counter counter) {
+    sub.visitorDispatch49(counter);
+  }
+
+  @override
+  void visitSub50(Sub50 sub, Counter counter) {
+    sub.visitorDispatch50(counter);
+  }
+
+  @override
+  void visitSub51(Sub51 sub, Counter counter) {
+    sub.visitorDispatch51(counter);
+  }
+
+  @override
+  void visitSub52(Sub52 sub, Counter counter) {
+    sub.visitorDispatch52(counter);
+  }
+
+  @override
+  void visitSub53(Sub53 sub, Counter counter) {
+    sub.visitorDispatch53(counter);
+  }
+
+  @override
+  void visitSub54(Sub54 sub, Counter counter) {
+    sub.visitorDispatch54(counter);
+  }
+
+  @override
+  void visitSub55(Sub55 sub, Counter counter) {
+    sub.visitorDispatch55(counter);
+  }
+
+  @override
+  void visitSub56(Sub56 sub, Counter counter) {
+    sub.visitorDispatch56(counter);
+  }
+
+  @override
+  void visitSub57(Sub57 sub, Counter counter) {
+    sub.visitorDispatch57(counter);
+  }
+
+  @override
+  void visitSub58(Sub58 sub, Counter counter) {
+    sub.visitorDispatch58(counter);
+  }
+
+  @override
+  void visitSub59(Sub59 sub, Counter counter) {
+    sub.visitorDispatch59(counter);
+  }
+
+  @override
+  void visitSub60(Sub60 sub, Counter counter) {
+    sub.visitorDispatch60(counter);
+  }
+
+  @override
+  void visitSub61(Sub61 sub, Counter counter) {
+    sub.visitorDispatch61(counter);
+  }
+
+  @override
+  void visitSub62(Sub62 sub, Counter counter) {
+    sub.visitorDispatch62(counter);
+  }
+
+  @override
+  void visitSub63(Sub63 sub, Counter counter) {
+    sub.visitorDispatch63(counter);
+  }
+
+  @override
+  void visitSub64(Sub64 sub, Counter counter) {
+    sub.visitorDispatch64(counter);
+  }
+
+  @override
+  void visitSub65(Sub65 sub, Counter counter) {
+    sub.visitorDispatch65(counter);
+  }
+
+  @override
+  void visitSub66(Sub66 sub, Counter counter) {
+    sub.visitorDispatch66(counter);
+  }
+
+  @override
+  void visitSub67(Sub67 sub, Counter counter) {
+    sub.visitorDispatch67(counter);
+  }
+
+  @override
+  void visitSub68(Sub68 sub, Counter counter) {
+    sub.visitorDispatch68(counter);
+  }
+
+  @override
+  void visitSub69(Sub69 sub, Counter counter) {
+    sub.visitorDispatch69(counter);
+  }
+
+  @override
+  void visitSub70(Sub70 sub, Counter counter) {
+    sub.visitorDispatch70(counter);
+  }
+
+  @override
+  void visitSub71(Sub71 sub, Counter counter) {
+    sub.visitorDispatch71(counter);
+  }
+
+  @override
+  void visitSub72(Sub72 sub, Counter counter) {
+    sub.visitorDispatch72(counter);
+  }
+
+  @override
+  void visitSub73(Sub73 sub, Counter counter) {
+    sub.visitorDispatch73(counter);
+  }
+
+  @override
+  void visitSub74(Sub74 sub, Counter counter) {
+    sub.visitorDispatch74(counter);
+  }
+
+  @override
+  void visitSub75(Sub75 sub, Counter counter) {
+    sub.visitorDispatch75(counter);
+  }
+
+  @override
+  void visitSub76(Sub76 sub, Counter counter) {
+    sub.visitorDispatch76(counter);
+  }
+
+  @override
+  void visitSub77(Sub77 sub, Counter counter) {
+    sub.visitorDispatch77(counter);
+  }
+
+  @override
+  void visitSub78(Sub78 sub, Counter counter) {
+    sub.visitorDispatch78(counter);
+  }
+
+  @override
+  void visitSub79(Sub79 sub, Counter counter) {
+    sub.visitorDispatch79(counter);
+  }
+
+  @override
+  void visitSub80(Sub80 sub, Counter counter) {
+    sub.visitorDispatch80(counter);
+  }
+
+  @override
+  void visitSub81(Sub81 sub, Counter counter) {
+    sub.visitorDispatch81(counter);
+  }
+
+  @override
+  void visitSub82(Sub82 sub, Counter counter) {
+    sub.visitorDispatch82(counter);
+  }
+
+  @override
+  void visitSub83(Sub83 sub, Counter counter) {
+    sub.visitorDispatch83(counter);
+  }
+
+  @override
+  void visitSub84(Sub84 sub, Counter counter) {
+    sub.visitorDispatch84(counter);
+  }
+
+  @override
+  void visitSub85(Sub85 sub, Counter counter) {
+    sub.visitorDispatch85(counter);
+  }
+
+  @override
+  void visitSub86(Sub86 sub, Counter counter) {
+    sub.visitorDispatch86(counter);
+  }
+
+  @override
+  void visitSub87(Sub87 sub, Counter counter) {
+    sub.visitorDispatch87(counter);
+  }
+
+  @override
+  void visitSub88(Sub88 sub, Counter counter) {
+    sub.visitorDispatch88(counter);
+  }
+
+  @override
+  void visitSub89(Sub89 sub, Counter counter) {
+    sub.visitorDispatch89(counter);
+  }
+
+  @override
+  void visitSub90(Sub90 sub, Counter counter) {
+    sub.visitorDispatch90(counter);
+  }
+
+  @override
+  void visitSub91(Sub91 sub, Counter counter) {
+    sub.visitorDispatch91(counter);
+  }
+
+  @override
+  void visitSub92(Sub92 sub, Counter counter) {
+    sub.visitorDispatch92(counter);
+  }
+
+  @override
+  void visitSub93(Sub93 sub, Counter counter) {
+    sub.visitorDispatch93(counter);
+  }
+
+  @override
+  void visitSub94(Sub94 sub, Counter counter) {
+    sub.visitorDispatch94(counter);
+  }
+
+  @override
+  void visitSub95(Sub95 sub, Counter counter) {
+    sub.visitorDispatch95(counter);
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/test_datatypes.dart b/pkg/front_end/benchmarks/patterns/test_datatypes.dart
new file mode 100644
index 0000000..a559a2c
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/test_datatypes.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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=2.14
+
+import 'util.dart';
+import 'generated/datatype.dart';
+
+typedef TestFunction<T> = void Function(T, Counter);
+typedef DataFunction = List<T> Function<T>(List<T>);
+
+class Counter {
+  int _value = 0;
+
+  int get value => _value;
+
+  void inc() {
+    _value++;
+  }
+}
+
+const Strategy ifThenElseStrategy = Strategy('if-then-else', '''
+Implements functionality in helper method. Invocation is done by an if-then-else
+sequence that uses is-tests to match functionality with subclasses.''');
+
+const Strategy dynamicDispatchStrategy = Strategy('dynamic-dispatch', '''
+Implements functionality by adding a method to each subclass that implements an
+interface method. Invocation is done as a dynamic dispatch on the interface 
+method.''');
+
+const Strategy visitorStrategy = Strategy('visitor', '''
+Implements functionality in helper method. Invocation is done by an if-then-else
+sequence that uses is-tests to match functionality with subclasses.''');
+
+const Scenario increasingScenario = Scenario('increasing', '''
+Implementation is called equally between all subclasses.''');
+// TODO(johnniwinther): Should Zipf's Law be used for 'first' and 'last'
+//  scenarios?
+const Scenario firstScenario = Scenario('first', '''
+Implementation is only called for the first two subclasses. For the 
+'if-then-else' strategy, this mimics when the order of the subclasses in the 
+if-then-else sequence aligns with the frequency of use, always finding a
+matching case early in the if-then-else sequence.''');
+const Scenario lastScenario = Scenario('last', '''
+Implementation is only called for the last two subclasses. For the 
+'if-then-else' strategy, this mimics when the order of the subclasses in the 
+if-then-else sequence *mis-aligns* with the frequency of use, always finding a
+matching case late in the if-then-else sequence.''');
+
+Map<Scenario, DataFunction> scenarios = {
+  increasingScenario: <T>(List<T> data) => data,
+  firstScenario: <T>(List<T> data) {
+    if (data.length < 2) {
+      return [data.first, data.first];
+    } else {
+      return data.take(2).toList();
+    }
+  },
+  lastScenario: <T>(List<T> data) {
+    if (data.length < 2) {
+      return [data.last, data.last];
+    } else {
+      return data.skip(data.length - 2).toList();
+    }
+  },
+};
+
+class Test<T> {
+  final int size;
+  final List<T> Function() createData;
+  final Map<Strategy, TestFunction<T>> strategies;
+
+  const Test(this.size, this.createData, this.strategies);
+
+  void _test(Registry registry, SeriesKey key, int runs, int iterations,
+      List<T> data, TestFunction<T> testFunction) {
+    int length = data.length;
+    for (int run = 0; run < runs; run++) {
+      Counter counter = new Counter();
+      Stopwatch sw = new Stopwatch();
+      for (int i = 0; i < iterations; i++) {
+        T value = data[i % length];
+        sw.start();
+        testFunction(value, counter);
+        sw.stop();
+      }
+      registry.registerData(key, size, sw.elapsedMicroseconds);
+      if (counter.value != iterations) {
+        throw 'Counter mismatch: '
+            'Expected $iterations, actual ${counter.value}';
+      }
+    }
+  }
+
+  void performTest(
+      {required Registry registry,
+      required int runs,
+      required int iterations,
+      required Map<Scenario, DataFunction> scenarios}) {
+    List<T> data = createData();
+    for (MapEntry<Scenario, DataFunction> scenario in scenarios.entries) {
+      List<T> scenarioData = scenario.value(data);
+      for (MapEntry<Strategy, TestFunction<T>> entry in strategies.entries) {
+        _test(registry, new SeriesKey(entry.key, scenario.key), runs,
+            iterations, scenarioData, entry.value);
+      }
+    }
+  }
+}
+
+void main() {
+  // Dry run
+  for (Test test in tests) {
+    test.performTest(
+        registry: new Registry(),
+        runs: 5,
+        iterations: 10,
+        scenarios: scenarios);
+  }
+  // Actual test
+  Registry registry = new Registry();
+  for (Test test in tests) {
+    test.performTest(
+        registry: registry, runs: 10, iterations: 100000, scenarios: scenarios);
+  }
+  SeriesSet seriesSet = registry.generateSeriesSet();
+  print('== Raw data ==');
+  for (Scenario scenario in scenarios.keys) {
+    print(seriesSet.getFullSpreadByScenario(scenario));
+  }
+  print('== Reduced averages ==');
+  SeriesSet reducedSeriesSet = seriesSet.filter((list) => removeMax(list, 3));
+  for (Scenario scenario in scenarios.keys) {
+    print(reducedSeriesSet.getAveragedSpreadByScenario(scenario));
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/test_lists.dart b/pkg/front_end/benchmarks/patterns/test_lists.dart
new file mode 100644
index 0000000..4a20f36
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/test_lists.dart
@@ -0,0 +1,271 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'util.dart';
+
+typedef TestFunction<T> = List<T> Function(List<T>);
+
+class InputOutputData<T> {
+  final List<T> input;
+  final List<T> output;
+
+  const InputOutputData(this.input, this.output);
+}
+
+const Strategy simpleAddStrategy = Strategy('simple-add', '''
+Add entries to a list one at a time.''');
+
+const Strategy spreadStrategy = Strategy('spread', '''
+Create the list via spreads.''');
+
+const Strategy listGenerateGrowableStrategy =
+    Strategy('list-generate-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listGenerateNotGrowableStrategy =
+    Strategy('list-generate-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Strategy listFilledGrowableStrategy = Strategy('list-filled-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listFilledNotGrowableStrategy =
+    Strategy('list-filled-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Strategy listFilledAlternativeGrowableStrategy =
+    Strategy('list-filled-alt-growable', '''
+Create list via List.generate with growable = true in an alternative way.''');
+
+const Strategy listFilledAlternativeNotGrowableStrategy =
+    Strategy('list-filled-alt-not-growable', '''
+Create list via List.generate with growable = false in an alternative way.''');
+
+const Scenario emptyScenario = Scenario('empty', '''
+The input and output is empty.''');
+const Scenario oneEntryScenario = Scenario('one', '''
+The input is one entry.''');
+const Scenario severalEntriesScenario = Scenario('several', '''
+The input has several entries.''');
+
+Map<Scenario, InputOutputData<String>> scenarios = {
+  emptyScenario: const InputOutputData([], []),
+  oneEntryScenario: const InputOutputData(["a"], ["<", "a", ">"]),
+  severalEntriesScenario: const InputOutputData(
+    [
+      "a",
+      "b",
+      "c",
+      "d",
+      "e",
+      "f",
+      "g",
+    ],
+    [
+      "<",
+      "a",
+      ", ",
+      "b",
+      ", ",
+      "c",
+      ", ",
+      "d",
+      ", ",
+      "e",
+      ", ",
+      "f",
+      ", ",
+      "g",
+      ">",
+    ],
+  ),
+};
+
+class Test<T> {
+  final int size;
+  final Map<Strategy, TestFunction<T>> strategies;
+
+  const Test(this.size, this.strategies);
+
+  void _test(Registry registry, SeriesKey key, int runs, int iterations,
+      List<T> input, List<T> expectedResult, TestFunction<T> testFunction) {
+    for (int run = 0; run < runs; run++) {
+      Stopwatch sw = new Stopwatch();
+      for (int i = 0; i < iterations; i++) {
+        sw.start();
+        List<T> actualOutput = testFunction(input);
+        sw.stop();
+        checkEquals(actualOutput, expectedResult);
+      }
+      registry.registerData(key, size, sw.elapsedMicroseconds);
+    }
+  }
+
+  void checkEquals(List<T> a, List<T> b) {
+    if (a.length != b.length) throw "length for $a vs $b";
+    for (int i = 0; i < a.length; i++) {
+      if (a[i] != b[i]) throw "index $i for $a vs $b";
+    }
+  }
+
+  void performTest(
+      {required Registry registry,
+      required int runs,
+      required int iterations,
+      required Map<Scenario, InputOutputData<T>> scenarios}) {
+    for (MapEntry<Scenario, InputOutputData<T>> scenario in scenarios.entries) {
+      List<T> scenarioInput = scenario.value.input;
+      List<T> scenarioExpectedOutput = scenario.value.output;
+      for (MapEntry<Strategy, TestFunction<T>> entry in strategies.entries) {
+        _test(registry, new SeriesKey(entry.key, scenario.key), runs,
+            iterations, scenarioInput, scenarioExpectedOutput, entry.value);
+      }
+    }
+  }
+}
+
+List<Test<String>> tests = [
+  // "size" isn't used here...
+  Test<String>(-1, {
+    simpleAddStrategy: simplyAdd,
+    listGenerateGrowableStrategy: listGenerateGrowable,
+    listGenerateNotGrowableStrategy: listGenerateNotGrowable,
+    listFilledGrowableStrategy: listFilledGrowable,
+    listFilledNotGrowableStrategy: listFilledNotGrowable,
+    listFilledAlternativeGrowableStrategy: listFilledAlternativeGrowable,
+    listFilledAlternativeNotGrowableStrategy: listFilledAlternativeNotGrowable,
+    spreadStrategy: spread,
+  }),
+];
+
+List<String> simplyAdd(List<String> input) {
+  if (input.isEmpty) return [];
+  List<String> result = [];
+  result.add("<");
+  result.add(input[0]);
+  for (int i = 1; i < input.length; i++) {
+    result.add(", ");
+    result.add(input[i]);
+  }
+  result.add(">");
+  return result;
+}
+
+List<String> listGenerateGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  return List<String>.generate(size, (index) {
+    if (index == 0) return "<";
+    if (index == size - 1) return ">";
+    if (index.isEven) return ", ";
+    return input[index >> 1];
+  }, growable: true);
+}
+
+List<String> listGenerateNotGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  return List<String>.generate(size, (index) {
+    if (index == 0) return "<";
+    if (index == size - 1) return ">";
+    if (index.isEven) return ", ";
+    return input[index >> 1];
+  }, growable: false);
+}
+
+List<String> listFilledAlternativeGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  List<String> result = List<String>.filled(size, ", ", growable: true);
+  for (int i = 0; i < input.length; i++) {
+    result[(i << 1) + 1] = input[i];
+  }
+  result[0] = "<";
+  result[result.length - 1] = ">";
+
+  return result;
+}
+
+List<String> listFilledAlternativeNotGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  List<String> result = List<String>.filled(size, ", ", growable: false);
+  for (int i = 0; i < input.length; i++) {
+    result[(i << 1) + 1] = input[i];
+  }
+  result[0] = "<";
+  result[result.length - 1] = ">";
+
+  return result;
+}
+
+List<String> listFilledGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  List<String> result = List<String>.filled(size, "", growable: true);
+  int j = 0;
+  result[j++] = "<";
+  result[j++] = input[0];
+  for (int i = 1; i < input.length; i++) {
+    result[j++] = ", ";
+    result[j++] = input[i];
+  }
+  result[j++] = ">";
+
+  return result;
+}
+
+List<String> listFilledNotGrowable(List<String> input) {
+  if (input.isEmpty) return [];
+  int size = input.length * 2 + 1;
+  List<String> result = List<String>.filled(size, "", growable: false);
+  int j = 0;
+  result[j++] = "<";
+  result[j++] = input[0];
+  for (int i = 1; i < input.length; i++) {
+    result[j++] = ", ";
+    result[j++] = input[i];
+  }
+  result[j++] = ">";
+
+  return result;
+}
+
+List<String> spread(List<String> input) {
+  return [
+    if (input.isNotEmpty) ...[
+      '<',
+      input.first,
+      for (String s in input.skip(1)) ...[', ', s],
+      '>',
+    ]
+  ];
+}
+
+void main() {
+  // Dry run
+  for (Test test in tests) {
+    test.performTest(
+        registry: new Registry(),
+        runs: 5,
+        iterations: 10,
+        scenarios: scenarios);
+  }
+  // Actual test
+  Registry registry = new Registry();
+  for (Test test in tests) {
+    test.performTest(
+        registry: registry, runs: 10, iterations: 100000, scenarios: scenarios);
+  }
+  SeriesSet seriesSet = registry.generateSeriesSet();
+  print('== Raw data ==');
+  for (Scenario scenario in scenarios.keys) {
+    print(seriesSet.getFullSpreadByScenario(scenario));
+  }
+  print('== Reduced averages ==');
+  SeriesSet reducedSeriesSet = seriesSet.filter((list) => removeMax(list, 3));
+  for (Scenario scenario in scenarios.keys) {
+    print(reducedSeriesSet.getAveragedSpreadByScenario(scenario));
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/test_lists_from_vs_of.dart b/pkg/front_end/benchmarks/patterns/test_lists_from_vs_of.dart
new file mode 100644
index 0000000..0ebf6da
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/test_lists_from_vs_of.dart
@@ -0,0 +1,138 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'util.dart';
+
+typedef TestFunction<T> = List<T> Function(List<T>);
+
+class InputOutputData<T> {
+  final List<T> input;
+  final List<T> output;
+
+  const InputOutputData(this.input, this.output);
+}
+
+const Strategy fromStrategy = Strategy('from', '''
+Using List.from.''');
+
+const Strategy ofStrategy = Strategy('of', '''
+Using List.of.''');
+
+const Scenario emptyScenario = Scenario('empty', '''
+The input and output is empty.''');
+const Scenario oneEntryScenario = Scenario('one', '''
+The input is one entry.''');
+const Scenario severalEntriesScenario = Scenario('several', '''
+The input has several entries.''');
+
+Map<Scenario, InputOutputData<String>> scenarios = {
+  emptyScenario: const InputOutputData([], []),
+  oneEntryScenario: const InputOutputData(["a"], ["a"]),
+  severalEntriesScenario: const InputOutputData(
+    [
+      "a",
+      "b",
+      "c",
+      "d",
+      "e",
+      "f",
+      "g",
+    ],
+    [
+      "a",
+      "b",
+      "c",
+      "d",
+      "e",
+      "f",
+      "g",
+    ],
+  ),
+};
+
+class Test<T> {
+  final int size;
+  final Map<Strategy, TestFunction<T>> strategies;
+
+  const Test(this.size, this.strategies);
+
+  void _test(Registry registry, SeriesKey key, int runs, int iterations,
+      List<T> input, List<T> expectedResult, TestFunction<T> testFunction) {
+    for (int run = 0; run < runs; run++) {
+      Stopwatch sw = new Stopwatch();
+      for (int i = 0; i < iterations; i++) {
+        sw.start();
+        List<T> actualOutput = testFunction(input);
+        sw.stop();
+        checkEquals(actualOutput, expectedResult);
+      }
+      registry.registerData(key, size, sw.elapsedMicroseconds);
+    }
+  }
+
+  void checkEquals(List<T> a, List<T> b) {
+    if (a.length != b.length) throw "length for $a vs $b";
+    for (int i = 0; i < a.length; i++) {
+      if (a[i] != b[i]) throw "index $i for $a vs $b";
+    }
+  }
+
+  void performTest(
+      {required Registry registry,
+      required int runs,
+      required int iterations,
+      required Map<Scenario, InputOutputData<T>> scenarios}) {
+    for (MapEntry<Scenario, InputOutputData<T>> scenario in scenarios.entries) {
+      List<T> scenarioInput = scenario.value.input;
+      List<T> scenarioExpectedOutput = scenario.value.output;
+      for (MapEntry<Strategy, TestFunction<T>> entry in strategies.entries) {
+        _test(registry, new SeriesKey(entry.key, scenario.key), runs,
+            iterations, scenarioInput, scenarioExpectedOutput, entry.value);
+      }
+    }
+  }
+}
+
+List<Test<String>> tests = [
+  // "size" isn't used here...
+  Test<String>(-1, {
+    fromStrategy: from,
+    ofStrategy: of,
+  }),
+];
+
+List<String> from(List<String> input) {
+  return new List<String>.from(input);
+}
+
+List<String> of(List<String> input) {
+  return new List<String>.of(input);
+}
+
+void main() {
+  // Dry run
+  for (Test test in tests) {
+    test.performTest(
+        registry: new Registry(),
+        runs: 5,
+        iterations: 10,
+        scenarios: scenarios);
+  }
+  // Actual test
+  Registry registry = new Registry();
+  for (Test test in tests) {
+    test.performTest(
+        registry: registry, runs: 10, iterations: 200000, scenarios: scenarios);
+  }
+  SeriesSet seriesSet = registry.generateSeriesSet();
+  print('== Raw data ==');
+  for (Scenario scenario in scenarios.keys) {
+    print(seriesSet.getFullSpreadByScenario(scenario));
+  }
+  print('== Reduced averages ==');
+  SeriesSet reducedSeriesSet = seriesSet.filter((list) => removeMax(list, 3));
+  for (Scenario scenario in scenarios.keys) {
+    print(reducedSeriesSet.getAveragedSpreadByScenario(scenario));
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/test_map_a_list.dart b/pkg/front_end/benchmarks/patterns/test_map_a_list.dart
new file mode 100644
index 0000000..d611a0e
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/test_map_a_list.dart
@@ -0,0 +1,192 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'util.dart';
+
+typedef TestFunction<T, U> = List<U> Function(List<T>);
+
+class InputOutputData<T, U> {
+  final List<T> input;
+  final List<U> output;
+
+  const InputOutputData(this.input, this.output);
+}
+
+const Strategy simpleAddStrategy = Strategy('simple-add', '''
+Add entries to a list one at a time.''');
+
+const Strategy mapToListStrategy = Strategy('mapToList', '''
+Create the list via .map([...]).toList().''');
+
+const Strategy listGenerateGrowableStrategy =
+    Strategy('list-generate-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listGenerateNotGrowableStrategy =
+    Strategy('list-generate-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Strategy listFilledGrowableStrategy = Strategy('list-filled-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listFilledNotGrowableStrategy =
+    Strategy('list-filled-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Scenario emptyScenario = Scenario('empty', '''
+The input and output is empty.''');
+const Scenario oneEntryScenario = Scenario('one', '''
+The input is one entry.''');
+const Scenario severalEntriesScenario = Scenario('several', '''
+The input has several entries.''');
+
+class Input {
+  final String content;
+
+  const Input(this.content);
+}
+
+Map<Scenario, InputOutputData<Input, String>> scenarios = {
+  emptyScenario: const InputOutputData([], []),
+  oneEntryScenario: const InputOutputData([Input("a")], ["a"]),
+  severalEntriesScenario: const InputOutputData(
+    [
+      Input("a"),
+      Input("b"),
+      Input("c"),
+      Input("d"),
+      Input("e"),
+      Input("f"),
+    ],
+    [
+      "a",
+      "b",
+      "c",
+      "d",
+      "e",
+      "f",
+    ],
+  ),
+};
+
+class Test<T, U> {
+  final int size;
+  final Map<Strategy, TestFunction<T, U>> strategies;
+
+  const Test(this.size, this.strategies);
+
+  void _test(Registry registry, SeriesKey key, int runs, int iterations,
+      List<T> input, List<U> expectedResult, TestFunction<T, U> testFunction) {
+    for (int run = 0; run < runs; run++) {
+      Stopwatch sw = new Stopwatch();
+      for (int i = 0; i < iterations; i++) {
+        sw.start();
+        List<U> actualOutput = testFunction(input);
+        sw.stop();
+        checkEquals(actualOutput, expectedResult);
+      }
+      registry.registerData(key, size, sw.elapsedMicroseconds);
+    }
+  }
+
+  void checkEquals(List<U> a, List<U> b) {
+    if (a.length != b.length) throw "length for $a vs $b";
+    for (int i = 0; i < a.length; i++) {
+      if (a[i] != b[i]) throw "index $i for $a vs $b";
+    }
+  }
+
+  void performTest(
+      {required Registry registry,
+      required int runs,
+      required int iterations,
+      required Map<Scenario, InputOutputData<T, U>> scenarios}) {
+    for (MapEntry<Scenario, InputOutputData<T, U>> scenario
+        in scenarios.entries) {
+      List<T> scenarioInput = scenario.value.input;
+      List<U> scenarioExpectedOutput = scenario.value.output;
+      for (MapEntry<Strategy, TestFunction<T, U>> entry in strategies.entries) {
+        _test(registry, new SeriesKey(entry.key, scenario.key), runs,
+            iterations, scenarioInput, scenarioExpectedOutput, entry.value);
+      }
+    }
+  }
+}
+
+List<Test<Input, String>> tests = [
+  // "size" isn't used here...
+  Test<Input, String>(-1, {
+    simpleAddStrategy: simplyAdd,
+    listGenerateGrowableStrategy: listGenerateGrowable,
+    listGenerateNotGrowableStrategy: listGenerateNotGrowable,
+    listFilledGrowableStrategy: listFilledGrowable,
+    listFilledNotGrowableStrategy: listFilledNotGrowable,
+    mapToListStrategy: mapToList,
+  }),
+];
+
+List<String> simplyAdd(List<Input> input) {
+  List<String> result = [];
+  for (int i = 0; i < input.length; i++) {
+    result.add(input[i].content);
+  }
+  return result;
+}
+
+List<String> listGenerateGrowable(List<Input> input) {
+  return List<String>.generate(input.length, (index) => input[index].content,
+      growable: true);
+}
+
+List<String> listGenerateNotGrowable(List<Input> input) {
+  return List<String>.generate(input.length, (index) => input[index].content,
+      growable: false);
+}
+
+List<String> listFilledGrowable(List<Input> input) {
+  List<String> result = List<String>.filled(input.length, "", growable: true);
+  for (int i = 0; i < input.length; i++) {
+    result[i] = input[i].content;
+  }
+  return result;
+}
+
+List<String> listFilledNotGrowable(List<Input> input) {
+  List<String> result = List<String>.filled(input.length, "", growable: false);
+  for (int i = 0; i < input.length; i++) {
+    result[i] = input[i].content;
+  }
+  return result;
+}
+
+List<String> mapToList(List<Input> input) {
+  return input.map((e) => e.content).toList();
+}
+
+void main() {
+  // Dry run
+  for (Test test in tests) {
+    test.performTest(
+        registry: new Registry(),
+        runs: 5,
+        iterations: 10,
+        scenarios: scenarios);
+  }
+  // Actual test
+  Registry registry = new Registry();
+  for (Test test in tests) {
+    test.performTest(
+        registry: registry, runs: 10, iterations: 100000, scenarios: scenarios);
+  }
+  SeriesSet seriesSet = registry.generateSeriesSet();
+  print('== Raw data ==');
+  for (Scenario scenario in scenarios.keys) {
+    print(seriesSet.getFullSpreadByScenario(scenario));
+  }
+  print('== Reduced averages ==');
+  SeriesSet reducedSeriesSet = seriesSet.filter((list) => removeMax(list, 3));
+  for (Scenario scenario in scenarios.keys) {
+    print(reducedSeriesSet.getAveragedSpreadByScenario(scenario));
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/test_sets_from_list_mapping.dart b/pkg/front_end/benchmarks/patterns/test_sets_from_list_mapping.dart
new file mode 100644
index 0000000..7bffec6
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/test_sets_from_list_mapping.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'util.dart';
+
+typedef TestFunction<T, U> = Set<U> Function(List<T>);
+
+class InputOutputData<T, U> {
+  final List<T> input;
+  final Set<U> output;
+
+  const InputOutputData(this.input, this.output);
+}
+
+const Strategy simpleAddStrategy = Strategy('simple-add', '''
+Add entries to a list one at a time.''');
+
+const Strategy mapToSetStrategy = Strategy('mapToSet', '''
+Create the set via new Set.from([...].map([...]).''');
+
+const Strategy listGenerateGrowableStrategy =
+    Strategy('list-generate-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listGenerateNotGrowableStrategy =
+    Strategy('list-generate-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Strategy listFilledGrowableStrategy = Strategy('list-filled-growable', '''
+Create list via List.generate with growable = true.''');
+
+const Strategy listFilledNotGrowableStrategy =
+    Strategy('list-filled-not-growable', '''
+Create list via List.generate with growable = false.''');
+
+const Scenario emptyScenario = Scenario('empty', '''
+The input and output is empty.''');
+const Scenario oneEntryScenario = Scenario('one', '''
+The input is one entry.''');
+const Scenario severalEntriesScenario = Scenario('several', '''
+The input has several entries.''');
+
+class Input {
+  final String content;
+
+  const Input(this.content);
+}
+
+Map<Scenario, InputOutputData<Input, String>> scenarios = {
+  emptyScenario: const InputOutputData([], {}),
+  oneEntryScenario: const InputOutputData([Input("a")], {"a"}),
+  severalEntriesScenario: const InputOutputData(
+    [
+      Input("a"),
+      Input("b"),
+      Input("c"),
+      Input("d"),
+      Input("e"),
+      Input("f"),
+    ],
+    {
+      "a",
+      "b",
+      "c",
+      "d",
+      "e",
+      "f",
+    },
+  ),
+};
+
+class Test<T, U> {
+  final int size;
+  final Map<Strategy, TestFunction<T, U>> strategies;
+
+  const Test(this.size, this.strategies);
+
+  void _test(Registry registry, SeriesKey key, int runs, int iterations,
+      List<T> input, Set<U> expectedResult, TestFunction<T, U> testFunction) {
+    for (int run = 0; run < runs; run++) {
+      Stopwatch sw = new Stopwatch();
+      for (int i = 0; i < iterations; i++) {
+        sw.start();
+        Set<U> actualOutput = testFunction(input);
+        sw.stop();
+        checkEquals(actualOutput, expectedResult);
+      }
+      registry.registerData(key, size, sw.elapsedMicroseconds);
+    }
+  }
+
+  void checkEquals(Set<U> a, Set<U> b) {
+    if (a.length != b.length) throw "length for $a vs $b";
+    Set<U> copy = new Set<U>.of(a);
+    copy.removeAll(b);
+    if (copy.isNotEmpty) throw "Not same content";
+  }
+
+  void performTest(
+      {required Registry registry,
+      required int runs,
+      required int iterations,
+      required Map<Scenario, InputOutputData<T, U>> scenarios}) {
+    for (MapEntry<Scenario, InputOutputData<T, U>> scenario
+        in scenarios.entries) {
+      List<T> scenarioInput = scenario.value.input;
+      Set<U> scenarioExpectedOutput = scenario.value.output;
+      for (MapEntry<Strategy, TestFunction<T, U>> entry in strategies.entries) {
+        _test(registry, new SeriesKey(entry.key, scenario.key), runs,
+            iterations, scenarioInput, scenarioExpectedOutput, entry.value);
+      }
+    }
+  }
+}
+
+List<Test<Input, String>> tests = [
+  // "size" isn't used here...
+  Test<Input, String>(-1, {
+    simpleAddStrategy: simplyAdd,
+    listGenerateGrowableStrategy: listGenerateGrowable,
+    listGenerateNotGrowableStrategy: listGenerateNotGrowable,
+    listFilledGrowableStrategy: listFilledGrowable,
+    listFilledNotGrowableStrategy: listFilledNotGrowable,
+    mapToSetStrategy: mapToSet,
+  }),
+];
+
+Set<String> simplyAdd(List<Input> input) {
+  Set<String> result = {};
+  for (int i = 0; i < input.length; i++) {
+    result.add(input[i].content);
+  }
+  return result;
+}
+
+Set<String> listGenerateGrowable(List<Input> input) {
+  return Set<String>.from(List<String>.generate(
+      input.length, (index) => input[index].content,
+      growable: true));
+}
+
+Set<String> listGenerateNotGrowable(List<Input> input) {
+  return Set<String>.from(List<String>.generate(
+      input.length, (index) => input[index].content,
+      growable: false));
+}
+
+Set<String> listFilledGrowable(List<Input> input) {
+  List<String> result = List<String>.filled(input.length, "", growable: true);
+  for (int i = 0; i < input.length; i++) {
+    result[i] = input[i].content;
+  }
+  return Set<String>.from(result);
+}
+
+Set<String> listFilledNotGrowable(List<Input> input) {
+  List<String> result = List<String>.filled(input.length, "", growable: false);
+  for (int i = 0; i < input.length; i++) {
+    result[i] = input[i].content;
+  }
+  return Set<String>.from(result);
+}
+
+Set<String> mapToSet(List<Input> input) {
+  return new Set<String>.from(input.map((e) => e.content));
+}
+
+void main() {
+  // Dry run
+  for (Test test in tests) {
+    test.performTest(
+        registry: new Registry(),
+        runs: 5,
+        iterations: 10,
+        scenarios: scenarios);
+  }
+  // Actual test
+  Registry registry = new Registry();
+  for (Test test in tests) {
+    test.performTest(
+        registry: registry, runs: 10, iterations: 100000, scenarios: scenarios);
+  }
+  SeriesSet seriesSet = registry.generateSeriesSet();
+  print('== Raw data ==');
+  for (Scenario scenario in scenarios.keys) {
+    print(seriesSet.getFullSpreadByScenario(scenario));
+  }
+  print('== Reduced averages ==');
+  SeriesSet reducedSeriesSet = seriesSet.filter((list) => removeMax(list, 3));
+  for (Scenario scenario in scenarios.keys) {
+    print(reducedSeriesSet.getAveragedSpreadByScenario(scenario));
+  }
+}
diff --git a/pkg/front_end/benchmarks/patterns/util.dart b/pkg/front_end/benchmarks/patterns/util.dart
new file mode 100644
index 0000000..6c7d3af
--- /dev/null
+++ b/pkg/front_end/benchmarks/patterns/util.dart
@@ -0,0 +1,233 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:math' as math;
+import '../../test/simple_stats.dart';
+
+/// Key used for a strategy in a test setup.
+class Strategy {
+  /// The short name of the strategy used in printouts.
+  final String name;
+
+  /// A full description of the strategy.
+  final String description;
+
+  const Strategy(this.name, this.description);
+
+  @override
+  int get hashCode => name.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is Strategy && name == other.name;
+  }
+
+  @override
+  String toString() => 'Strategy($name)';
+}
+
+/// Key used for a scenario used when running a test.
+class Scenario {
+  /// The short name of the scenario used in printouts.
+  final String name;
+
+  /// A full description of the scenario.
+  final String description;
+
+  const Scenario(this.name, this.description);
+
+  @override
+  int get hashCode => name.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is Scenario && name == other.name;
+  }
+
+  @override
+  String toString() => 'Strategy($name)';
+}
+
+/// The values that constitutes the input size values of the test.
+class XAxis {
+  final List<num> values;
+
+  XAxis(this.values);
+}
+
+/// Key for a strategy/scenario pair.
+class SeriesKey {
+  final Strategy strategy;
+  final Scenario scenario;
+
+  const SeriesKey(this.strategy, this.scenario);
+
+  @override
+  int get hashCode => strategy.hashCode * 13 + scenario.hashCode * 17;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is SeriesKey &&
+        strategy == other.strategy &&
+        scenario == other.scenario;
+  }
+
+  @override
+  String toString() => 'SeriesKey($strategy,$scenario)';
+}
+
+/// Data collected for running one strategy using one scenario.
+class Series {
+  /// The key that identifiers this series.
+  final SeriesKey key;
+
+  /// The x-axis values corresponding the [values].
+  final XAxis xAxis;
+
+  /// The measured values. The indices of the outer list corresponds to the
+  /// indices of the [xAxis]. The size of the inner list is the number
+  /// measurements performed for that x-value.
+  final List<List<num>> values;
+
+  Series(this.key, this.xAxis, this.values);
+
+  /// Returns a new [Series] where measurements have been removed using
+  /// [filter].
+  ///
+  /// This can for instance be used to remove outliers from the measurements.
+  Series filter(List<num> filter(List<num> list)) {
+    List<List<num>> filteredValues = [];
+    for (List<num> list in values) {
+      filteredValues.add(filter(list));
+    }
+    return new Series(key, xAxis, filteredValues);
+  }
+}
+
+/// A full set of series collected for a set of strategies and scenarios.
+class SeriesSet {
+  /// The shared x-axis of all series in [seriesList].
+  final XAxis xAxis;
+
+  /// All collected [Series].
+  final List<Series> seriesList;
+
+  SeriesSet(this.xAxis, this.seriesList);
+
+  /// Returns a new [SeriesSet] where measurements have been removed using
+  /// [filter].
+  ///
+  /// This can for instance be used to remove outliers from the measurements.
+  SeriesSet filter(List<num> filter(List<num> list)) {
+    List<Series> filteredSeries = [];
+    for (Series series in this.seriesList) {
+      filteredSeries.add(series.filter(filter));
+    }
+    return new SeriesSet(xAxis, filteredSeries);
+  }
+
+  /// Returns a tab-based table of the averages of all measurements for a given
+  /// [scenario].
+  String getAveragedSpreadByScenario(Scenario scenario) {
+    Map<Series, List<num>> stats = {};
+    for (Series series in this.seriesList) {
+      if (series.key.scenario != scenario) continue;
+      stats[series] = series.values
+          .map((data) => SimpleTTestStat.average(data))
+          .toList(growable: false);
+    }
+    StringBuffer sb = new StringBuffer();
+    sb.write(scenario.name);
+    for (Series series in stats.keys) {
+      sb.write('\t${series.key.strategy.name}');
+    }
+    sb.writeln();
+    for (int index = 0; index < xAxis.values.length; index++) {
+      sb.write(xAxis.values[index]);
+      for (List<num> stat in stats.values) {
+        sb.write('\t');
+        sb.write(stat[index]);
+      }
+      sb.writeln();
+    }
+    return sb.toString();
+  }
+
+  /// Returns a tab-based table of all measurements for a given [scenario].
+  String getFullSpreadByScenario(Scenario scenario) {
+    List<Series> seriesList = [];
+    for (Series series in this.seriesList) {
+      if (series.key.scenario != scenario) continue;
+      seriesList.add(series);
+    }
+    StringBuffer sb = new StringBuffer();
+    sb.write(scenario.name);
+    for (Series series in seriesList) {
+      int columns = series.values.map((l) => l.length).reduce(math.max);
+      sb.write('\t${series.key.strategy.name}');
+      for (int i = 0; i < columns; i++) {
+        sb.write('\t');
+      }
+    }
+    sb.writeln();
+    for (int index = 0; index < xAxis.values.length; index++) {
+      sb.write(xAxis.values[index]);
+      for (Series series in seriesList) {
+        List<num> values = series.values[index];
+        for (int i = 0; i < values.length; i++) {
+          sb.write('\t${values[i]}');
+        }
+      }
+      sb.writeln();
+    }
+    return sb.toString();
+  }
+}
+
+/// Registry used to collect data during measurement.
+class Registry {
+  final Set<num> _xAxisSet = {};
+  final Map<SeriesKey, Map<num, List<num>>> _seriesMap = {};
+
+  /// Registers the measurement of [y] for the given [x] value under the
+  /// strategy/scenario defined by [key].
+  void registerData(SeriesKey key, num x, num y) {
+    _xAxisSet.add(x);
+    ((_seriesMap[key] ??= {})[x] ??= []).add(y);
+  }
+
+  /// Generates [SeriesSet] for all collected measurements.
+  SeriesSet generateSeriesSet() {
+    XAxis xAxis = new XAxis(_xAxisSet.toList(growable: false)..sort());
+    List<Series> series = [];
+    for (MapEntry<SeriesKey, Map<num, List<num>>> entry in _seriesMap.entries) {
+      SeriesKey key = entry.key;
+      Map<num, List<num>> valuesMap = entry.value;
+      List<List<num>> values = [];
+      for (num x in xAxis.values) {
+        values.add(valuesMap[x] ?? []);
+      }
+      series.add(new Series(key, xAxis, values));
+    }
+    _xAxisSet.clear();
+    _seriesMap.clear();
+    return new SeriesSet(xAxis, series);
+  }
+}
+
+/// Filter function that removes the max [removeMaxCount] values from a list.
+///
+/// This can be used in [Series.filter] and [SeriesSet.filter] to remove
+/// outliers from a set of measurements.
+List<num> removeMax(List<num> list, int removeMaxCount) {
+  if (removeMaxCount == 0) return list;
+  List<num> copy = list.toList()..sort();
+  for (int i = 0; i < removeMaxCount; i++) {
+    copy.removeLast();
+  }
+  return copy;
+}
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 e1b7997..a8355e8 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -4,6 +4,7 @@
 
 library front_end.compiler_options;
 
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, DiagnosticMessageHandler;
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
@@ -17,6 +18,7 @@
 
 import '../base/nnbd_mode.dart';
 
+import '../fasta/kernel/macro.dart';
 import 'experimental_flags.dart'
     show
         AllowedExperimentalFlags,
@@ -109,6 +111,18 @@
   /// file system.  TODO(paulberry): fix this.
   FileSystem fileSystem = StandardFileSystem.instance;
 
+  /// Function that creates a [MacroExecutor] if supported.
+  ///
+  /// This is an experimental feature.
+  Future<MacroExecutor> Function() macroExecutorProvider =
+      () async => throw 'Macro execution is not supported.';
+
+  /// Map from [MacroClass] to [Uri] for the precompiled dill that contains
+  /// the macro code.
+  ///
+  /// This is an experimental feature.
+  Map<MacroClass, Uri>? precompiledMacroUris;
+
   /// Whether to generate code for the SDK.
   ///
   /// By default the front end resolves components using a prebuilt SDK summary.
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 4dd9122..1a8f894 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -33,26 +33,26 @@
 }
 
 const Version enableAlternativeInvalidationStrategyVersion =
-    const Version(2, 16);
-const Version enableConstFunctionsVersion = const Version(2, 16);
+    const Version(2, 17);
+const Version enableConstFunctionsVersion = const Version(2, 17);
 const Version enableConstantUpdate2018Version = const Version(2, 0);
 const Version enableConstructorTearoffsVersion = const Version(2, 15);
 const Version enableControlFlowCollectionsVersion = const Version(2, 0);
-const Version enableEnhancedEnumsVersion = const Version(2, 16);
+const Version enableEnhancedEnumsVersion = const Version(2, 17);
 const Version enableExtensionMethodsVersion = const Version(2, 6);
-const Version enableExtensionTypesVersion = const Version(2, 16);
+const Version enableExtensionTypesVersion = const Version(2, 17);
 const Version enableGenericMetadataVersion = const Version(2, 14);
-const Version enableMacrosVersion = const Version(2, 16);
-const Version enableNamedArgumentsAnywhereVersion = const Version(2, 16);
+const Version enableMacrosVersion = const Version(2, 17);
+const Version enableNamedArgumentsAnywhereVersion = const Version(2, 17);
 const Version enableNonNullableVersion = const Version(2, 12);
 const Version enableNonfunctionTypeAliasesVersion = const Version(2, 13);
 const Version enableSetLiteralsVersion = const Version(2, 0);
 const Version enableSpreadCollectionsVersion = const Version(2, 0);
-const Version enableSuperParametersVersion = const Version(2, 16);
-const Version enableTestExperimentVersion = const Version(2, 16);
+const Version enableSuperParametersVersion = const Version(2, 17);
+const Version enableTestExperimentVersion = const Version(2, 17);
 const Version enableTripleShiftVersion = const Version(2, 14);
-const Version enableValueClassVersion = const Version(2, 16);
-const Version enableVarianceVersion = const Version(2, 16);
+const Version enableValueClassVersion = const Version(2, 17);
+const Version enableVarianceVersion = const Version(2, 17);
 
 ExperimentalFlag? parseExperimentalFlag(String flag) {
   switch (flag) {
@@ -127,7 +127,7 @@
   ExperimentalFlag.alternativeInvalidationStrategy: false,
   ExperimentalFlag.constFunctions: false,
   ExperimentalFlag.constantUpdate2018: true,
-  ExperimentalFlag.constructorTearoffs: false,
+  ExperimentalFlag.constructorTearoffs: true,
   ExperimentalFlag.controlFlowCollections: true,
   ExperimentalFlag.enhancedEnums: false,
   ExperimentalFlag.extensionMethods: true,
@@ -147,49 +147,49 @@
 };
 
 const Map<ExperimentalFlag, Version> experimentEnabledVersion = {
-  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 16),
-  ExperimentalFlag.constFunctions: const Version(2, 16),
+  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 17),
+  ExperimentalFlag.constFunctions: const Version(2, 17),
   ExperimentalFlag.constantUpdate2018: const Version(2, 0),
   ExperimentalFlag.constructorTearoffs: const Version(2, 15),
   ExperimentalFlag.controlFlowCollections: const Version(2, 0),
-  ExperimentalFlag.enhancedEnums: const Version(2, 16),
+  ExperimentalFlag.enhancedEnums: const Version(2, 17),
   ExperimentalFlag.extensionMethods: const Version(2, 6),
-  ExperimentalFlag.extensionTypes: const Version(2, 16),
+  ExperimentalFlag.extensionTypes: const Version(2, 17),
   ExperimentalFlag.genericMetadata: const Version(2, 14),
-  ExperimentalFlag.macros: const Version(2, 16),
-  ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 16),
+  ExperimentalFlag.macros: const Version(2, 17),
+  ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 17),
   ExperimentalFlag.nonNullable: const Version(2, 12),
   ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
   ExperimentalFlag.setLiterals: const Version(2, 0),
   ExperimentalFlag.spreadCollections: const Version(2, 0),
-  ExperimentalFlag.superParameters: const Version(2, 16),
-  ExperimentalFlag.testExperiment: const Version(2, 16),
+  ExperimentalFlag.superParameters: const Version(2, 17),
+  ExperimentalFlag.testExperiment: const Version(2, 17),
   ExperimentalFlag.tripleShift: const Version(2, 14),
-  ExperimentalFlag.valueClass: const Version(2, 16),
-  ExperimentalFlag.variance: const Version(2, 16),
+  ExperimentalFlag.valueClass: const Version(2, 17),
+  ExperimentalFlag.variance: const Version(2, 17),
 };
 
 const Map<ExperimentalFlag, Version> experimentReleasedVersion = {
-  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 16),
-  ExperimentalFlag.constFunctions: const Version(2, 16),
+  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 17),
+  ExperimentalFlag.constFunctions: const Version(2, 17),
   ExperimentalFlag.constantUpdate2018: const Version(2, 0),
   ExperimentalFlag.constructorTearoffs: const Version(2, 15),
   ExperimentalFlag.controlFlowCollections: const Version(2, 0),
-  ExperimentalFlag.enhancedEnums: const Version(2, 16),
+  ExperimentalFlag.enhancedEnums: const Version(2, 17),
   ExperimentalFlag.extensionMethods: const Version(2, 6),
-  ExperimentalFlag.extensionTypes: const Version(2, 16),
+  ExperimentalFlag.extensionTypes: const Version(2, 17),
   ExperimentalFlag.genericMetadata: const Version(2, 14),
-  ExperimentalFlag.macros: const Version(2, 16),
-  ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 16),
+  ExperimentalFlag.macros: const Version(2, 17),
+  ExperimentalFlag.namedArgumentsAnywhere: const Version(2, 17),
   ExperimentalFlag.nonNullable: const Version(2, 10),
   ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
   ExperimentalFlag.setLiterals: const Version(2, 0),
   ExperimentalFlag.spreadCollections: const Version(2, 0),
-  ExperimentalFlag.superParameters: const Version(2, 16),
-  ExperimentalFlag.testExperiment: const Version(2, 16),
+  ExperimentalFlag.superParameters: const Version(2, 17),
+  ExperimentalFlag.testExperiment: const Version(2, 17),
   ExperimentalFlag.tripleShift: const Version(2, 14),
-  ExperimentalFlag.valueClass: const Version(2, 16),
-  ExperimentalFlag.variance: const Version(2, 16),
+  ExperimentalFlag.valueClass: const Version(2, 17),
+  ExperimentalFlag.variance: const Version(2, 17),
 };
 
 const AllowedExperimentalFlags defaultAllowedExperimentalFlags =
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 18d185d..357b21f 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -12,9 +12,6 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show StringToken;
 
-import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart'
-    show LibrariesSpecification;
-
 import 'package:kernel/kernel.dart' show Component;
 
 import 'package:kernel/ast.dart' as ir;
@@ -217,26 +214,6 @@
   return compilerResult?.component;
 }
 
-/// Retrieve the name of the libraries that are supported by [target] according
-/// to the libraries specification [json] file.
-///
-/// Dart2js uses these names to determine the value of library environment
-/// constants, such as `const bool.fromEnvironment("dart.library.io")`.
-// TODO(sigmund): refactor dart2js so that we can retrieve this data later in
-// the compilation pipeline. At that point we can get it from the CFE
-// results directly and completely hide the libraries specification file from
-// dart2js.
-// TODO(sigmund): delete after all constant evaluation is done in the CFE, as
-// this data will no longer be needed on the dart2js side.
-Iterable<String> getSupportedLibraryNames(
-    Uri librariesSpecificationUri, String json, String target) {
-  return LibrariesSpecification.parse(librariesSpecificationUri, json)
-      .specificationFor(target)
-      .allLibraries
-      .where((l) => l.isSupported)
-      .map((l) => l.name);
-}
-
 /// Desugar API to determine whether [member] is a redirecting factory
 /// constructor.
 // TODO(sigmund): Delete this API once `member.isRedirectingFactory`
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 521d5ab..f8a8de9 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -8,6 +8,8 @@
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+
 import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart'
     show
         LibrariesSpecification,
@@ -68,6 +70,7 @@
         templateSdkSpecificationNotFound,
         templateSdkSummaryNotFound;
 
+import '../fasta/kernel/macro.dart';
 import '../fasta/messages.dart' show getLocation;
 
 import '../fasta/problems.dart' show DebugAbort, unimplemented;
@@ -531,12 +534,10 @@
       return new TargetLibrariesSpecification(name);
     }
 
-    String json = await fileSystem
-        .entityForUri(librariesSpecificationUri!)
-        .readAsString();
     try {
-      LibrariesSpecification spec =
-          await LibrariesSpecification.parse(librariesSpecificationUri!, json);
+      LibrariesSpecification spec = await LibrariesSpecification.load(
+          librariesSpecificationUri!,
+          (Uri uri) => fileSystem.entityForUri(uri).readAsString());
       return spec.specificationFor(name);
     } on LibrariesSpecificationException catch (e) {
       reportWithoutLocation(
@@ -854,6 +855,12 @@
     }
   }
 
+  Future<MacroExecutor> Function() get macroExecutorProvider =>
+      _raw.macroExecutorProvider;
+
+  Map<MacroClass, Uri> get precompiledMacroUris =>
+      _raw.precompiledMacroUris ?? const {};
+
   CompilerOptions get rawOptionsForTesting => _raw;
 }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index eb36433..05653ef 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -7,11 +7,8 @@
 import 'package:kernel/ast.dart'
     show
         Class,
-        Constructor,
         DartType,
         DynamicType,
-        FunctionNode,
-        FunctionType,
         FutureOrType,
         InterfaceType,
         Member,
@@ -19,68 +16,24 @@
         NullType,
         Nullability,
         Supertype,
-        TreeNode,
-        TypeParameter,
         getAsTypeArguments;
-
-import 'package:kernel/class_hierarchy.dart'
-    show ClassHierarchy, ClassHierarchyMembers;
-
-import 'package:kernel/core_types.dart' show CoreTypes;
-
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/src/legacy_erasure.dart';
 import 'package:kernel/text/text_serialization_verifier.dart';
 
-import 'package:kernel/type_algebra.dart' show Substitution, substitute;
-
-import 'package:kernel/type_environment.dart'
-    show SubtypeCheckMode, TypeEnvironment;
-
-import 'package:kernel/src/legacy_erasure.dart';
-
-import '../dill/dill_member_builder.dart';
-
 import '../fasta_codes.dart';
-
-import '../kernel/kernel_helper.dart';
-
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
-
-import '../loader.dart';
-
 import '../modifier.dart';
-
-import '../names.dart' show noSuchMethodName;
-
 import '../problems.dart' show internalProblem, unhandled;
-
 import '../scope.dart';
-
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import '../source/source_loader.dart';
-
 import '../type_inference/type_schema.dart' show UnknownType;
-
-import '../util/helpers.dart' show DelayedActionPerformer;
-
 import 'builder.dart';
-import 'constructor_builder.dart';
-import 'constructor_reference_builder.dart';
 import 'declaration_builder.dart';
-import 'field_builder.dart';
-import 'function_builder.dart';
 import 'library_builder.dart';
 import 'member_builder.dart';
 import 'metadata_builder.dart';
-import 'named_type_builder.dart';
-import 'never_type_declaration_builder.dart';
 import 'nullability_builder.dart';
-import 'factory_builder.dart';
-import 'type_alias_builder.dart';
 import 'type_builder.dart';
-import 'type_declaration_builder.dart';
 import 'type_variable_builder.dart';
-import 'void_type_declaration_builder.dart';
 
 abstract class ClassBuilder implements DeclarationBuilder {
   /// The type variables declared on a class, extension or mixin declaration.
@@ -102,13 +55,9 @@
 
   ConstructorScopeBuilder get constructorScopeBuilder;
 
-  abstract ClassBuilder? actualOrigin;
-
   @override
   Uri get fileUri;
 
-  ClassBuilder? get patchForTesting;
-
   bool get isAbstract;
 
   bool get isMacro;
@@ -123,28 +72,11 @@
 
   abstract TypeBuilder? mixedInTypeBuilder;
 
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes);
-
-  /// Registers a constructor redirection for this class and returns true if
-  /// this redirection gives rise to a cycle that has not been reported before.
-  bool checkConstructorCyclic(String source, String target);
-
   MemberBuilder? findConstructorOrFactory(
       String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary);
 
   void forEach(void f(String name, Builder builder));
 
-  void forEachDeclaredField(
-      void Function(String name, FieldBuilder fieldBuilder) f);
-
-  void forEachDeclaredConstructor(
-      void Function(String name, ConstructorBuilder constructorBuilder)
-          callback);
-
   /// The [Class] built by this builder.
   ///
   /// For a patch class the origin class is returned.
@@ -153,8 +85,6 @@
   @override
   ClassBuilder get origin;
 
-  Class get actualCls;
-
   abstract bool isNullClass;
 
   @override
@@ -177,50 +107,6 @@
   Supertype buildMixedInType(
       LibraryBuilder library, List<TypeBuilder>? arguments);
 
-  void checkSupertypes(CoreTypes coreTypes);
-
-  void handleSeenCovariant(
-      ClassHierarchyMembers memberHierarchy,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member interfaceMember, bool isSetter));
-
-  bool hasUserDefinedNoSuchMethod(
-      Class klass, ClassHierarchy hierarchy, Class objectClass);
-
-  void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes);
-
-  // Computes the function type of a given redirection target. Returns [null] if
-  // the type of the target could not be computed.
-  FunctionType? computeRedirecteeType(
-      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment);
-
-  String computeRedirecteeName(ConstructorReferenceBuilder redirectionTarget);
-
-  void checkRedirectingFactory(
-      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment);
-
-  void checkRedirectingFactories(TypeEnvironment typeEnvironment);
-
-  /// Returns a map which maps the type variables of [superclass] to their
-  /// respective values as defined by the superclass clause of this class (and
-  /// its superclasses).
-  ///
-  /// It's assumed that [superclass] is a superclass of this class.
-  ///
-  /// For example, given:
-  ///
-  ///     class Box<T> {}
-  ///     class BeatBox extends Box<Beat> {}
-  ///     class Beat {}
-  ///
-  /// We have:
-  ///
-  ///     [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
-  ///
-  /// It's an error if [superclass] isn't a superclass.
-  Map<TypeParameter, DartType> getSubstitutionMap(Class superclass);
-
   /// Looks up the member by [name] on the class built by this class builder.
   ///
   /// If [isSetter] is `false`, only fields, methods, and getters with that name
@@ -237,12 +123,6 @@
   Member? lookupInstanceMember(ClassHierarchy hierarchy, Name name,
       {bool isSetter: false, bool isSuper: false});
 
-  /// Looks up the constructor by [name] on the class built by this class
-  /// builder.
-  ///
-  /// If [isSuper] is `true`, constructors in the superclass are searched.
-  Constructor? lookupConstructor(Name name, {bool isSuper: false});
-
   /// Calls [f] for each constructor declared in this class.
   ///
   /// If [includeInjectedConstructors] is `true`, constructors only declared in
@@ -271,14 +151,6 @@
   @override
   final ConstructorScopeBuilder constructorScopeBuilder;
 
-  Map<String, ConstructorRedirection>? _redirectingConstructors;
-
-  @override
-  ClassBuilder? actualOrigin;
-
-  @override
-  ClassBuilder? get patchForTesting => _patchBuilder;
-
   @override
   bool isNullClass = false;
 
@@ -286,7 +158,6 @@
   InterfaceType? _nullableRawType;
   InterfaceType? _nonNullableRawType;
   InterfaceType? _thisType;
-  ClassBuilder? _patchBuilder;
 
   ClassBuilderImpl(
       List<MetadataBuilder>? metadata,
@@ -330,68 +201,6 @@
       (modifiers & declaresConstConstructorMask) != 0;
 
   @override
-  void forEachConstructor(void Function(String, MemberBuilder) f,
-      {bool includeInjectedConstructors: false}) {
-    if (isPatch) {
-      actualOrigin!.forEachConstructor(f,
-          includeInjectedConstructors: includeInjectedConstructors);
-    } else {
-      constructors.forEach(f);
-      if (includeInjectedConstructors) {
-        _patchBuilder?.constructors
-            .forEach((String name, MemberBuilder builder) {
-          if (!builder.isPatch) {
-            f(name, builder);
-          }
-        });
-      }
-    }
-  }
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    void build(String ignore, Builder declaration) {
-      MemberBuilder member = declaration as MemberBuilder;
-      member.buildOutlineExpressions(library, coreTypes,
-          delayedActionPerformers, synthesizedFunctionNodes);
-    }
-
-    MetadataBuilder.buildAnnotations(isPatch ? origin.cls : cls, metadata,
-        library, this, null, fileUri, library.scope);
-    if (typeVariables != null) {
-      for (int i = 0; i < typeVariables!.length; i++) {
-        typeVariables![i].buildOutlineExpressions(library, this, null,
-            coreTypes, delayedActionPerformers, scope.parent!);
-      }
-    }
-
-    constructors.forEach(build);
-    scope.forEach(build);
-  }
-
-  /// Registers a constructor redirection for this class and returns true if
-  /// this redirection gives rise to a cycle that has not been reported before.
-  @override
-  bool checkConstructorCyclic(String source, String target) {
-    ConstructorRedirection? redirect = new ConstructorRedirection(target);
-    _redirectingConstructors ??= <String, ConstructorRedirection>{};
-    _redirectingConstructors![source] = redirect;
-    while (redirect != null) {
-      if (redirect.cycleReported) return false;
-      if (redirect.target == source) {
-        redirect.cycleReported = true;
-        return true;
-      }
-      redirect = _redirectingConstructors![redirect.target];
-    }
-    return false;
-  }
-
-  @override
   Builder? findStaticBuilder(
       String name, int charOffset, Uri fileUri, LibraryBuilder accessingLibrary,
       {bool isSetter: false}) {
@@ -434,56 +243,6 @@
   }
 
   @override
-  void forEachDeclaredField(
-      void Function(String name, FieldBuilder fieldBuilder) callback) {
-    void callbackFilteringFieldBuilders(String name, Builder builder) {
-      if (builder is FieldBuilder) {
-        callback(name, builder);
-      }
-    }
-
-    // Currently, fields can't be patched, but can be injected.  When the fields
-    // will be made available for patching, the following code should iterate
-    // first over the fields from the patch and then -- over the fields in the
-    // original declaration, filtering out the patched fields.  For now, the
-    // assert checks that the names of the fields from the original declaration
-    // and from the patch don't intersect.
-    assert(
-        _patchBuilder == null ||
-            _patchBuilder!.scope.localMembers
-                .where((b) => b is FieldBuilder)
-                .map((b) => (b as FieldBuilder).name)
-                .toSet()
-                .intersection(scope.localMembers
-                    .where((b) => b is FieldBuilder)
-                    .map((b) => (b as FieldBuilder).name)
-                    .toSet())
-                .isEmpty,
-        "Detected an attempt to patch a field.");
-    _patchBuilder?.scope.forEach(callbackFilteringFieldBuilders);
-    scope.forEach(callbackFilteringFieldBuilders);
-  }
-
-  @override
-  void forEachDeclaredConstructor(
-      void Function(String name, ConstructorBuilder constructorBuilder)
-          callback) {
-    Set<String> visitedConstructorNames = {};
-    void callbackFilteringFieldBuilders(String name, Builder builder) {
-      if (builder is ConstructorBuilder &&
-          visitedConstructorNames.add(builder.name)) {
-        callback(name, builder);
-      }
-    }
-
-    // Constructors can be patched, so iterate first over constructors in the
-    // patch, and then over constructors in the original declaration skipping
-    // those with the names that are in the patch.
-    _patchBuilder?.constructors.forEach(callbackFilteringFieldBuilders);
-    constructors.forEach(callbackFilteringFieldBuilders);
-  }
-
-  @override
   Builder? lookupLocalMember(String name,
       {bool setter: false, bool required: false}) {
     Builder? builder = scope.lookupLocalMember(name, setter: setter);
@@ -518,9 +277,6 @@
   }
 
   @override
-  ClassBuilder get origin => actualOrigin ?? this;
-
-  @override
   InterfaceType get thisType {
     return _thisType ??= new InterfaceType(cls, library.nonNullable,
         getAsTypeArguments(cls.typeParameters, library.library));
@@ -582,44 +338,6 @@
   }
 
   @override
-  int get typeVariablesCount => typeVariables?.length ?? 0;
-
-  @override
-  List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder>? arguments) {
-    if (arguments == null && typeVariables == null) {
-      return <DartType>[];
-    }
-
-    if (arguments == null && typeVariables != null) {
-      List<DartType> result = new List<DartType>.generate(typeVariables!.length,
-          (int i) => typeVariables![i].defaultType!.build(library),
-          growable: true);
-      if (library is SourceLibraryBuilder) {
-        library.inferredTypes.addAll(result);
-      }
-      return result;
-    }
-
-    if (arguments != null && arguments.length != typeVariablesCount) {
-      // That should be caught and reported as a compile-time error earlier.
-      return unhandled(
-          templateTypeArgumentMismatch
-              .withArguments(typeVariablesCount)
-              .problemMessage,
-          "buildTypeArguments",
-          -1,
-          null);
-    }
-
-    assert(arguments!.length == typeVariablesCount);
-    List<DartType> result = new List<DartType>.generate(
-        arguments!.length, (int i) => arguments[i].build(library),
-        growable: true);
-    return result;
-  }
-
-  @override
   DartType buildType(LibraryBuilder library,
       NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments) {
     return buildTypeWithBuiltArguments(
@@ -657,145 +375,6 @@
   }
 
   @override
-  void checkSupertypes(CoreTypes coreTypes) {
-    // This method determines whether the class (that's being built) its super
-    // class appears both in 'extends' and 'implements' clauses and whether any
-    // interface appears multiple times in the 'implements' clause.
-    // Moreover, it checks that `FutureOr` and `void` are not among the
-    // supertypes.
-
-    void fail(NamedTypeBuilder target, Message message,
-        TypeAliasBuilder? aliasBuilder) {
-      int nameOffset = target.nameOffset;
-      int nameLength = target.nameLength;
-      // TODO(eernst): nameOffset not fully implemented; use backup.
-      if (nameOffset == -1) {
-        nameOffset = this.charOffset;
-        nameLength = noLength;
-      }
-      if (aliasBuilder != null) {
-        addProblem(message, nameOffset, nameLength, context: [
-          messageTypedefCause.withLocation(
-              aliasBuilder.fileUri, aliasBuilder.charOffset, noLength),
-        ]);
-      } else {
-        addProblem(message, nameOffset, nameLength);
-      }
-    }
-
-    // Extract and check superclass (if it exists).
-    ClassBuilder? superClass;
-    TypeBuilder? superClassType = supertypeBuilder;
-    if (superClassType is NamedTypeBuilder) {
-      TypeDeclarationBuilder? decl = superClassType.declaration;
-      TypeAliasBuilder? aliasBuilder; // Non-null if a type alias is use.
-      if (decl is TypeAliasBuilder) {
-        aliasBuilder = decl;
-        decl = aliasBuilder.unaliasDeclaration(superClassType.arguments,
-            isUsedAsClass: true,
-            usedAsClassCharOffset: superClassType.charOffset,
-            usedAsClassFileUri: superClassType.fileUri);
-      }
-      // TODO(eernst): Should gather 'restricted supertype' checks in one place,
-      // e.g., dynamic/int/String/Null and more are checked elsewhere.
-      if (decl is VoidTypeDeclarationBuilder) {
-        fail(superClassType, messageExtendsVoid, aliasBuilder);
-      } else if (decl is NeverTypeDeclarationBuilder) {
-        fail(superClassType, messageExtendsNever, aliasBuilder);
-      } else if (decl is ClassBuilder) {
-        superClass = decl;
-      }
-    }
-    if (interfaceBuilders == null) return;
-
-    // Validate interfaces.
-    Map<ClassBuilder, int>? problems;
-    Map<ClassBuilder, int>? problemsOffsets;
-    Set<ClassBuilder> implemented = new Set<ClassBuilder>();
-    for (TypeBuilder type in interfaceBuilders!) {
-      if (type is NamedTypeBuilder) {
-        int? charOffset = type.charOffset;
-        TypeDeclarationBuilder? typeDeclaration = type.declaration;
-        TypeDeclarationBuilder? decl;
-        TypeAliasBuilder? aliasBuilder; // Non-null if a type alias is used.
-        if (typeDeclaration is TypeAliasBuilder) {
-          aliasBuilder = typeDeclaration;
-          decl = aliasBuilder.unaliasDeclaration(type.arguments,
-              isUsedAsClass: true,
-              usedAsClassCharOffset: type.charOffset,
-              usedAsClassFileUri: type.fileUri);
-        } else {
-          decl = typeDeclaration;
-        }
-        if (decl is ClassBuilder) {
-          ClassBuilder interface = decl;
-          if (superClass == interface) {
-            addProblem(
-                templateImplementsSuperClass.withArguments(interface.name),
-                this.charOffset,
-                noLength);
-          } else if (interface.cls.name == "FutureOr" &&
-              interface.cls.enclosingLibrary.importUri.scheme == "dart" &&
-              interface.cls.enclosingLibrary.importUri.path == "async") {
-            addProblem(messageImplementsFutureOr, this.charOffset, noLength);
-          } else if (implemented.contains(interface)) {
-            // Aggregate repetitions.
-            problems ??= <ClassBuilder, int>{};
-            problems[interface] ??= 0;
-            problems[interface] = problems[interface]! + 1;
-            problemsOffsets ??= <ClassBuilder, int>{};
-            problemsOffsets[interface] ??= charOffset ?? TreeNode.noOffset;
-          } else {
-            implemented.add(interface);
-          }
-        }
-        if (decl != superClass) {
-          // TODO(eernst): Have all 'restricted supertype' checks in one place.
-          if (decl is VoidTypeDeclarationBuilder) {
-            fail(type, messageImplementsVoid, aliasBuilder);
-          } else if (decl is NeverTypeDeclarationBuilder) {
-            fail(type, messageImplementsNever, aliasBuilder);
-          }
-        }
-      }
-    }
-    if (problems != null) {
-      problems.forEach((ClassBuilder interface, int repetitions) {
-        addProblem(
-            templateImplementsRepeated.withArguments(
-                interface.name, repetitions),
-            problemsOffsets![interface]!,
-            noLength);
-      });
-    }
-  }
-
-  @override
-  void handleSeenCovariant(
-      ClassHierarchyMembers memberHierarchy,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member interfaceMember, bool isSetter)) {
-    // When a parameter is covariant we have to check that we also
-    // override the same member in all parents.
-    for (Supertype supertype in interfaceMember.enclosingClass!.supers) {
-      Member? member = memberHierarchy.getInterfaceMember(
-          supertype.classNode, interfaceMember.name,
-          setter: isSetter);
-      if (member != null) {
-        callback(member, isSetter);
-      }
-    }
-  }
-
-  @override
-  bool hasUserDefinedNoSuchMethod(
-      Class klass, ClassHierarchy hierarchy, Class objectClass) {
-    Member? noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
-    return noSuchMethod != null && noSuchMethod.enclosingClass != objectClass;
-  }
-
-  @override
   String get fullNameForErrors {
     return isMixinApplication && !isNamedMixinApplication
         ? "${supertypeBuilder!.fullNameForErrors} with "
@@ -804,363 +383,6 @@
   }
 
   @override
-  void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes) {
-    TypeEnvironment typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
-    // A mixin declaration can only be applied to a class that implements all
-    // the declaration's superclass constraints.
-    InterfaceType supertype = cls.supertype!.asInterfaceType;
-    Substitution substitution = Substitution.fromSupertype(cls.mixedInType!);
-    for (Supertype constraint in cls.mixedInClass!.superclassConstraints()) {
-      InterfaceType requiredInterface =
-          substitution.substituteSupertype(constraint).asInterfaceType;
-      InterfaceType? implementedInterface = hierarchy.getTypeAsInstanceOf(
-          supertype, requiredInterface.classNode, library.library);
-      if (implementedInterface == null ||
-          !typeEnvironment.areMutualSubtypes(
-              implementedInterface,
-              requiredInterface,
-              library.isNonNullableByDefault
-                  ? SubtypeCheckMode.withNullabilities
-                  : SubtypeCheckMode.ignoringNullabilities)) {
-        library.addProblem(
-            templateMixinApplicationIncompatibleSupertype.withArguments(
-                supertype,
-                requiredInterface,
-                cls.mixedInType!.asInterfaceType,
-                library.isNonNullableByDefault),
-            cls.fileOffset,
-            noLength,
-            cls.fileUri);
-      }
-    }
-  }
-
-  @override
-  void applyPatch(Builder patch) {
-    if (patch is ClassBuilder) {
-      patch.actualOrigin = this;
-      _patchBuilder = patch;
-      // TODO(ahe): Complain if `patch.supertype` isn't null.
-      scope.forEachLocalMember((String name, Builder member) {
-        Builder? memberPatch =
-            patch.scope.lookupLocalMember(name, setter: false);
-        if (memberPatch != null) {
-          member.applyPatch(memberPatch);
-        }
-      });
-      scope.forEachLocalSetter((String name, Builder member) {
-        Builder? memberPatch =
-            patch.scope.lookupLocalMember(name, setter: true);
-        if (memberPatch != null) {
-          member.applyPatch(memberPatch);
-        }
-      });
-      constructors.local.forEach((String name, Builder member) {
-        Builder? memberPatch = patch.constructors.local[name];
-        if (memberPatch != null) {
-          member.applyPatch(memberPatch);
-        }
-      });
-
-      int originLength = typeVariables?.length ?? 0;
-      int patchLength = patch.typeVariables?.length ?? 0;
-      if (originLength != patchLength) {
-        patch.addProblem(messagePatchClassTypeVariablesMismatch,
-            patch.charOffset, noLength, context: [
-          messagePatchClassOrigin.withLocation(fileUri, charOffset, noLength)
-        ]);
-      } else if (typeVariables != null) {
-        int count = 0;
-        for (TypeVariableBuilder t in patch.typeVariables!) {
-          typeVariables![count++].applyPatch(t);
-        }
-      }
-    } else {
-      library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
-          noLength, patch.fileUri, context: [
-        messagePatchDeclarationOrigin.withLocation(
-            fileUri, charOffset, noLength)
-      ]);
-    }
-  }
-
-  @override
-  FunctionType? computeRedirecteeType(
-      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment) {
-    ConstructorReferenceBuilder redirectionTarget = factory.redirectionTarget;
-    Builder? targetBuilder = redirectionTarget.target;
-    FunctionNode targetNode;
-    if (targetBuilder == null) return null;
-    if (targetBuilder is FunctionBuilder) {
-      targetNode = targetBuilder.function;
-    } else if (targetBuilder is DillConstructorBuilder) {
-      // It seems that the [redirectionTarget.target] is an instance of
-      // [DillMemberBuilder] whenever the redirectee is an implicit constructor,
-      // e.g.
-      //
-      //   class A {
-      //     factory A() = B;
-      //   }
-      //   class B implements A {}
-      //
-      targetNode = targetBuilder.constructor.function;
-    } else if (targetBuilder is DillFactoryBuilder) {
-      // It seems that the [redirectionTarget.target] is an instance of
-      // [DillMemberBuilder] whenever the redirectee is an implicit constructor,
-      // e.g.
-      //
-      //   class A {
-      //     factory A() = B;
-      //   }
-      //   class B implements A {}
-      //
-      targetNode = targetBuilder.procedure.function;
-    } else if (targetBuilder is AmbiguousBuilder) {
-      // Multiple definitions with the same name: An error has already been
-      // issued.
-      // TODO(http://dartbug.com/35294): Unfortunate error; see also
-      // https://dart-review.googlesource.com/c/sdk/+/85390/.
-      return null;
-    } else {
-      unhandled("${redirectionTarget.target}", "computeRedirecteeType",
-          charOffset, fileUri);
-    }
-
-    List<DartType>? typeArguments = factory.getTypeArguments();
-    FunctionType targetFunctionType =
-        targetNode.computeFunctionType(library.nonNullable);
-    if (typeArguments != null &&
-        targetFunctionType.typeParameters.length != typeArguments.length) {
-      addProblemForRedirectingFactory(
-          factory,
-          templateTypeArgumentMismatch
-              .withArguments(targetFunctionType.typeParameters.length),
-          redirectionTarget.charOffset,
-          noLength);
-      return null;
-    }
-
-    // Compute the substitution of the target class type parameters if
-    // [redirectionTarget] has any type arguments.
-    Substitution? substitution;
-    bool hasProblem = false;
-    if (typeArguments != null && typeArguments.length > 0) {
-      substitution = Substitution.fromPairs(
-          targetFunctionType.typeParameters, typeArguments);
-      for (int i = 0; i < targetFunctionType.typeParameters.length; i++) {
-        TypeParameter typeParameter = targetFunctionType.typeParameters[i];
-        DartType typeParameterBound =
-            substitution.substituteType(typeParameter.bound);
-        DartType typeArgument = typeArguments[i];
-        // Check whether the [typeArgument] respects the bounds of
-        // [typeParameter].
-        Loader loader = library.loader;
-        if (!typeEnvironment.isSubtypeOf(typeArgument, typeParameterBound,
-            SubtypeCheckMode.ignoringNullabilities)) {
-          addProblemForRedirectingFactory(
-              factory,
-              templateRedirectingFactoryIncompatibleTypeArgument.withArguments(
-                  typeArgument,
-                  typeParameterBound,
-                  library.isNonNullableByDefault),
-              redirectionTarget.charOffset,
-              noLength);
-          hasProblem = true;
-        } else if (library.isNonNullableByDefault && loader is SourceLoader) {
-          if (!typeEnvironment.isSubtypeOf(typeArgument, typeParameterBound,
-              SubtypeCheckMode.withNullabilities)) {
-            addProblemForRedirectingFactory(
-                factory,
-                templateRedirectingFactoryIncompatibleTypeArgument
-                    .withArguments(typeArgument, typeParameterBound,
-                        library.isNonNullableByDefault),
-                redirectionTarget.charOffset,
-                noLength);
-            hasProblem = true;
-          }
-        }
-      }
-    } else if (typeArguments == null &&
-        targetFunctionType.typeParameters.length > 0) {
-      // TODO(hillerstrom): In this case, we need to perform type inference on
-      // the redirectee to obtain actual type arguments which would allow the
-      // following program to type check:
-      //
-      //    class A<T> {
-      //       factory A() = B;
-      //    }
-      //    class B<T> implements A<T> {
-      //       B();
-      //    }
-      //
-      return null;
-    }
-
-    // Substitute if necessary.
-    targetFunctionType = substitution == null
-        ? targetFunctionType
-        : (substitution.substituteType(targetFunctionType.withoutTypeParameters)
-            as FunctionType);
-
-    return hasProblem ? null : targetFunctionType;
-  }
-
-  @override
-  String computeRedirecteeName(ConstructorReferenceBuilder redirectionTarget) {
-    String targetName = redirectionTarget.fullNameForErrors;
-    if (targetName == "") {
-      return redirectionTarget.target!.parent!.fullNameForErrors;
-    } else {
-      return targetName;
-    }
-  }
-
-  bool _isCyclicRedirectingFactory(RedirectingFactoryBuilder factory) {
-    // We use the [tortoise and hare algorithm]
-    // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
-    // handle cycles.
-    Builder? tortoise = factory;
-    Builder? hare = factory.redirectionTarget.target;
-    if (hare == factory) {
-      return true;
-    }
-    while (tortoise != hare) {
-      // Hare moves 2 steps forward.
-      if (hare is! RedirectingFactoryBuilder) {
-        return false;
-      }
-      hare = hare.redirectionTarget.target;
-      if (hare == factory) {
-        return true;
-      }
-      if (hare is! RedirectingFactoryBuilder) {
-        return false;
-      }
-      hare = hare.redirectionTarget.target;
-      if (hare == factory) {
-        return true;
-      }
-      // Tortoise moves one step forward. No need to test type of tortoise
-      // as it follows hare which already checked types.
-      tortoise =
-          (tortoise as RedirectingFactoryBuilder).redirectionTarget.target;
-    }
-    // Cycle found, but original factory doesn't belong to a cycle.
-    return false;
-  }
-
-  void addProblemForRedirectingFactory(RedirectingFactoryBuilder factory,
-      Message message, int charOffset, int length) {
-    addProblem(message, charOffset, length);
-    String text = library.loader.target.context
-        .format(
-            message.withLocation(fileUri, charOffset, length), Severity.error)
-        .plain;
-    factory.body = new RedirectingFactoryBody.error(text);
-  }
-
-  @override
-  void checkRedirectingFactory(
-      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment) {
-    // Check that factory declaration is not cyclic.
-    if (_isCyclicRedirectingFactory(factory)) {
-      addProblemForRedirectingFactory(
-          factory,
-          templateCyclicRedirectingFactoryConstructors
-              .withArguments("${factory.member.enclosingClass!.name}"
-                  "${factory.name == '' ? '' : '.${factory.name}'}"),
-          factory.charOffset,
-          noLength);
-      return;
-    }
-
-    // The factory type cannot contain any type parameters other than those of
-    // its enclosing class, because constructors cannot specify type parameters
-    // of their own.
-    FunctionType factoryType = factory.function
-        .computeThisFunctionType(library.nonNullable)
-        .withoutTypeParameters;
-    FunctionType? redirecteeType =
-        computeRedirecteeType(factory, typeEnvironment);
-
-    // TODO(hillerstrom): It would be preferable to know whether a failure
-    // happened during [_computeRedirecteeType].
-    if (redirecteeType == null) {
-      return;
-    }
-
-    // Check whether [redirecteeType] <: [factoryType].
-    Loader loader = library.loader;
-    if (!typeEnvironment.isSubtypeOf(
-        redirecteeType, factoryType, SubtypeCheckMode.ignoringNullabilities)) {
-      addProblemForRedirectingFactory(
-          factory,
-          templateIncompatibleRedirecteeFunctionType.withArguments(
-              redirecteeType, factoryType, library.isNonNullableByDefault),
-          factory.redirectionTarget.charOffset,
-          noLength);
-    } else if (library.isNonNullableByDefault && loader is SourceLoader) {
-      if (!typeEnvironment.isSubtypeOf(
-          redirecteeType, factoryType, SubtypeCheckMode.withNullabilities)) {
-        addProblemForRedirectingFactory(
-            factory,
-            templateIncompatibleRedirecteeFunctionType.withArguments(
-                redirecteeType, factoryType, library.isNonNullableByDefault),
-            factory.redirectionTarget.charOffset,
-            noLength);
-      }
-    }
-  }
-
-  @override
-  void checkRedirectingFactories(TypeEnvironment typeEnvironment) {
-    Map<String, MemberBuilder> constructors = this.constructors.local;
-    for (Builder? constructor in constructors.values) {
-      do {
-        if (constructor is RedirectingFactoryBuilder) {
-          checkRedirectingFactory(constructor, typeEnvironment);
-        }
-        constructor = constructor!.next;
-      } while (constructor != null);
-    }
-  }
-
-  @override
-  Map<TypeParameter, DartType> getSubstitutionMap(Class superclass) {
-    Supertype? supertype = cls.supertype;
-    Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
-    List<DartType> arguments;
-    List<TypeParameter> variables;
-    Class? classNode;
-
-    while (classNode != superclass) {
-      classNode = supertype!.classNode;
-      arguments = supertype.typeArguments;
-      variables = classNode.typeParameters;
-      supertype = classNode.supertype;
-      if (variables.isNotEmpty) {
-        Map<TypeParameter, DartType> directSubstitutionMap =
-            <TypeParameter, DartType>{};
-        for (int i = 0; i < variables.length; i++) {
-          DartType argument =
-              i < arguments.length ? arguments[i] : const DynamicType();
-          // ignore: unnecessary_null_comparison
-          if (substitutionMap != null) {
-            // TODO(ahe): Investigate if requiring the caller to use
-            // `substituteDeep` from `package:kernel/type_algebra.dart` instead
-            // of `substitute` is faster. If so, we can simply this code.
-            argument = substitute(argument, substitutionMap);
-          }
-          directSubstitutionMap[variables[i]] = argument;
-        }
-        substitutionMap = directSubstitutionMap;
-      }
-    }
-
-    return substitutionMap;
-  }
-
-  @override
   Member? lookupInstanceMember(ClassHierarchy hierarchy, Name name,
       {bool isSetter: false, bool isSuper: false}) {
     Class? instanceClass = cls;
@@ -1200,63 +422,6 @@
     }
     return target;
   }
-
-  @override
-  Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
-    if (name.text == "new") {
-      name = new Name("", name.library);
-    }
-
-    Class? instanceClass = cls;
-    if (isSuper) {
-      instanceClass = instanceClass.superclass;
-    }
-    if (instanceClass != null) {
-      for (Constructor constructor in instanceClass.constructors) {
-        if (constructor.name == name) {
-          return constructor;
-        }
-      }
-    }
-
-    /// Performs a similar lookup to [lookupConstructor], but using a slower
-    /// implementation.
-    Constructor? lookupConstructorWithPatches(Name name, bool isSuper) {
-      ClassBuilder? builder = this.origin;
-
-      ClassBuilder? getSuperclass(ClassBuilder builder) {
-        // This way of computing the superclass is slower than using the kernel
-        // objects directly.
-        TypeBuilder? supertype = builder.supertypeBuilder;
-        if (supertype is NamedTypeBuilder) {
-          TypeDeclarationBuilder? builder = supertype.declaration;
-          if (builder is ClassBuilder) return builder;
-          if (builder is TypeAliasBuilder) {
-            TypeDeclarationBuilder? declarationBuilder =
-                builder.unaliasDeclaration(supertype.arguments,
-                    isUsedAsClass: true,
-                    usedAsClassCharOffset: supertype.charOffset,
-                    usedAsClassFileUri: supertype.fileUri);
-            if (declarationBuilder is ClassBuilder) return declarationBuilder;
-          }
-        }
-        return null;
-      }
-
-      if (isSuper) {
-        builder = getSuperclass(builder)?.origin;
-      }
-      if (builder != null) {
-        Class cls = builder.cls;
-        for (Constructor constructor in cls.constructors) {
-          if (constructor.name == name) return constructor;
-        }
-      }
-      return null;
-    }
-
-    return lookupConstructorWithPatches(name, isSuper);
-  }
 }
 
 class ConstructorRedirection {
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index f53cbfa..960410b 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -2,529 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
 
-import '../builder/library_builder.dart';
-
-import '../constant_context.dart' show ConstantContext;
-
-import '../dill/dill_member_builder.dart';
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/expression_generator_helper.dart'
-    show ExpressionGeneratorHelper;
-import '../kernel/hierarchy/class_member.dart' show ClassMember;
-import '../kernel/utils.dart'
-    show isRedirectingGenerativeConstructorImplementation;
-import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
-
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../messages.dart'
-    show
-        Message,
-        messageMoreThanOneSuperInitializer,
-        messageRedirectingConstructorWithAnotherInitializer,
-        messageRedirectingConstructorWithMultipleRedirectInitializers,
-        messageRedirectingConstructorWithSuperInitializer,
-        messageSuperInitializerNotLast,
-        noLength;
-
-import '../source/source_class_builder.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-import '../type_inference/type_schema.dart';
-import '../type_inference/type_inferrer.dart';
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'builder.dart';
-import 'field_builder.dart';
-import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
 
 abstract class ConstructorBuilder implements FunctionBuilder {
-  abstract Token? beginInitializers;
-
-  ConstructorBuilder? get actualOrigin;
-
-  ConstructorBuilder? get patchForTesting;
-
-  Constructor get actualConstructor;
-
-  @override
-  ConstructorBuilder get origin;
-
-  bool get isRedirectingGenerativeConstructor;
-
   /// The [Constructor] built by this builder.
   Constructor get constructor;
-
-  void injectInvalidInitializer(Message message, int charOffset, int length,
-      ExpressionGeneratorHelper helper);
-
-  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
-      {required InitializerInferenceResult? inferenceResult});
-
-  void prepareInitializers();
-
-  /// Infers the types of any untyped initializing formals.
-  void inferFormalTypes();
-
-  /// Registers field as being initialized by this constructor.
-  ///
-  /// The field can be initialized either via an initializing formal or via an
-  /// entry in the constructor initializer list.
-  void registerInitializedField(FieldBuilder fieldBuilder);
-
-  /// Returns the fields registered as initialized by this constructor.
-  ///
-  /// Returns the set of fields previously registered via
-  /// [registerInitializedField] and passes on the ownership of the collection
-  /// to the caller.
-  Set<FieldBuilder>? takeInitializedFields();
-}
-
-class SourceConstructorBuilder extends FunctionBuilderImpl
-    implements ConstructorBuilder {
-  final Constructor _constructor;
-  final Procedure? _constructorTearOff;
-
-  Set<FieldBuilder>? _initializedFields;
-
-  final int charOpenParenOffset;
-
-  bool hasMovedSuperInitializer = false;
-
-  SuperInitializer? superInitializer;
-
-  RedirectingInitializer? redirectingInitializer;
-
-  @override
-  Token? beginInitializers;
-
-  @override
-  ConstructorBuilder? actualOrigin;
-
-  @override
-  Constructor get actualConstructor => _constructor;
-
-  SourceConstructorBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder? returnType,
-      String name,
-      List<TypeVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      SourceLibraryBuilder compilationUnit,
-      int startCharOffset,
-      int charOffset,
-      this.charOpenParenOffset,
-      int charEndOffset,
-      Reference? constructorReference,
-      Reference? tearOffReference,
-      {String? nativeMethodName,
-      required bool forAbstractClassOrEnum})
-      : _constructor = new Constructor(new FunctionNode(null),
-            name: new Name(name, compilationUnit.library),
-            fileUri: compilationUnit.fileUri,
-            reference: constructorReference)
-          ..startFileOffset = startCharOffset
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
-        _constructorTearOff = createConstructorTearOffProcedure(
-            name,
-            compilationUnit,
-            compilationUnit.fileUri,
-            charOffset,
-            tearOffReference,
-            forAbstractClassOrEnum: forAbstractClassOrEnum),
-        super(metadata, modifiers, returnType, name, typeVariables, formals,
-            compilationUnit, charOffset, nativeMethodName);
-
-  @override
-  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
-  @override
-  SourceClassBuilder get classBuilder =>
-      super.classBuilder as SourceClassBuilder;
-
-  @override
-  Member? get readTarget => _constructorTearOff ?? _constructor;
-
-  @override
-  Member? get writeTarget => null;
-
-  @override
-  Member get invokeTarget => constructor;
-
-  @override
-  FunctionNode get function => _constructor.function;
-
-  @override
-  Iterable<Member> get exportedMembers => [constructor];
-
-  @override
-  ConstructorBuilder get origin => actualOrigin ?? this;
-
-  @override
-  ConstructorBuilder? get patchForTesting =>
-      dataForTesting?.patchForTesting as ConstructorBuilder?;
-
-  @override
-  bool get isDeclarationInstanceMember => false;
-
-  @override
-  bool get isClassInstanceMember => false;
-
-  @override
-  bool get isConstructor => true;
-
-  @override
-  AsyncMarker get asyncModifier => AsyncMarker.Sync;
-
-  @override
-  ProcedureKind? get kind => null;
-
-  @override
-  bool get isRedirectingGenerativeConstructor {
-    return isRedirectingGenerativeConstructorImplementation(_constructor);
-  }
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    Member member = build(library);
-    f(member, BuiltMemberKind.Constructor);
-    if (_constructorTearOff != null) {
-      f(_constructorTearOff!, BuiltMemberKind.Method);
-    }
-  }
-
-  bool _hasBeenBuilt = false;
-
-  @override
-  Constructor build(SourceLibraryBuilder libraryBuilder) {
-    if (!_hasBeenBuilt) {
-      buildFunction(libraryBuilder);
-      _constructor.function.fileOffset = charOpenParenOffset;
-      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
-      _constructor.function.typeParameters = const <TypeParameter>[];
-      _constructor.isConst = isConst;
-      _constructor.isExternal = isExternal;
-      updatePrivateMemberName(_constructor, libraryBuilder);
-
-      if (_constructorTearOff != null) {
-        buildConstructorTearOffProcedure(_constructorTearOff!, _constructor,
-            classBuilder.cls, libraryBuilder);
-      }
-
-      _hasBeenBuilt = true;
-    }
-    if (formals != null) {
-      bool needsInference = false;
-      for (FormalParameterBuilder formal in formals!) {
-        if (formal.type == null && formal.isInitializingFormal) {
-          formal.variable!.type = const UnknownType();
-          needsInference = true;
-        }
-      }
-      if (needsInference) {
-        assert(
-            library == libraryBuilder,
-            "Unexpected library builder ${libraryBuilder} for"
-            " constructor $this in ${library}.");
-        libraryBuilder.loader
-            .registerConstructorToBeInferred(_constructor, this);
-      }
-    }
-    return _constructor;
-  }
-
-  @override
-  void inferFormalTypes() {
-    if (formals != null) {
-      for (FormalParameterBuilder formal in formals!) {
-        if (formal.type == null && formal.isInitializingFormal) {
-          formal.finalizeInitializingFormal(classBuilder);
-        }
-      }
-    }
-  }
-
-  bool _hasBuiltOutlines = false;
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    if (_hasBuiltOutlines) return;
-    if (isConst && isPatch) {
-      origin.buildOutlineExpressions(library, coreTypes,
-          delayedActionPerformers, synthesizedFunctionNodes);
-    }
-    super.buildOutlineExpressions(
-        library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
-
-    // For modular compilation purposes we need to include initializers
-    // for const constructors into the outline.
-    if (isConst && beginInitializers != null) {
-      BodyBuilder bodyBuilder = library.loader
-          .createBodyBuilderForOutlineExpression(
-              library, classBuilder, this, classBuilder.scope, fileUri);
-      bodyBuilder.constantContext = ConstantContext.required;
-      bodyBuilder.parseInitializers(beginInitializers!);
-      bodyBuilder.performBacklogComputations(delayedActionPerformers);
-    }
-    beginInitializers = null;
-    if (isConst && isPatch) {
-      _finishPatch();
-    }
-    _hasBuiltOutlines = true;
-  }
-
-  @override
-  void buildFunction(SourceLibraryBuilder library) {
-    // According to the specification §9.3 the return type of a constructor
-    // function is its enclosing class.
-    super.buildFunction(library);
-    Class enclosingClass = classBuilder.cls;
-    List<DartType> typeParameterTypes = <DartType>[];
-    for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
-      TypeParameter typeParameter = enclosingClass.typeParameters[i];
-      typeParameterTypes.add(
-          new TypeParameterType.withDefaultNullabilityForLibrary(
-              typeParameter, library.library));
-    }
-    function.returnType = new InterfaceType(
-        enclosingClass, library.nonNullable, typeParameterTypes);
-  }
-
-  @override
-  Constructor get constructor => isPatch ? origin.constructor : _constructor;
-
-  @override
-  Member get member => constructor;
-
-  @override
-  void injectInvalidInitializer(Message message, int charOffset, int length,
-      ExpressionGeneratorHelper helper) {
-    List<Initializer> initializers = _constructor.initializers;
-    Initializer lastInitializer = initializers.removeLast();
-    assert(lastInitializer == superInitializer ||
-        lastInitializer == redirectingInitializer);
-    Initializer error = helper.buildInvalidInitializer(
-        helper.buildProblem(message, charOffset, length));
-    initializers.add(error..parent = _constructor);
-    initializers.add(lastInitializer);
-  }
-
-  @override
-  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
-      {required InitializerInferenceResult? inferenceResult}) {
-    List<Initializer> initializers = _constructor.initializers;
-    if (initializer is SuperInitializer) {
-      if (superInitializer != null) {
-        injectInvalidInitializer(messageMoreThanOneSuperInitializer,
-            initializer.fileOffset, "super".length, helper);
-      } else if (redirectingInitializer != null) {
-        injectInvalidInitializer(
-            messageRedirectingConstructorWithSuperInitializer,
-            initializer.fileOffset,
-            "super".length,
-            helper);
-      } else {
-        inferenceResult?.applyResult(initializers, _constructor);
-        initializers.add(initializer..parent = _constructor);
-        superInitializer = initializer;
-      }
-    } else if (initializer is RedirectingInitializer) {
-      if (superInitializer != null) {
-        // Point to the existing super initializer.
-        injectInvalidInitializer(
-            messageRedirectingConstructorWithSuperInitializer,
-            superInitializer!.fileOffset,
-            "super".length,
-            helper);
-      } else if (redirectingInitializer != null) {
-        injectInvalidInitializer(
-            messageRedirectingConstructorWithMultipleRedirectInitializers,
-            initializer.fileOffset,
-            noLength,
-            helper);
-      } else if (initializers.isNotEmpty) {
-        // Error on all previous ones.
-        for (int i = 0; i < initializers.length; i++) {
-          Initializer initializer = initializers[i];
-          int length = noLength;
-          if (initializer is AssertInitializer) length = "assert".length;
-          Initializer error = helper.buildInvalidInitializer(
-              helper.buildProblem(
-                  messageRedirectingConstructorWithAnotherInitializer,
-                  initializer.fileOffset,
-                  length));
-          error.parent = _constructor;
-          initializers[i] = error;
-        }
-        inferenceResult?.applyResult(initializers, _constructor);
-        initializers.add(initializer..parent = _constructor);
-        redirectingInitializer = initializer;
-      } else {
-        inferenceResult?.applyResult(initializers, _constructor);
-        initializers.add(initializer..parent = _constructor);
-        redirectingInitializer = initializer;
-      }
-    } else if (redirectingInitializer != null) {
-      int length = noLength;
-      if (initializer is AssertInitializer) length = "assert".length;
-      injectInvalidInitializer(
-          messageRedirectingConstructorWithAnotherInitializer,
-          initializer.fileOffset,
-          length,
-          helper);
-    } else if (superInitializer != null) {
-      injectInvalidInitializer(messageSuperInitializerNotLast,
-          initializer.fileOffset, noLength, helper);
-    } else {
-      inferenceResult?.applyResult(initializers, _constructor);
-      initializers.add(initializer..parent = _constructor);
-    }
-  }
-
-  @override
-  VariableDeclaration? getTearOffParameter(int index) {
-    if (_constructorTearOff != null) {
-      if (index < _constructorTearOff!.function.positionalParameters.length) {
-        return _constructorTearOff!.function.positionalParameters[index];
-      } else {
-        index -= _constructorTearOff!.function.positionalParameters.length;
-        if (index < _constructorTearOff!.function.namedParameters.length) {
-          return _constructorTearOff!.function.namedParameters[index];
-        }
-      }
-    }
-    return null;
-  }
-
-  void _finishPatch() {
-    // TODO(ahe): restore file-offset once we track both origin and patch file
-    // URIs. See https://github.com/dart-lang/sdk/issues/31579
-    origin.constructor.fileUri = fileUri;
-    origin.constructor.startFileOffset = _constructor.startFileOffset;
-    origin.constructor.fileOffset = _constructor.fileOffset;
-    origin.constructor.fileEndOffset = _constructor.fileEndOffset;
-    origin.constructor.annotations
-        .forEach((m) => m.fileOffset = _constructor.fileOffset);
-
-    origin.constructor.isExternal = _constructor.isExternal;
-    origin.constructor.function = _constructor.function;
-    origin.constructor.function.parent = origin.constructor;
-    origin.constructor.initializers = _constructor.initializers;
-    setParents(origin.constructor.initializers, origin.constructor);
-  }
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-    _finishPatch();
-    return 1;
-  }
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    _constructor.isExternal = true;
-    super.becomeNative(loader);
-  }
-
-  @override
-  void applyPatch(Builder patch) {
-    if (patch is SourceConstructorBuilder) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
-    }
-  }
-
-  @override
-  void prepareInitializers() {
-    // For const constructors we parse initializers already at the outlining
-    // stage, there is no easy way to make body building stage skip initializer
-    // parsing, so we simply clear parsed initializers and rebuild them
-    // again.
-    // For when doing an experimental incremental compilation they are also
-    // potentially done more than once (because it rebuilds the bodies of an old
-    // compile), and so we also clear them.
-    // Note: this method clears both initializers from the target Kernel node
-    // and internal state associated with parsing initializers.
-    _constructor.initializers = [];
-    redirectingInitializer = null;
-    superInitializer = null;
-    hasMovedSuperInitializer = false;
-  }
-
-  @override
-  List<ClassMember> get localMembers =>
-      throw new UnsupportedError('${runtimeType}.localMembers');
-
-  @override
-  List<ClassMember> get localSetters =>
-      throw new UnsupportedError('${runtimeType}.localSetters');
-
-  @override
-  void registerInitializedField(FieldBuilder fieldBuilder) {
-    (_initializedFields ??= {}).add(fieldBuilder);
-  }
-
-  @override
-  Set<FieldBuilder>? takeInitializedFields() {
-    Set<FieldBuilder>? result = _initializedFields;
-    _initializedFields = null;
-    return result;
-  }
-}
-
-class SyntheticConstructorBuilder extends DillConstructorBuilder {
-  MemberBuilderImpl? _origin;
-  SynthesizedFunctionNode? _synthesizedFunctionNode;
-
-  SyntheticConstructorBuilder(SourceClassBuilder parent,
-      Constructor constructor, Procedure? constructorTearOff,
-      {MemberBuilderImpl? origin,
-      SynthesizedFunctionNode? synthesizedFunctionNode})
-      : _origin = origin,
-        _synthesizedFunctionNode = synthesizedFunctionNode,
-        super(constructor, constructorTearOff, parent);
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder libraryBuilder,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    if (_origin != null) {
-      // Ensure that default value expressions have been created for [_origin].
-      LibraryBuilder originLibraryBuilder = _origin!.library;
-      if (originLibraryBuilder is SourceLibraryBuilder) {
-        // If [_origin] is from a source library, we need to build the default
-        // values and initializers first.
-        _origin!.buildOutlineExpressions(originLibraryBuilder, coreTypes,
-            delayedActionPerformers, synthesizedFunctionNodes);
-      }
-      _synthesizedFunctionNode!.cloneDefaultValues();
-      _synthesizedFunctionNode = null;
-      _origin = null;
-    }
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
deleted file mode 100644
index ecc964c..0000000
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ /dev/null
@@ -1,551 +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.enum_builder;
-
-import 'package:kernel/ast.dart'
-    show
-        Arguments,
-        AsyncMarker,
-        Class,
-        Constructor,
-        ConstructorInvocation,
-        Expression,
-        Field,
-        InstanceAccessKind,
-        InstanceGet,
-        IntLiteral,
-        InterfaceType,
-        ListLiteral,
-        Name,
-        ProcedureKind,
-        Reference,
-        ReturnStatement,
-        StaticGet,
-        StringConcatenation,
-        StringLiteral,
-        SuperInitializer,
-        ThisExpression;
-import 'package:kernel/core_types.dart';
-
-import 'package:kernel/reference_from_index.dart' show IndexedClass;
-
-import '../fasta_codes.dart'
-    show
-        LocatedMessage,
-        messageNoUnnamedConstructorInObject,
-        templateDuplicatedDeclaration,
-        templateDuplicatedDeclarationCause,
-        templateDuplicatedDeclarationSyntheticCause,
-        templateEnumConstantSameNameAsEnclosing;
-
-import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/kernel_helper.dart';
-
-import '../util/helpers.dart';
-
-import '../modifier.dart' show constMask, hasInitializerMask, staticMask;
-
-import '../scope.dart';
-
-import '../source/name_scheme.dart';
-import '../source/source_class_builder.dart' show SourceClassBuilder;
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import 'builder.dart';
-import 'class_builder.dart';
-import 'constructor_builder.dart';
-import 'field_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'library_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'named_type_builder.dart';
-import 'nullability_builder.dart';
-import 'procedure_builder.dart';
-import 'type_builder.dart';
-
-class EnumBuilder extends SourceClassBuilder {
-  final List<EnumConstantInfo?>? enumConstantInfos;
-
-  final NamedTypeBuilder intType;
-
-  final NamedTypeBuilder stringType;
-
-  final NamedTypeBuilder objectType;
-
-  final NamedTypeBuilder listType;
-
-  EnumBuilder.internal(
-      List<MetadataBuilder>? metadata,
-      String name,
-      Scope scope,
-      ConstructorScope constructors,
-      Class cls,
-      this.enumConstantInfos,
-      this.intType,
-      this.listType,
-      this.objectType,
-      TypeBuilder enumType,
-      this.stringType,
-      SourceLibraryBuilder parent,
-      int startCharOffset,
-      int charOffset,
-      int charEndOffset,
-      IndexedClass? referencesFromIndexed)
-      : super(
-            metadata,
-            0,
-            name,
-            /* typeVariable = */ null,
-            enumType,
-            /* interfaces = */ null,
-            /* onTypes = */ null,
-            scope,
-            constructors,
-            parent,
-            /* constructorReferences = */ null,
-            startCharOffset,
-            charOffset,
-            charEndOffset,
-            referencesFromIndexed,
-            cls: cls);
-
-  factory EnumBuilder(
-      List<MetadataBuilder>? metadata,
-      String name,
-      List<EnumConstantInfo?>? enumConstantInfos,
-      SourceLibraryBuilder parent,
-      int startCharOffset,
-      int charOffset,
-      int charEndOffset,
-      IndexedClass? referencesFromIndexed,
-      Scope scope) {
-    assert(enumConstantInfos == null || enumConstantInfos.isNotEmpty);
-
-    Uri fileUri = parent.fileUri;
-
-    // TODO(ahe): These types shouldn't be looked up in scope, they come
-    // directly from dart:core.
-    NamedTypeBuilder intType = new NamedTypeBuilder(
-        "int",
-        const NullabilityBuilder.omitted(),
-        /* arguments = */ null,
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess:
-            // If "int" resolves to an instance type variable then that we would
-            // allowed (the types that we are adding are in instance context
-            // after all) but it would be unexpected and we would like an
-            // assertion failure, since "int" was meant to be `int` from
-            // `dart:core`.
-            // TODO(johnniwinther): Add a more robust way of creating named
-            // typed builders for dart:core types. This might be needed for the
-            // enhanced enums feature where enums can actually declare type
-            // variables.
-            InstanceTypeVariableAccessState.Unexpected);
-    NamedTypeBuilder stringType = new NamedTypeBuilder(
-        "String",
-        const NullabilityBuilder.omitted(),
-        /* arguments = */ null,
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-    NamedTypeBuilder objectType = new NamedTypeBuilder(
-        "Object",
-        const NullabilityBuilder.omitted(),
-        /* arguments = */ null,
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-    NamedTypeBuilder enumType = new NamedTypeBuilder(
-        "_Enum",
-        const NullabilityBuilder.omitted(),
-        /* arguments = */ null,
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-    Class cls = new Class(
-        name: name,
-        reference: referencesFromIndexed?.cls.reference,
-        fileUri: fileUri);
-    Map<String, MemberBuilder> members = <String, MemberBuilder>{};
-    Map<String, MemberBuilder> setters = <String, MemberBuilder>{};
-    Map<String, MemberBuilder> constructors = <String, MemberBuilder>{};
-    NamedTypeBuilder selfType = new NamedTypeBuilder(
-        name,
-        const NullabilityBuilder.omitted(),
-        /* arguments = */ null,
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-    NamedTypeBuilder listType = new NamedTypeBuilder(
-        "List",
-        const NullabilityBuilder.omitted(),
-        <TypeBuilder>[selfType],
-        /* fileUri = */ null,
-        /* charOffset = */ null,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-
-    // metadata class E extends _Enum {
-    //   const E(int index, String name) : super(index, name);
-    //   static const E id0 = const E(0, 'id0');
-    //   ...
-    //   static const E id${n-1} = const E(n - 1, 'idn-1');
-    //   static const List<E> values = const <E>[id0, ..., id${n-1}];
-    //   String toString() {
-    //     return "E.${_Enum::_name}";
-    //   }
-    // }
-
-    NameScheme staticFieldNameScheme = new NameScheme(
-        isInstanceMember: false,
-        className: name,
-        isExtensionMember: false,
-        extensionName: null,
-        libraryReference: referencesFromIndexed != null
-            ? referencesFromIndexed.library.reference
-            : parent.library.reference);
-
-    NameScheme procedureNameScheme = new NameScheme(
-        isInstanceMember: true,
-        className: name,
-        isExtensionMember: false,
-        extensionName: null,
-        libraryReference: referencesFromIndexed != null
-            ? referencesFromIndexed.library.reference
-            : parent.library.reference);
-
-    Reference? constructorReference;
-    Reference? tearOffReference;
-    Reference? toStringReference;
-    Reference? valuesFieldReference;
-    Reference? valuesGetterReference;
-    Reference? valuesSetterReference;
-    if (referencesFromIndexed != null) {
-      constructorReference =
-          referencesFromIndexed.lookupConstructorReference(new Name(""));
-      tearOffReference = referencesFromIndexed.lookupGetterReference(
-          constructorTearOffName("", referencesFromIndexed.library));
-      toStringReference =
-          referencesFromIndexed.lookupGetterReference(new Name("toString"));
-      Name valuesName = new Name("values");
-      valuesFieldReference =
-          referencesFromIndexed.lookupFieldReference(valuesName);
-      valuesGetterReference =
-          referencesFromIndexed.lookupGetterReference(valuesName);
-      valuesSetterReference =
-          referencesFromIndexed.lookupSetterReference(valuesName);
-    }
-
-    ConstructorBuilder constructorBuilder = new SourceConstructorBuilder(
-        /* metadata = */ null,
-        constMask,
-        /* returnType = */ null,
-        "",
-        /* typeParameters = */ null,
-        <FormalParameterBuilder>[
-          new FormalParameterBuilder(
-              null, 0, intType, "index", parent, charOffset),
-          new FormalParameterBuilder(
-              null, 0, stringType, "name", parent, charOffset)
-        ],
-        parent,
-        charOffset,
-        charOffset,
-        charOffset,
-        charEndOffset,
-        constructorReference,
-        tearOffReference,
-        forAbstractClassOrEnum: true);
-    constructors[""] = constructorBuilder;
-    FieldBuilder valuesBuilder = new SourceFieldBuilder(
-        /* metadata = */ null,
-        listType,
-        "values",
-        constMask | staticMask | hasInitializerMask,
-        /* isTopLevel = */ false,
-        parent,
-        charOffset,
-        charOffset,
-        staticFieldNameScheme,
-        fieldReference: valuesFieldReference,
-        fieldGetterReference: valuesGetterReference,
-        fieldSetterReference: valuesSetterReference);
-    members["values"] = valuesBuilder;
-    ProcedureBuilder toStringBuilder = new SourceProcedureBuilder(
-        /* metadata = */ null,
-        0,
-        stringType,
-        "toString",
-        /* typeVariables = */ null,
-        /* formals = */ null,
-        ProcedureKind.Method,
-        parent,
-        charOffset,
-        charOffset,
-        charOffset,
-        charEndOffset,
-        toStringReference,
-        /* tearOffReference = */ null,
-        AsyncMarker.Sync,
-        procedureNameScheme,
-        isExtensionMember: false,
-        isInstanceMember: true);
-    members["toString"] = toStringBuilder;
-    constructorBuilder.registerInitializedField(valuesBuilder);
-    String className = name;
-    if (enumConstantInfos != null) {
-      for (int i = 0; i < enumConstantInfos.length; i++) {
-        EnumConstantInfo enumConstantInfo = enumConstantInfos[i]!;
-        List<MetadataBuilder>? metadata = enumConstantInfo.metadata;
-        String name = enumConstantInfo.name;
-        MemberBuilder? existing = members[name];
-        if (existing != null) {
-          // The existing declaration is synthetic if it has the same
-          // charOffset as the enclosing enum.
-          bool isSynthetic = existing.charOffset == charOffset;
-          List<LocatedMessage> context = isSynthetic
-              ? <LocatedMessage>[
-                  templateDuplicatedDeclarationSyntheticCause
-                      .withArguments(name)
-                      .withLocation(
-                          parent.fileUri, charOffset, className.length)
-                ]
-              : <LocatedMessage>[
-                  templateDuplicatedDeclarationCause
-                      .withArguments(name)
-                      .withLocation(
-                          parent.fileUri, existing.charOffset, name.length)
-                ];
-          parent.addProblem(templateDuplicatedDeclaration.withArguments(name),
-              enumConstantInfo.charOffset, name.length, parent.fileUri,
-              context: context);
-          enumConstantInfos[i] = null;
-        } else if (name == className) {
-          parent.addProblem(
-              templateEnumConstantSameNameAsEnclosing.withArguments(name),
-              enumConstantInfo.charOffset,
-              name.length,
-              parent.fileUri);
-        }
-        Reference? fieldReference;
-        Reference? getterReference;
-        Reference? setterReference;
-        if (referencesFromIndexed != null) {
-          Name nameName = new Name(name, referencesFromIndexed.library);
-          fieldReference = referencesFromIndexed.lookupFieldReference(nameName);
-          getterReference =
-              referencesFromIndexed.lookupGetterReference(nameName);
-          setterReference =
-              referencesFromIndexed.lookupSetterReference(nameName);
-        }
-        FieldBuilder fieldBuilder = new SourceFieldBuilder(
-            metadata,
-            selfType,
-            name,
-            constMask | staticMask | hasInitializerMask,
-            /* isTopLevel = */ false,
-            parent,
-            enumConstantInfo.charOffset,
-            enumConstantInfo.charOffset,
-            staticFieldNameScheme,
-            fieldReference: fieldReference,
-            fieldGetterReference: getterReference,
-            fieldSetterReference: setterReference);
-        members[name] = fieldBuilder..next = existing;
-      }
-    }
-    final int startCharOffsetComputed =
-        metadata == null ? startCharOffset : metadata.first.charOffset;
-    scope.forEachLocalMember((name, member) {
-      members[name] = member as MemberBuilder;
-    });
-    scope.forEachLocalSetter((name, member) {
-      setters[name] = member;
-    });
-    EnumBuilder enumBuilder = new EnumBuilder.internal(
-        metadata,
-        name,
-        new Scope(
-            local: members,
-            setters: setters,
-            parent: parent.scope,
-            debugName: "enum $name",
-            isModifiable: false),
-        new ConstructorScope(name, constructors),
-        cls,
-        enumConstantInfos,
-        intType,
-        listType,
-        objectType,
-        enumType,
-        stringType,
-        parent,
-        startCharOffsetComputed,
-        charOffset,
-        charEndOffset,
-        referencesFromIndexed);
-
-    void setParent(String name, MemberBuilder? builder) {
-      while (builder != null) {
-        builder.parent = enumBuilder;
-        builder = builder.next as MemberBuilder?;
-      }
-    }
-
-    members.forEach(setParent);
-    constructors.forEach(setParent);
-    selfType.bind(enumBuilder);
-    return enumBuilder;
-  }
-
-  @override
-  TypeBuilder? get mixedInTypeBuilder => null;
-
-  @override
-  InterfaceType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments) {
-    return rawType(nullabilityBuilder.build(library));
-  }
-
-  @override
-  Class build(SourceLibraryBuilder libraryBuilder, LibraryBuilder coreLibrary) {
-    cls.isEnum = true;
-    intType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
-    stringType.resolveIn(
-        coreLibrary.scope, charOffset, fileUri, libraryBuilder);
-    objectType.resolveIn(
-        coreLibrary.scope, charOffset, fileUri, libraryBuilder);
-    TypeBuilder supertypeBuilder = this.supertypeBuilder!;
-    supertypeBuilder.resolveIn(
-        coreLibrary.scope, charOffset, fileUri, libraryBuilder);
-    listType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
-
-    List<Expression> values = <Expression>[];
-    if (enumConstantInfos != null) {
-      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
-        if (enumConstantInfo != null) {
-          Builder declaration = firstMemberNamed(enumConstantInfo.name)!;
-          if (declaration.isField) {
-            SourceFieldBuilder fieldBuilder = declaration as SourceFieldBuilder;
-            fieldBuilder.build(libraryBuilder);
-            values.add(new StaticGet(fieldBuilder.field));
-          }
-        }
-      }
-    }
-    SourceFieldBuilder valuesBuilder =
-        firstMemberNamed("values") as SourceFieldBuilder;
-    valuesBuilder.build(libraryBuilder);
-    SourceConstructorBuilder constructorBuilder =
-        constructorScopeBuilder[""] as SourceConstructorBuilder;
-    Constructor constructor = constructorBuilder.build(libraryBuilder);
-    ClassBuilder objectClass = objectType.declaration as ClassBuilder;
-    ClassBuilder enumClass = supertypeBuilder.declaration as ClassBuilder;
-    MemberBuilder? superConstructor = enumClass.findConstructorOrFactory(
-        "", charOffset, fileUri, libraryBuilder);
-    if (superConstructor == null || !superConstructor.isConstructor) {
-      // TODO(ahe): Ideally, we would also want to check that [Object]'s
-      // unnamed constructor requires no arguments. But that information isn't
-      // always available at this point, and it's not really a situation that
-      // can happen unless you start modifying the SDK sources.
-      // (We should add a correct message. We no longer depend on Object here.)
-      library.addProblem(messageNoUnnamedConstructorInObject,
-          objectClass.charOffset, objectClass.name.length, objectClass.fileUri);
-    } else {
-      constructor.initializers.add(new SuperInitializer(
-          superConstructor.member as Constructor,
-          new Arguments.forwarded(constructor.function, libraryBuilder.library))
-        ..parent = constructor);
-    }
-    return super.build(libraryBuilder, coreLibrary);
-  }
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder libraryBuilder,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    List<Expression> values = <Expression>[];
-    if (enumConstantInfos != null) {
-      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
-        if (enumConstantInfo != null) {
-          Builder declaration = firstMemberNamed(enumConstantInfo.name)!;
-          if (declaration.isField) {
-            SourceFieldBuilder fieldBuilder = declaration as SourceFieldBuilder;
-            fieldBuilder.build(libraryBuilder);
-            values.add(new StaticGet(fieldBuilder.field));
-          }
-        }
-      }
-    }
-    SourceFieldBuilder valuesBuilder =
-        firstMemberNamed("values") as SourceFieldBuilder;
-    valuesBuilder.buildBody(
-        coreTypes,
-        new ListLiteral(values,
-            typeArgument: rawType(library.nonNullable), isConst: true));
-    SourceConstructorBuilder constructorBuilder =
-        constructorScopeBuilder[""] as SourceConstructorBuilder;
-    Constructor constructor = constructorBuilder.constructor;
-    int index = 0;
-    if (enumConstantInfos != null) {
-      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
-        if (enumConstantInfo != null) {
-          String constant = enumConstantInfo.name;
-          Builder declaration = firstMemberNamed(constant)!;
-          FieldBuilder field;
-          if (declaration.isField) {
-            field = declaration as FieldBuilder;
-          } else {
-            continue;
-          }
-          Arguments arguments = new Arguments(<Expression>[
-            new IntLiteral(index++),
-            new StringLiteral(constant),
-          ]);
-          field.buildBody(coreTypes,
-              new ConstructorInvocation(constructor, arguments, isConst: true));
-        }
-      }
-    }
-
-    ProcedureBuilder toStringBuilder =
-        firstMemberNamed("toString") as ProcedureBuilder;
-
-    TypeBuilder supertypeBuilder = this.supertypeBuilder!;
-    ClassBuilder enumClass = supertypeBuilder.declaration as ClassBuilder;
-    MemberBuilder? nameFieldBuilder =
-        enumClass.lookupLocalMember("_name") as MemberBuilder?;
-    if (nameFieldBuilder != null) {
-      Field nameField = nameFieldBuilder.member as Field;
-
-      toStringBuilder.body = new ReturnStatement(new StringConcatenation([
-        new StringLiteral("${cls.demangledName}."),
-        new InstanceGet.byReference(
-            InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
-            interfaceTargetReference: nameField.getterReference,
-            resultType: nameField.getterType),
-      ]));
-    } else {}
-
-    super.buildOutlineExpressions(
-        library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
-  }
-
-  @override
-  MemberBuilder? findConstructorOrFactory(
-      String name, int charOffset, Uri uri, LibraryBuilder library) {
-    return null;
-  }
-}
-
-class EnumConstantInfo {
-  final List<MetadataBuilder>? metadata;
-  final String name;
-  final int charOffset;
-  const EnumConstantInfo(this.metadata, this.name, this.charOffset);
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index fabf10a..95e42ab 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 
 import '../fasta_codes.dart'
     show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
@@ -37,7 +37,7 @@
 
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes);
 
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
deleted file mode 100644
index 86c7b96..0000000
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ /dev/null
@@ -1,476 +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:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-import 'package:kernel/type_algebra.dart';
-
-import '../dill/dill_member_builder.dart';
-
-import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/forest.dart';
-import '../kernel/hierarchy/class_member.dart';
-import '../kernel/internal_ast.dart';
-import '../kernel/kernel_helper.dart';
-import '../kernel/redirecting_factory_body.dart'
-    show getRedirectingFactoryBody, RedirectingFactoryBody;
-
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../messages.dart'
-    show messageConstFactoryRedirectionToNonConst, noLength;
-
-import '../problems.dart' show unexpected, unhandled;
-
-import '../source/name_scheme.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import '../type_inference/type_inferrer.dart';
-import '../type_inference/type_schema.dart';
-
-import '../util/helpers.dart';
-
-import 'builder.dart';
-import 'constructor_reference_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
-
-class SourceFactoryBuilder extends FunctionBuilderImpl {
-  final int charOpenParenOffset;
-
-  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
-
-  @override
-  final bool isExtensionInstanceMember = false;
-
-  final Procedure _procedureInternal;
-  final Procedure? _factoryTearOff;
-
-  SourceFactoryBuilder? actualOrigin;
-
-  SourceFactoryBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder returnType,
-      String name,
-      List<TypeVariableBuilder> typeVariables,
-      List<FormalParameterBuilder>? formals,
-      SourceLibraryBuilder libraryBuilder,
-      int startCharOffset,
-      int charOffset,
-      this.charOpenParenOffset,
-      int charEndOffset,
-      Reference? procedureReference,
-      Reference? tearOffReference,
-      AsyncMarker asyncModifier,
-      NameScheme nameScheme,
-      {String? nativeMethodName})
-      : _procedureInternal = new Procedure(
-            nameScheme.getProcedureName(ProcedureKind.Factory, name),
-            ProcedureKind.Factory,
-            new FunctionNode(null),
-            fileUri: libraryBuilder.fileUri,
-            reference: procedureReference)
-          ..startFileOffset = startCharOffset
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault,
-        _factoryTearOff = createFactoryTearOffProcedure(name, libraryBuilder,
-            libraryBuilder.fileUri, charOffset, tearOffReference),
-        super(metadata, modifiers, returnType, name, typeVariables, formals,
-            libraryBuilder, charOffset, nativeMethodName) {
-    this.asyncModifier = asyncModifier;
-  }
-
-  SourceFactoryBuilder? get patchForTesting =>
-      dataForTesting?.patchForTesting as SourceFactoryBuilder?;
-
-  @override
-  AsyncMarker get asyncModifier => actualAsyncModifier;
-
-  @override
-  Statement? get body {
-    if (bodyInternal == null && !isAbstract && !isExternal) {
-      bodyInternal = new EmptyStatement();
-    }
-    return bodyInternal;
-  }
-
-  void set asyncModifier(AsyncMarker newModifier) {
-    actualAsyncModifier = newModifier;
-    function.asyncMarker = actualAsyncModifier;
-    function.dartAsyncMarker = actualAsyncModifier;
-  }
-
-  @override
-  Member get member => _procedure;
-
-  @override
-  SourceFactoryBuilder get origin => actualOrigin ?? this;
-
-  @override
-  ProcedureKind get kind => ProcedureKind.Factory;
-
-  Procedure get _procedure => isPatch ? origin._procedure : _procedureInternal;
-
-  @override
-  FunctionNode get function => _procedureInternal.function;
-
-  @override
-  Member? get readTarget => origin._factoryTearOff ?? _procedure;
-
-  @override
-  Member? get writeTarget => null;
-
-  @override
-  Member? get invokeTarget => _procedure;
-
-  @override
-  Iterable<Member> get exportedMembers => [_procedure];
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    Member member = build(library);
-    f(member, BuiltMemberKind.Method);
-    if (_factoryTearOff != null) {
-      f(_factoryTearOff!, BuiltMemberKind.Method);
-    }
-  }
-
-  @override
-  Procedure build(SourceLibraryBuilder libraryBuilder) {
-    buildFunction(libraryBuilder);
-    _procedureInternal.function.fileOffset = charOpenParenOffset;
-    _procedureInternal.function.fileEndOffset =
-        _procedureInternal.fileEndOffset;
-    _procedureInternal.isAbstract = isAbstract;
-    _procedureInternal.isExternal = isExternal;
-    _procedureInternal.isConst = isConst;
-    updatePrivateMemberName(_procedureInternal, libraryBuilder);
-    _procedureInternal.isStatic = isStatic;
-
-    if (_factoryTearOff != null) {
-      buildConstructorTearOffProcedure(_factoryTearOff!, _procedureInternal,
-          classBuilder!.cls, libraryBuilder);
-    }
-    return _procedureInternal;
-  }
-
-  bool _hasBuiltOutlines = false;
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    if (_hasBuiltOutlines) return;
-    super.buildOutlineExpressions(
-        library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
-    _hasBuiltOutlines = true;
-  }
-
-  @override
-  VariableDeclaration? getTearOffParameter(int index) {
-    if (_factoryTearOff != null) {
-      if (index < _factoryTearOff!.function.positionalParameters.length) {
-        return _factoryTearOff!.function.positionalParameters[index];
-      } else {
-        index -= _factoryTearOff!.function.positionalParameters.length;
-        if (index < _factoryTearOff!.function.namedParameters.length) {
-          return _factoryTearOff!.function.namedParameters[index];
-        }
-      }
-    }
-    return null;
-  }
-
-  @override
-  List<ClassMember> get localMembers =>
-      throw new UnsupportedError('${runtimeType}.localMembers');
-
-  @override
-  List<ClassMember> get localSetters =>
-      throw new UnsupportedError('${runtimeType}.localSetters');
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    _procedureInternal.isExternal = true;
-    super.becomeNative(loader);
-  }
-
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
-    if (bodyInternal != null) {
-      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
-    }
-    bodyInternal = new RedirectingFactoryBody(target, typeArguments, function);
-    function.body = bodyInternal;
-    bodyInternal?.parent = function;
-    if (isPatch) {
-      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
-    }
-  }
-
-  @override
-  void applyPatch(Builder patch) {
-    if (patch is SourceFactoryBuilder) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
-    }
-  }
-
-  void _finishPatch() {
-    // TODO(ahe): restore file-offset once we track both origin and patch file
-    // URIs. See https://github.com/dart-lang/sdk/issues/31579
-    origin._procedure.fileUri = fileUri;
-    origin._procedure.startFileOffset = _procedureInternal.startFileOffset;
-    origin._procedure.fileOffset = _procedureInternal.fileOffset;
-    origin._procedure.fileEndOffset = _procedureInternal.fileEndOffset;
-    origin._procedure.annotations
-        .forEach((m) => m.fileOffset = _procedureInternal.fileOffset);
-
-    origin._procedure.isAbstract = _procedureInternal.isAbstract;
-    origin._procedure.isExternal = _procedureInternal.isExternal;
-    origin._procedure.function = _procedureInternal.function;
-    origin._procedure.function.parent = origin._procedure;
-    origin._procedure.isRedirectingFactory =
-        _procedureInternal.isRedirectingFactory;
-  }
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-    _finishPatch();
-    return 1;
-  }
-}
-
-class RedirectingFactoryBuilder extends SourceFactoryBuilder {
-  final ConstructorReferenceBuilder redirectionTarget;
-  List<DartType>? typeArguments;
-
-  FreshTypeParameters? _tearOffTypeParameters;
-
-  RedirectingFactoryBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder returnType,
-      String name,
-      List<TypeVariableBuilder> typeVariables,
-      List<FormalParameterBuilder>? formals,
-      SourceLibraryBuilder libraryBuilder,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      Reference? procedureReference,
-      Reference? tearOffReference,
-      NameScheme nameScheme,
-      String? nativeMethodName,
-      this.redirectionTarget)
-      : super(
-            metadata,
-            modifiers,
-            returnType,
-            name,
-            typeVariables,
-            formals,
-            libraryBuilder,
-            startCharOffset,
-            charOffset,
-            charOpenParenOffset,
-            charEndOffset,
-            procedureReference,
-            tearOffReference,
-            AsyncMarker.Sync,
-            nameScheme,
-            nativeMethodName: nativeMethodName);
-
-  @override
-  Statement? get body => bodyInternal;
-
-  @override
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
-    if (bodyInternal != null) {
-      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
-    }
-
-    // Ensure that constant factories only have constant targets/bodies.
-    if (isConst && !target.isConst) {
-      library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
-          noLength, fileUri);
-    }
-
-    bodyInternal = new RedirectingFactoryBody(target, typeArguments, function);
-    function.body = bodyInternal;
-    bodyInternal?.parent = function;
-    _procedure.isRedirectingFactory = true;
-    if (isPatch) {
-      // ignore: unnecessary_null_comparison
-      if (function.typeParameters != null) {
-        Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
-        for (int i = 0; i < function.typeParameters.length; i++) {
-          substitution[function.typeParameters[i]] =
-              new TypeParameterType.withDefaultNullabilityForLibrary(
-                  actualOrigin!.function.typeParameters[i], library.library);
-        }
-        typeArguments = new List<DartType>.generate(typeArguments.length,
-            (int i) => substitute(typeArguments[i], substitution),
-            growable: false);
-      }
-      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
-    }
-  }
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    Member member = build(library);
-    f(member, BuiltMemberKind.RedirectingFactory);
-    if (_factoryTearOff != null) {
-      f(_factoryTearOff!, BuiltMemberKind.Method);
-    }
-  }
-
-  @override
-  Procedure build(SourceLibraryBuilder libraryBuilder) {
-    buildFunction(libraryBuilder);
-    _procedureInternal.function.fileOffset = charOpenParenOffset;
-    _procedureInternal.function.fileEndOffset =
-        _procedureInternal.fileEndOffset;
-    _procedureInternal.isAbstract = isAbstract;
-    _procedureInternal.isExternal = isExternal;
-    _procedureInternal.isConst = isConst;
-    _procedureInternal.isStatic = isStatic;
-    _procedureInternal.isRedirectingFactory = true;
-    if (redirectionTarget.typeArguments != null) {
-      typeArguments = new List<DartType>.generate(
-          redirectionTarget.typeArguments!.length,
-          (int i) => redirectionTarget.typeArguments![i].build(library),
-          growable: false);
-    }
-    updatePrivateMemberName(_procedureInternal, libraryBuilder);
-    if (_factoryTearOff != null) {
-      _tearOffTypeParameters =
-          buildRedirectingFactoryTearOffProcedureParameters(
-              _factoryTearOff!, _procedureInternal, libraryBuilder);
-    }
-    return _procedureInternal;
-  }
-
-  @override
-  bool _hasBuiltOutlines = false;
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    if (_hasBuiltOutlines) return;
-    if (isConst && isPatch) {
-      origin.buildOutlineExpressions(library, coreTypes,
-          delayedActionPerformers, synthesizedFunctionNodes);
-    }
-    super.buildOutlineExpressions(
-        library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
-    RedirectingFactoryBody redirectingFactoryBody =
-        _procedureInternal.function.body as RedirectingFactoryBody;
-    List<DartType>? typeArguments = redirectingFactoryBody.typeArguments;
-    Member? target = redirectingFactoryBody.target;
-    if (typeArguments != null && typeArguments.any((t) => t is UnknownType)) {
-      TypeInferrerImpl inferrer = library.loader.typeInferenceEngine
-              .createLocalTypeInferrer(
-                  fileUri, classBuilder!.thisType, library, null)
-          as TypeInferrerImpl;
-      inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
-          library, classBuilder, this, classBuilder!.scope, fileUri);
-      Builder? targetBuilder = redirectionTarget.target;
-      if (targetBuilder is FunctionBuilder) {
-        target = targetBuilder.member;
-      } else if (targetBuilder is DillMemberBuilder) {
-        target = targetBuilder.member;
-      } else {
-        unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
-            charOffset, fileUri);
-      }
-      ArgumentsImpl targetInvocationArguments;
-      {
-        List<Expression> positionalArguments = <Expression>[];
-        for (VariableDeclaration parameter
-            in _procedure.function.positionalParameters) {
-          inferrer.flowAnalysis.declare(parameter, true);
-          positionalArguments
-              .add(new VariableGetImpl(parameter, forNullGuardedAccess: false));
-        }
-        List<NamedExpression> namedArguments = <NamedExpression>[];
-        for (VariableDeclaration parameter
-            in _procedure.function.namedParameters) {
-          inferrer.flowAnalysis.declare(parameter, true);
-          namedArguments.add(new NamedExpression(parameter.name!,
-              new VariableGetImpl(parameter, forNullGuardedAccess: false)));
-        }
-        // If arguments are created using [Forest.createArguments], and the
-        // type arguments are omitted, they are to be inferred.
-        targetInvocationArguments = const Forest().createArguments(
-            _procedure.fileOffset, positionalArguments,
-            named: namedArguments);
-      }
-      InvocationInferenceResult result = inferrer.inferInvocation(
-          function.returnType,
-          charOffset,
-          target.function!.computeFunctionType(Nullability.nonNullable),
-          targetInvocationArguments,
-          staticTarget: target);
-      if (result.inferredType is InterfaceType) {
-        typeArguments = (result.inferredType as InterfaceType).typeArguments;
-      } else {
-        // Assume that the error is reported elsewhere, use 'dynamic' for
-        // recovery.
-        typeArguments = new List<DartType>.filled(
-            target.enclosingClass!.typeParameters.length, const DynamicType(),
-            growable: true);
-      }
-
-      function.body =
-          new RedirectingFactoryBody(target, typeArguments, function);
-      function.body!.parent = function;
-    }
-    if (_factoryTearOff != null &&
-        (target is Constructor || target is Procedure && target.isFactory)) {
-      synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
-          _factoryTearOff!,
-          target!,
-          typeArguments ?? [],
-          _tearOffTypeParameters!));
-    }
-    if (isConst && isPatch) {
-      _finishPatch();
-    }
-    _hasBuiltOutlines = true;
-  }
-
-  @override
-  void _finishPatch() {
-    super._finishPatch();
-
-    SourceFactoryBuilder redirectingOrigin = origin;
-    if (redirectingOrigin is RedirectingFactoryBuilder) {
-      redirectingOrigin.typeArguments = typeArguments;
-    }
-  }
-
-  List<DartType>? getTypeArguments() {
-    return getRedirectingFactoryBody(_procedure)!.typeArguments;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 8acdc68..a5fd7b7 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -4,1852 +4,10 @@
 
 library fasta.field_builder;
 
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/type_algebra.dart';
 
-import '../constant_context.dart' show ConstantContext;
-
-import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/hierarchy/class_member.dart';
-import '../kernel/hierarchy/members_builder.dart';
-import '../kernel/implicit_field_type.dart';
-import '../kernel/kernel_helper.dart';
-import '../kernel/late_lowering.dart' as late_lowering;
-import '../kernel/member_covariance.dart';
-
-import '../modifier.dart' show covariantMask, hasInitializerMask, lateMask;
-
-import '../problems.dart' show internalProblem;
-
-import '../scope.dart' show Scope;
-
-import '../source/name_scheme.dart';
-import '../source/source_extension_builder.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../type_inference/type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly;
-
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'class_builder.dart';
 import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
 
 abstract class FieldBuilder implements MemberBuilder {
   Field get field;
-
-  List<MetadataBuilder>? get metadata;
-
-  TypeBuilder? get type;
-
-  bool get isCovariantByDeclaration;
-
-  bool get isLate;
-
-  bool get hasInitializer;
-
-  /// Whether the body of this field has been built.
-  ///
-  /// Constant fields have their initializer built in the outline so we avoid
-  /// building them twice as part of the non-outline build.
-  bool get hasBodyBeenBuilt;
-
-  /// Builds the body of this field using [initializer] as the initializer
-  /// expression.
-  void buildBody(CoreTypes coreTypes, Expression? initializer);
-
-  /// Builds the field initializers for each field used to encode this field
-  /// using the [fileOffset] for the created nodes and [value] as the initial
-  /// field value.
-  List<Initializer> buildInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic});
-
-  bool get isEligibleForInference;
-
-  DartType get builtType;
-
-  DartType inferType();
-
-  DartType get fieldType;
-}
-
-class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
-  @override
-  final String name;
-
-  @override
-  final int modifiers;
-
-  late FieldEncoding _fieldEncoding;
-
-  @override
-  final List<MetadataBuilder>? metadata;
-
-  @override
-  final TypeBuilder? type;
-
-  Token? _constInitializerToken;
-
-  bool hadTypesInferred = false;
-
-  @override
-  bool hasBodyBeenBuilt = false;
-
-  // TODO(johnniwinther): [parent] is not trust-worthy for determining
-  //  properties since it is changed after the creation of the builder. For now
-  //  we require it has an argument here. A follow-up should clean up the
-  //  misuse of parent.
-  @override
-  final bool isTopLevel;
-
-  SourceFieldBuilder(
-      this.metadata,
-      this.type,
-      this.name,
-      this.modifiers,
-      this.isTopLevel,
-      SourceLibraryBuilder libraryBuilder,
-      int charOffset,
-      int charEndOffset,
-      NameScheme fieldNameScheme,
-      {Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      Token? constInitializerToken})
-      : _constInitializerToken = constInitializerToken,
-        super(libraryBuilder, charOffset) {
-    bool isInstanceMember = fieldNameScheme.isInstanceMember;
-
-    Uri fileUri = libraryBuilder.fileUri;
-    // If in mixed mode, late lowerings cannot use `null` as a sentinel on
-    // non-nullable fields since they can be assigned from legacy code.
-    late_lowering.IsSetStrategy isSetStrategy =
-        late_lowering.computeIsSetStrategy(libraryBuilder);
-
-    if (isAbstract || isExternal) {
-      assert(fieldReference == null);
-      assert(lateIsSetFieldReference == null);
-      assert(lateIsSetGetterReference == null);
-      assert(lateIsSetSetterReference == null);
-      assert(lateGetterReference == null);
-      assert(lateSetterReference == null);
-      _fieldEncoding = new AbstractOrExternalFieldEncoding(
-          this,
-          name,
-          fieldNameScheme,
-          fileUri,
-          charOffset,
-          charEndOffset,
-          fieldGetterReference,
-          fieldSetterReference,
-          isAbstract: isAbstract,
-          isExternal: isExternal,
-          isFinal: isFinal,
-          isCovariantByDeclaration: isCovariantByDeclaration,
-          isNonNullableByDefault: library.isNonNullableByDefault);
-    } else if (isLate &&
-        libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
-            hasInitializer: hasInitializer,
-            isFinal: isFinal,
-            isStatic: !isInstanceMember)) {
-      if (hasInitializer) {
-        if (isFinal) {
-          _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
-              name,
-              fieldNameScheme,
-              fileUri,
-              charOffset,
-              charEndOffset,
-              fieldReference,
-              fieldGetterReference,
-              fieldSetterReference,
-              lateIsSetFieldReference,
-              lateIsSetGetterReference,
-              lateIsSetSetterReference,
-              lateGetterReference,
-              lateSetterReference,
-              isCovariantByDeclaration,
-              isSetStrategy);
-        } else {
-          _fieldEncoding = new LateFieldWithInitializerEncoding(
-              name,
-              fieldNameScheme,
-              fileUri,
-              charOffset,
-              charEndOffset,
-              fieldReference,
-              fieldGetterReference,
-              fieldSetterReference,
-              lateIsSetFieldReference,
-              lateIsSetGetterReference,
-              lateIsSetSetterReference,
-              lateGetterReference,
-              lateSetterReference,
-              isCovariantByDeclaration,
-              isSetStrategy);
-        }
-      } else {
-        if (isFinal) {
-          _fieldEncoding = new LateFinalFieldWithoutInitializerEncoding(
-              name,
-              fieldNameScheme,
-              fileUri,
-              charOffset,
-              charEndOffset,
-              fieldReference,
-              fieldGetterReference,
-              fieldSetterReference,
-              lateIsSetFieldReference,
-              lateIsSetGetterReference,
-              lateIsSetSetterReference,
-              lateGetterReference,
-              lateSetterReference,
-              isCovariantByDeclaration,
-              isSetStrategy);
-        } else {
-          _fieldEncoding = new LateFieldWithoutInitializerEncoding(
-              name,
-              fieldNameScheme,
-              fileUri,
-              charOffset,
-              charEndOffset,
-              fieldReference,
-              fieldGetterReference,
-              fieldSetterReference,
-              lateIsSetFieldReference,
-              lateIsSetGetterReference,
-              lateIsSetSetterReference,
-              lateGetterReference,
-              lateSetterReference,
-              isCovariantByDeclaration,
-              isSetStrategy);
-        }
-      }
-    } else if (libraryBuilder.isNonNullableByDefault &&
-        libraryBuilder.loader.target.backendTarget.useStaticFieldLowering &&
-        !isInstanceMember &&
-        !isConst &&
-        hasInitializer) {
-      if (isFinal) {
-        _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
-            name,
-            fieldNameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-      } else {
-        _fieldEncoding = new LateFieldWithInitializerEncoding(
-            name,
-            fieldNameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-      }
-    } else {
-      assert(lateIsSetFieldReference == null);
-      assert(lateIsSetGetterReference == null);
-      assert(lateIsSetSetterReference == null);
-      assert(lateGetterReference == null);
-      assert(lateSetterReference == null);
-      _fieldEncoding = new RegularFieldEncoding(
-          name, fieldNameScheme, fileUri, charOffset, charEndOffset,
-          isFinal: isFinal,
-          isConst: isConst,
-          isLate: isLate,
-          hasInitializer: hasInitializer,
-          isNonNullableByDefault: library.isNonNullableByDefault,
-          fieldReference: fieldReference,
-          getterReference: fieldGetterReference,
-          setterReference: fieldSetterReference);
-    }
-  }
-
-  bool get isLateLowered => _fieldEncoding.isLateLowering;
-
-  bool _typeEnsured = false;
-  Set<ClassMember>? _overrideDependencies;
-
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    assert(
-        overriddenMembers.every((overriddenMember) =>
-            overriddenMember.classBuilder != classBuilder),
-        "Unexpected override dependencies for $this: $overriddenMembers");
-    _overrideDependencies ??= {};
-    _overrideDependencies!.addAll(overriddenMembers);
-  }
-
-  void _ensureType(ClassMembersBuilder membersBuilder) {
-    if (_typeEnsured) return;
-    if (_overrideDependencies != null) {
-      membersBuilder.inferFieldType(this, _overrideDependencies!);
-      _overrideDependencies = null;
-    } else {
-      inferType();
-    }
-    _typeEnsured = true;
-  }
-
-  @override
-  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
-  @override
-  Member get member => _fieldEncoding.field;
-
-  @override
-  String get debugName => "FieldBuilder";
-
-  @override
-  bool get isField => true;
-
-  @override
-  bool get isLate => (modifiers & lateMask) != 0;
-
-  @override
-  bool get isCovariantByDeclaration => (modifiers & covariantMask) != 0;
-
-  @override
-  bool get hasInitializer => (modifiers & hasInitializerMask) != 0;
-
-  @override
-  void buildBody(CoreTypes coreTypes, Expression? initializer) {
-    assert(!hasBodyBeenBuilt);
-    hasBodyBeenBuilt = true;
-    if (!hasInitializer &&
-        initializer != null &&
-        initializer is! NullLiteral &&
-        !isConst &&
-        !isFinal) {
-      internalProblem(
-          messageInternalProblemAlreadyInitialized, charOffset, fileUri);
-    }
-    _fieldEncoding.createBodies(coreTypes, initializer);
-  }
-
-  @override
-  List<Initializer> buildInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic}) {
-    return _fieldEncoding.createInitializer(fileOffset, value,
-        isSynthetic: isSynthetic);
-  }
-
-  @override
-  bool get isEligibleForInference {
-    return type == null && (hasInitializer || isClassInstanceMember);
-  }
-
-  @override
-  bool get isAssignable {
-    if (isConst) return false;
-    if (isFinal) {
-      if (isLate) {
-        return !hasInitializer;
-      }
-      return false;
-    }
-    return true;
-  }
-
-  @override
-  Field get field => _fieldEncoding.field;
-
-  @override
-  Member get readTarget => _fieldEncoding.readTarget;
-
-  @override
-  Member? get writeTarget {
-    return isAssignable ? _fieldEncoding.writeTarget : null;
-  }
-
-  @override
-  Member get invokeTarget => readTarget;
-
-  @override
-  Iterable<Member> get exportedMembers => _fieldEncoding.exportedMembers;
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    build(library);
-    _fieldEncoding.registerMembers(library, this, f);
-  }
-
-  /// Builds the core AST structures for this field as needed for the outline.
-  void build(SourceLibraryBuilder libraryBuilder) {
-    if (type != null) {
-      fieldType = type!.build(libraryBuilder);
-    }
-    _fieldEncoding.build(libraryBuilder, this);
-  }
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    _fieldEncoding.completeSignature(coreTypes);
-
-    for (Annotatable annotatable in _fieldEncoding.annotatables) {
-      MetadataBuilder.buildAnnotations(
-          annotatable,
-          metadata,
-          library,
-          declarationBuilder,
-          this,
-          fileUri,
-          declarationBuilder?.scope ?? library.scope);
-    }
-
-    // For modular compilation we need to include initializers of all const
-    // fields and all non-static final fields in classes with const constructors
-    // into the outline.
-    if ((isConst ||
-            (isFinal &&
-                !isStatic &&
-                isClassMember &&
-                classBuilder!.declaresConstConstructor)) &&
-        _constInitializerToken != null) {
-      Scope scope = declarationBuilder?.scope ?? library.scope;
-      BodyBuilder bodyBuilder = library.loader
-          .createBodyBuilderForOutlineExpression(
-              library, declarationBuilder, this, scope, fileUri);
-      bodyBuilder.constantContext =
-          isConst ? ConstantContext.inferred : ConstantContext.required;
-      Expression initializer = bodyBuilder.typeInferrer.inferFieldInitializer(
-          bodyBuilder,
-          fieldType,
-          bodyBuilder.parseFieldInitializer(_constInitializerToken!));
-      if (bodyBuilder.transformSetLiterals ||
-          bodyBuilder.transformCollections) {
-        // Wrap the initializer in a temporary parent expression; the
-        // transformations need a parent relation.
-        Not wrapper = new Not(initializer);
-        SourceLoader loader = library.loader;
-        loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
-            bodyBuilder.transformCollections, library.library);
-        initializer = wrapper.operand;
-      }
-      buildBody(coreTypes, initializer);
-      bodyBuilder.performBacklogComputations(delayedActionPerformers);
-    }
-    _constInitializerToken = null;
-  }
-
-  @override
-  DartType get fieldType => _fieldEncoding.type;
-
-  void set fieldType(DartType value) {
-    _fieldEncoding.type = value;
-    if (!isFinal && !isConst && parent is ClassBuilder) {
-      Class enclosingClass = classBuilder!.cls;
-      if (enclosingClass.typeParameters.isNotEmpty) {
-        IncludesTypeParametersNonCovariantly needsCheckVisitor =
-            new IncludesTypeParametersNonCovariantly(
-                enclosingClass.typeParameters,
-                // We are checking the field type as if it is the type of the
-                // parameter of the implicit setter and this is a contravariant
-                // position.
-                initialVariance: Variance.contravariant);
-        if (value.accept(needsCheckVisitor)) {
-          _fieldEncoding.setGenericCovariantImpl();
-        }
-      }
-    }
-  }
-
-  @override
-  DartType inferType() {
-    SourceLibraryBuilder library = this.library;
-    if (fieldType is! ImplicitFieldType) {
-      // We have already inferred a type.
-      return fieldType;
-    }
-
-    ImplicitFieldType implicitFieldType = fieldType as ImplicitFieldType;
-    DartType inferredType = implicitFieldType.computeType();
-    if (fieldType is ImplicitFieldType) {
-      // `fieldType` may have changed if a circularity was detected when
-      // [inferredType] was computed.
-      if (!library.isNonNullableByDefault) {
-        inferredType = legacyErasure(inferredType);
-      }
-      fieldType = implicitFieldType.checkInferred(inferredType);
-
-      IncludesTypeParametersNonCovariantly? needsCheckVisitor;
-      if (parent is ClassBuilder) {
-        Class enclosingClass = classBuilder!.cls;
-        if (enclosingClass.typeParameters.isNotEmpty) {
-          needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
-              enclosingClass.typeParameters,
-              // We are checking the field type as if it is the type of the
-              // parameter of the implicit setter and this is a contravariant
-              // position.
-              initialVariance: Variance.contravariant);
-        }
-      }
-      if (needsCheckVisitor != null) {
-        if (fieldType.accept(needsCheckVisitor)) {
-          _fieldEncoding.setGenericCovariantImpl();
-        }
-      }
-    }
-    return fieldType;
-  }
-
-  @override
-  DartType get builtType => fieldType;
-
-  List<ClassMember>? _localMembers;
-  List<ClassMember>? _localSetters;
-
-  @override
-  List<ClassMember> get localMembers =>
-      _localMembers ??= _fieldEncoding.getLocalMembers(this);
-
-  @override
-  List<ClassMember> get localSetters =>
-      _localSetters ??= _fieldEncoding.getLocalSetters(this);
-}
-
-/// Strategy pattern for creating different encodings of a declared field.
-///
-/// This is used to provide lowerings for late fields using synthesized getters
-/// and setters.
-abstract class FieldEncoding {
-  /// The type of the declared field.
-  abstract DartType type;
-
-  /// Creates the bodies needed for the field encoding using [initializer] as
-  /// the declared initializer expression.
-  ///
-  /// This method is not called for fields in outlines unless their are constant
-  /// or part of a const constructor.
-  void createBodies(CoreTypes coreTypes, Expression? initializer);
-
-  List<Initializer> createInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic});
-
-  /// Registers that the (implicit) setter associated with this field needs to
-  /// contain a runtime type check to deal with generic covariance.
-  void setGenericCovariantImpl();
-
-  /// Returns the field that holds the field value at runtime.
-  Field get field;
-
-  /// Returns the members that holds the field annotations.
-  Iterable<Annotatable> get annotatables;
-
-  /// Returns the member used to read the field value.
-  Member get readTarget;
-
-  /// Returns the member used to write to the field.
-  Member? get writeTarget;
-
-  /// Returns the generated members that are visible through exports.
-  Iterable<Member> get exportedMembers;
-
-  /// Creates the members necessary for this field encoding.
-  ///
-  /// This method is called for both outline and full compilation so the created
-  /// members should be without body. The member bodies are created through
-  /// [createBodies].
-  void build(
-      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder);
-
-  /// Calls [f] for each member needed for this field encoding.
-  void registerMembers(
-      SourceLibraryBuilder library,
-      SourceFieldBuilder fieldBuilder,
-      void Function(Member, BuiltMemberKind) f);
-
-  /// Returns a list of the field, getters and methods created by this field
-  /// encoding.
-  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder);
-
-  /// Returns a list of the setters created by this field encoding.
-  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder);
-
-  /// Ensures that the signatures all members created by this field encoding
-  /// are fully typed.
-  void completeSignature(CoreTypes coreTypes);
-
-  /// Returns `true` if this encoding is a late lowering.
-  bool get isLateLowering;
-}
-
-class RegularFieldEncoding implements FieldEncoding {
-  late final Field _field;
-
-  RegularFieldEncoding(String name, NameScheme nameScheme, Uri fileUri,
-      int charOffset, int charEndOffset,
-      {required bool isFinal,
-      required bool isConst,
-      required bool isLate,
-      required bool hasInitializer,
-      required bool isNonNullableByDefault,
-      required Reference? fieldReference,
-      required Reference? getterReference,
-      required Reference? setterReference}) {
-    // ignore: unnecessary_null_comparison
-    assert(isFinal != null);
-    // ignore: unnecessary_null_comparison
-    assert(isConst != null);
-    // ignore: unnecessary_null_comparison
-    assert(isLate != null);
-    // ignore: unnecessary_null_comparison
-    assert(hasInitializer != null);
-    bool isImmutable =
-        isLate ? (isFinal && hasInitializer) : (isFinal || isConst);
-    _field = isImmutable
-        ? new Field.immutable(
-            nameScheme.getFieldName(FieldNameType.Field, name,
-                isSynthesized: false),
-            isFinal: isFinal,
-            isConst: isConst,
-            isLate: isLate,
-            fileUri: fileUri,
-            fieldReference: fieldReference,
-            getterReference: getterReference)
-        : new Field.mutable(
-            nameScheme.getFieldName(FieldNameType.Field, name,
-                isSynthesized: false),
-            isFinal: isFinal,
-            isLate: isLate,
-            fileUri: fileUri,
-            fieldReference: fieldReference,
-            getterReference: getterReference,
-            setterReference: setterReference);
-    _field
-      ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = isNonNullableByDefault;
-  }
-
-  @override
-  DartType get type => _field.type;
-
-  @override
-  void set type(DartType value) {
-    _field.type = value;
-  }
-
-  @override
-  void completeSignature(CoreTypes coreTypes) {}
-
-  @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer) {
-    if (initializer != null) {
-      _field.initializer = initializer..parent = _field;
-    }
-  }
-
-  @override
-  List<Initializer> createInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic}) {
-    return <Initializer>[
-      new FieldInitializer(_field, value)
-        ..fileOffset = fileOffset
-        ..isSynthetic = isSynthetic
-    ];
-  }
-
-  @override
-  void build(
-      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
-    _field..isCovariantByDeclaration = fieldBuilder.isCovariantByDeclaration;
-    if (fieldBuilder.isExtensionMember) {
-      _field
-        ..isStatic = true
-        ..isExtensionMember = true;
-    } else {
-      bool isInstanceMember =
-          !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
-      _field
-        ..isStatic = !isInstanceMember
-        ..isExtensionMember = false;
-    }
-    _field.isLate = fieldBuilder.isLate;
-    updatePrivateMemberName(_field, libraryBuilder);
-  }
-
-  @override
-  void registerMembers(
-      SourceLibraryBuilder library,
-      SourceFieldBuilder fieldBuilder,
-      void Function(Member, BuiltMemberKind) f) {
-    f(
-        _field,
-        fieldBuilder.isExtensionMember
-            ? BuiltMemberKind.ExtensionField
-            : BuiltMemberKind.Field);
-  }
-
-  @override
-  void setGenericCovariantImpl() {
-    _field.isCovariantByClass = true;
-  }
-
-  @override
-  Field get field => _field;
-
-  @override
-  Iterable<Annotatable> get annotatables => [_field];
-
-  @override
-  Member get readTarget => _field;
-
-  @override
-  Member get writeTarget => _field;
-
-  @override
-  Iterable<Member> get exportedMembers => [_field];
-
-  @override
-  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
-      <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: false)];
-
-  @override
-  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
-      fieldBuilder.isAssignable
-          ? <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: true)]
-          : const <ClassMember>[];
-
-  @override
-  bool get isLateLowering => false;
-}
-
-class SourceFieldMember extends BuilderClassMember {
-  @override
-  final SourceFieldBuilder memberBuilder;
-
-  Covariance? _covariance;
-
-  @override
-  final bool forSetter;
-
-  SourceFieldMember(this.memberBuilder, {required this.forSetter})
-      // ignore: unnecessary_null_comparison
-      : assert(forSetter != null);
-
-  @override
-  void inferType(ClassMembersBuilder membersBuilder) {
-    memberBuilder._ensureType(membersBuilder);
-  }
-
-  @override
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    memberBuilder.registerOverrideDependency(overriddenMembers);
-  }
-
-  @override
-  Member getMember(ClassMembersBuilder membersBuilder) {
-    memberBuilder._ensureType(membersBuilder);
-    return memberBuilder.field;
-  }
-
-  @override
-  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
-    return _covariance ??= forSetter
-        ? new Covariance.fromMember(getMember(membersBuilder),
-            forSetter: forSetter)
-        : const Covariance.empty();
-  }
-
-  @override
-  bool get isSourceDeclaration => true;
-
-  @override
-  bool get isProperty => true;
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    return other is SourceFieldMember && memberBuilder == other.memberBuilder;
-  }
-}
-
-abstract class AbstractLateFieldEncoding implements FieldEncoding {
-  final String name;
-  final int fileOffset;
-  final int fileEndOffset;
-  DartType? _type;
-  late final Field _field;
-  Field? _lateIsSetField;
-  late Procedure _lateGetter;
-  Procedure? _lateSetter;
-
-  // If `true`, an isSet field is used even when the type of the field is
-  // not potentially nullable.
-  //
-  // This is used to force use isSet fields in mixed mode encoding since
-  // we cannot trust non-nullable fields to be initialized with non-null values.
-  final late_lowering.IsSetStrategy _isSetStrategy;
-  late_lowering.IsSetEncoding? _isSetEncoding;
-
-  // If `true`, the is-set field was register before the type was known to be
-  // nullable or non-nullable. In this case we do not try to remove it from
-  // the generated AST to avoid inconsistency between the class hierarchy used
-  // during and after inference.
-  //
-  // This is also used to force use isSet fields in mixed mode encoding since
-  // we cannot trust non-nullable fields to be initialized with non-null values.
-  bool _forceIncludeIsSetField;
-
-  AbstractLateFieldEncoding(
-      this.name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      bool isCovariantByDeclaration,
-      late_lowering.IsSetStrategy isSetStrategy)
-      : fileOffset = charOffset,
-        fileEndOffset = charEndOffset,
-        _isSetStrategy = isSetStrategy,
-        _forceIncludeIsSetField =
-            isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
-    _field = new Field.mutable(
-        nameScheme.getFieldName(FieldNameType.Field, name, isSynthesized: true),
-        fileUri: fileUri,
-        fieldReference: fieldReference,
-        getterReference: fieldGetterReference,
-        setterReference: fieldSetterReference)
-      ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = true
-      ..isInternalImplementation = true;
-    switch (_isSetStrategy) {
-      case late_lowering.IsSetStrategy.useSentinelOrNull:
-      case late_lowering.IsSetStrategy.forceUseSentinel:
-        // [_lateIsSetField] is never needed.
-        break;
-      case late_lowering.IsSetStrategy.forceUseIsSetField:
-      case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
-        _lateIsSetField = new Field.mutable(
-            nameScheme.getFieldName(FieldNameType.IsSetField, name,
-                isSynthesized: true),
-            fileUri: fileUri,
-            fieldReference: lateIsSetFieldReference,
-            getterReference: lateIsSetGetterReference,
-            setterReference: lateIsSetSetterReference)
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = true
-          ..isInternalImplementation = true;
-        break;
-    }
-    _lateGetter = new Procedure(
-        nameScheme.getFieldName(FieldNameType.Getter, name,
-            isSynthesized: true),
-        ProcedureKind.Getter,
-        new FunctionNode(null)
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset,
-        fileUri: fileUri,
-        reference: lateGetterReference)
-      ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = true;
-    _lateSetter = _createSetter(
-        nameScheme.getFieldName(FieldNameType.Setter, name,
-            isSynthesized: true),
-        fileUri,
-        charOffset,
-        lateSetterReference,
-        isCovariantByDeclaration: isCovariantByDeclaration);
-  }
-
-  late_lowering.IsSetEncoding get isSetEncoding {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return _isSetEncoding ??=
-        late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
-  }
-
-  @override
-  void completeSignature(CoreTypes coreTypes) {
-    _lateIsSetField?.type = coreTypes.boolRawType(Nullability.nonNullable);
-  }
-
-  @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
-      _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
-          new Arguments([], types: [_type!])..fileOffset = fileOffset)
-        ..fileOffset = fileOffset
-        ..parent = _field;
-    } else {
-      _field.initializer = new NullLiteral()
-        ..fileOffset = fileOffset
-        ..parent = _field;
-    }
-    if (_lateIsSetField != null) {
-      _lateIsSetField!.initializer = new BoolLiteral(false)
-        ..fileOffset = fileOffset
-        ..parent = _lateIsSetField;
-    }
-    _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
-      ..parent = _lateGetter.function;
-    if (_lateSetter != null) {
-      _lateSetter!.function.body = _createSetterBody(
-          coreTypes, name, _lateSetter!.function.positionalParameters.first)
-        ..parent = _lateSetter!.function;
-    }
-  }
-
-  @override
-  List<Initializer> createInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic}) {
-    List<Initializer> initializers = <Initializer>[];
-    if (_lateIsSetField != null) {
-      initializers.add(new FieldInitializer(
-          _lateIsSetField!, new BoolLiteral(true)..fileOffset = fileOffset)
-        ..fileOffset = fileOffset
-        ..isSynthetic = isSynthetic);
-    }
-    initializers.add(new FieldInitializer(_field, value)
-      ..fileOffset = fileOffset
-      ..isSynthetic = isSynthetic);
-    return initializers;
-  }
-
-  /// Creates an [Expression] that reads [_field].
-  ///
-  /// If [needsPromotion] is `true`, the field will be read through a `let`
-  /// expression that promotes the expression to [_type]. This is needed for a
-  /// sound encoding of fields with type variable type of undetermined
-  /// nullability.
-  Expression _createFieldRead({bool needsPromotion: false}) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    if (needsPromotion) {
-      VariableDeclaration variable = new VariableDeclaration.forValue(
-          _createFieldGet(_field),
-          type: _type!.withDeclaredNullability(Nullability.nullable))
-        ..fileOffset = fileOffset;
-      return new Let(
-          variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
-    } else {
-      return _createFieldGet(_field);
-    }
-  }
-
-  /// Creates an [Expression] that reads [field].
-  Expression _createFieldGet(Field field) {
-    if (field.isStatic) {
-      return new StaticGet(field)..fileOffset = fileOffset;
-    } else {
-      // No substitution needed for the result type, since any type variables
-      // in there are also in scope at the access site.
-      return new InstanceGet(InstanceAccessKind.Instance,
-          new ThisExpression()..fileOffset = fileOffset, field.name,
-          interfaceTarget: field, resultType: field.type)
-        ..fileOffset = fileOffset;
-    }
-  }
-
-  /// Creates an [Expression] that writes [value] to [field].
-  Expression _createFieldSet(Field field, Expression value) {
-    if (field.isStatic) {
-      return new StaticSet(field, value)..fileOffset = fileOffset;
-    } else {
-      return new InstanceSet(InstanceAccessKind.Instance,
-          new ThisExpression()..fileOffset = fileOffset, field.name, value,
-          interfaceTarget: field)
-        ..fileOffset = fileOffset;
-    }
-  }
-
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression? initializer);
-
-  Procedure? _createSetter(
-      Name name, Uri fileUri, int charOffset, Reference? reference,
-      {required bool isCovariantByDeclaration}) {
-    // ignore: unnecessary_null_comparison
-    assert(isCovariantByDeclaration != null);
-    VariableDeclaration parameter = new VariableDeclaration(null)
-      ..isCovariantByDeclaration = isCovariantByDeclaration
-      ..fileOffset = fileOffset;
-    return new Procedure(
-        name,
-        ProcedureKind.Setter,
-        new FunctionNode(null,
-            positionalParameters: [parameter], returnType: const VoidType())
-          ..fileOffset = charOffset
-          ..fileEndOffset = fileEndOffset,
-        fileUri: fileUri,
-        reference: reference)
-      ..fileOffset = charOffset
-      ..fileEndOffset = fileEndOffset
-      ..isNonNullableByDefault = true;
-  }
-
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter);
-
-  @override
-  DartType get type {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return _type!;
-  }
-
-  @override
-  void set type(DartType value) {
-    assert(_type == null || _type is ImplicitFieldType,
-        "Type has already been computed for field $name.");
-    _type = value;
-    if (value is! ImplicitFieldType) {
-      _field.type = value.withDeclaredNullability(Nullability.nullable);
-      _lateGetter.function.returnType = value;
-      if (_lateSetter != null) {
-        _lateSetter!.function.positionalParameters.single.type = value;
-      }
-      if (!_type!.isPotentiallyNullable && !_forceIncludeIsSetField) {
-        // We only need the is-set field if the field is potentially nullable.
-        //  Otherwise we use `null` to signal that the field is uninitialized.
-        _lateIsSetField = null;
-      }
-    }
-  }
-
-  @override
-  void setGenericCovariantImpl() {
-    _field.isCovariantByClass = true;
-    _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
-  }
-
-  @override
-  Field get field => _field;
-
-  @override
-  Iterable<Annotatable> get annotatables {
-    List<Annotatable> list = [_lateGetter];
-    if (_lateSetter != null) {
-      list.add(_lateSetter!);
-    }
-    return list;
-  }
-
-  @override
-  Member get readTarget => _lateGetter;
-
-  @override
-  Member? get writeTarget => _lateSetter;
-
-  @override
-  Iterable<Member> get exportedMembers {
-    if (_lateSetter != null) {
-      return [_lateGetter, _lateSetter!];
-    }
-    return [_lateGetter];
-  }
-
-  @override
-  void build(
-      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
-    bool isInstanceMember;
-    bool isExtensionMember = fieldBuilder.isExtensionMember;
-    if (isExtensionMember) {
-      _field
-        ..isStatic = true
-        ..isExtensionMember = isExtensionMember;
-      isInstanceMember = false;
-    } else {
-      isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
-      _field
-        ..isStatic = !isInstanceMember
-        ..isExtensionMember = false;
-    }
-    updatePrivateMemberName(_field, libraryBuilder);
-    if (_lateIsSetField != null) {
-      _lateIsSetField!
-        ..isStatic = !isInstanceMember
-        ..isStatic = _field.isStatic
-        ..isExtensionMember = isExtensionMember;
-      updatePrivateMemberName(_lateIsSetField!, libraryBuilder);
-    }
-    _lateGetter
-      ..isStatic = !isInstanceMember
-      ..isExtensionMember = isExtensionMember;
-    updatePrivateMemberName(_lateGetter, libraryBuilder);
-    if (_lateSetter != null) {
-      _lateSetter!
-        ..isStatic = !isInstanceMember
-        ..isExtensionMember = isExtensionMember;
-      updatePrivateMemberName(_lateSetter!, libraryBuilder);
-    }
-  }
-
-  @override
-  void registerMembers(
-      SourceLibraryBuilder library,
-      SourceFieldBuilder fieldBuilder,
-      void Function(Member, BuiltMemberKind) f) {
-    f(
-        _field,
-        fieldBuilder.isExtensionMember
-            ? BuiltMemberKind.ExtensionField
-            : BuiltMemberKind.Field);
-    if (_lateIsSetField != null) {
-      _forceIncludeIsSetField = true;
-      f(_lateIsSetField!, BuiltMemberKind.LateIsSetField);
-    }
-    f(_lateGetter, BuiltMemberKind.LateGetter);
-    if (_lateSetter != null) {
-      f(_lateSetter!, BuiltMemberKind.LateSetter);
-    }
-  }
-
-  @override
-  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
-    List<ClassMember> list = <ClassMember>[
-      new _SynthesizedFieldClassMember(
-          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
-          isInternalImplementation: true),
-      new _SynthesizedFieldClassMember(fieldBuilder, _lateGetter,
-          _SynthesizedFieldMemberKind.LateGetterSetter,
-          isInternalImplementation: false)
-    ];
-    if (_lateIsSetField != null) {
-      list.add(new _SynthesizedFieldClassMember(
-          fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
-          isInternalImplementation: true));
-    }
-    return list;
-  }
-
-  @override
-  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
-    List<ClassMember> list = <ClassMember>[
-      new _SynthesizedFieldClassMember(
-          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
-          forSetter: true, isInternalImplementation: true),
-    ];
-    if (_lateIsSetField != null) {
-      list.add(new _SynthesizedFieldClassMember(
-          fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
-          forSetter: true, isInternalImplementation: true));
-    }
-    if (_lateSetter != null) {
-      list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateSetter!,
-          _SynthesizedFieldMemberKind.LateGetterSetter,
-          forSetter: true, isInternalImplementation: false));
-    }
-    return list;
-  }
-
-  @override
-  bool get isLateLowering => true;
-}
-
-mixin NonFinalLate on AbstractLateFieldEncoding {
-  @override
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createSetterBody(
-        coreTypes, fileOffset, name, parameter, _type!,
-        shouldReturnValue: false,
-        createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value),
-        createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField!, value),
-        isSetEncoding: isSetEncoding);
-  }
-}
-
-mixin LateWithoutInitializer on AbstractLateFieldEncoding {
-  @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression? initializer) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createGetterBodyWithoutInitializer(
-        coreTypes, fileOffset, name, type,
-        createVariableRead: _createFieldRead,
-        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
-        isSetEncoding: isSetEncoding,
-        forField: true);
-  }
-}
-
-class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
-    with NonFinalLate, LateWithoutInitializer {
-  LateFieldWithoutInitializerEncoding(
-      String name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      bool isCovariantByDeclaration,
-      late_lowering.IsSetStrategy isSetStrategy)
-      : super(
-            name,
-            nameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-}
-
-class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
-    with NonFinalLate {
-  LateFieldWithInitializerEncoding(
-      String name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      bool isCovariantByDeclaration,
-      late_lowering.IsSetStrategy isSetStrategy)
-      : super(
-            name,
-            nameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-
-  @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression? initializer) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createGetterWithInitializer(
-        coreTypes, fileOffset, name, _type!, initializer!,
-        createVariableRead: _createFieldRead,
-        createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value),
-        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
-        createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField!, value),
-        isSetEncoding: isSetEncoding);
-  }
-}
-
-class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
-    with LateWithoutInitializer {
-  LateFinalFieldWithoutInitializerEncoding(
-      String name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      bool isCovariantByDeclaration,
-      late_lowering.IsSetStrategy isSetStrategy)
-      : super(
-            name,
-            nameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-
-  @override
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createSetterBodyFinal(
-        coreTypes, fileOffset, name, parameter, type,
-        shouldReturnValue: false,
-        createVariableRead: () => _createFieldGet(_field),
-        createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value),
-        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
-        createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField!, value),
-        isSetEncoding: isSetEncoding,
-        forField: true);
-  }
-}
-
-class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
-  LateFinalFieldWithInitializerEncoding(
-      String name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? fieldReference,
-      Reference? fieldGetterReference,
-      Reference? fieldSetterReference,
-      Reference? lateIsSetFieldReference,
-      Reference? lateIsSetGetterReference,
-      Reference? lateIsSetSetterReference,
-      Reference? lateGetterReference,
-      Reference? lateSetterReference,
-      bool isCovariantByDeclaration,
-      late_lowering.IsSetStrategy isSetStrategy)
-      : super(
-            name,
-            nameScheme,
-            fileUri,
-            charOffset,
-            charEndOffset,
-            fieldReference,
-            fieldGetterReference,
-            fieldSetterReference,
-            lateIsSetFieldReference,
-            lateIsSetGetterReference,
-            lateIsSetSetterReference,
-            lateGetterReference,
-            lateSetterReference,
-            isCovariantByDeclaration,
-            isSetStrategy);
-  @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression? initializer) {
-    assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createGetterWithInitializerWithRecheck(
-        coreTypes, fileOffset, name, _type!, initializer!,
-        createVariableRead: _createFieldRead,
-        createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value),
-        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
-        createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField!, value),
-        isSetEncoding: isSetEncoding,
-        forField: true);
-  }
-
-  @override
-  Procedure? _createSetter(
-          Name name, Uri fileUri, int charOffset, Reference? reference,
-          {required bool isCovariantByDeclaration}) =>
-      null;
-
-  @override
-  Statement _createSetterBody(
-          CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
-      throw new UnsupportedError(
-          '$runtimeType._createSetterBody is not supported.');
-}
-
-class _SynthesizedFieldClassMember implements ClassMember {
-  final SourceFieldBuilder fieldBuilder;
-  final _SynthesizedFieldMemberKind _kind;
-
-  final Member _member;
-
-  Covariance? _covariance;
-
-  @override
-  final bool forSetter;
-
-  @override
-  final bool isInternalImplementation;
-
-  _SynthesizedFieldClassMember(this.fieldBuilder, this._member, this._kind,
-      {this.forSetter: false, required this.isInternalImplementation})
-      // ignore: unnecessary_null_comparison
-      : assert(isInternalImplementation != null);
-
-  @override
-  Member getMember(ClassMembersBuilder membersBuilder) {
-    fieldBuilder._ensureType(membersBuilder);
-    return _member;
-  }
-
-  @override
-  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
-    return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
-        forSetter: forSetter);
-  }
-
-  @override
-  void inferType(ClassMembersBuilder membersBuilder) {
-    fieldBuilder._ensureType(membersBuilder);
-  }
-
-  @override
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    fieldBuilder.registerOverrideDependency(overriddenMembers);
-  }
-
-  @override
-  bool get isSourceDeclaration => true;
-
-  @override
-  bool get isProperty => isField || isGetter || isSetter;
-
-  @override
-  ClassBuilder get classBuilder => fieldBuilder.classBuilder!;
-
-  @override
-  bool isObjectMember(ClassBuilder objectClass) {
-    return classBuilder == objectClass;
-  }
-
-  @override
-  bool get isDuplicate => fieldBuilder.isDuplicate;
-
-  @override
-  bool get isStatic => fieldBuilder.isStatic;
-
-  @override
-  bool get isField => _member is Field;
-
-  @override
-  bool get isAssignable {
-    Member field = _member;
-    return field is Field && field.hasSetter;
-  }
-
-  @override
-  bool get isSetter {
-    Member procedure = _member;
-    return procedure is Procedure && procedure.kind == ProcedureKind.Setter;
-  }
-
-  @override
-  bool get isGetter {
-    Member procedure = _member;
-    return procedure is Procedure && procedure.kind == ProcedureKind.Getter;
-  }
-
-  @override
-  bool get isFinal {
-    Member field = _member;
-    return field is Field && field.isFinal;
-  }
-
-  @override
-  bool get isConst {
-    Member field = _member;
-    return field is Field && field.isConst;
-  }
-
-  @override
-  Name get name => _member.name;
-
-  @override
-  String get fullName {
-    String suffix = isSetter ? "=" : "";
-    String className = classBuilder.fullNameForErrors;
-    // ignore: unnecessary_null_comparison
-    return className == null
-        ? "${fullNameForErrors}$suffix"
-        : "${className}.${fullNameForErrors}$suffix";
-  }
-
-  @override
-  String get fullNameForErrors => fieldBuilder.fullNameForErrors;
-
-  @override
-  Uri get fileUri => fieldBuilder.fileUri;
-
-  @override
-  int get charOffset => fieldBuilder.charOffset;
-
-  @override
-  bool get isAbstract => _member.isAbstract;
-
-  @override
-  bool get isSynthesized => false;
-
-  @override
-  bool get hasDeclarations => false;
-
-  @override
-  List<ClassMember> get declarations =>
-      throw new UnsupportedError("$runtimeType.declarations");
-
-  @override
-  ClassMember get interfaceMember => this;
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    if (identical(this, other)) return true;
-    return other is _SynthesizedFieldClassMember &&
-        fieldBuilder == other.fieldBuilder &&
-        _kind == other._kind;
-  }
-
-  @override
-  String toString() => '_SynthesizedFieldClassMember('
-      '$fieldBuilder,$_member,$_kind,forSetter=${forSetter})';
-}
-
-class AbstractOrExternalFieldEncoding implements FieldEncoding {
-  final SourceFieldBuilder _fieldBuilder;
-  final bool isAbstract;
-  final bool isExternal;
-  final bool _isExtensionInstanceMember;
-
-  late Procedure _getter;
-  Procedure? _setter;
-  DartType? _type;
-
-  AbstractOrExternalFieldEncoding(
-      this._fieldBuilder,
-      String name,
-      NameScheme nameScheme,
-      Uri fileUri,
-      int charOffset,
-      int charEndOffset,
-      Reference? getterReference,
-      Reference? setterReference,
-      {required this.isAbstract,
-      required this.isExternal,
-      required bool isFinal,
-      required bool isCovariantByDeclaration,
-      required bool isNonNullableByDefault})
-      // ignore: unnecessary_null_comparison
-      : assert(isAbstract != null),
-        // ignore: unnecessary_null_comparison
-        assert(isExternal != null),
-        // ignore: unnecessary_null_comparison
-        assert(isFinal != null),
-        // ignore: unnecessary_null_comparison
-        assert(isCovariantByDeclaration != null),
-        // ignore: unnecessary_null_comparison
-        assert(isNonNullableByDefault != null),
-        _isExtensionInstanceMember = isExternal &&
-            nameScheme.isExtensionMember &&
-            nameScheme.isInstanceMember {
-    if (_isExtensionInstanceMember) {
-      _getter = new Procedure(
-          nameScheme.getProcedureName(ProcedureKind.Getter, name),
-          ProcedureKind.Method,
-          new FunctionNode(null, positionalParameters: [
-            new VariableDeclaration(extensionThisName)..fileOffset
-          ]),
-          fileUri: fileUri,
-          reference: getterReference)
-        ..fileOffset = charOffset
-        ..fileEndOffset = charEndOffset
-        ..isNonNullableByDefault = isNonNullableByDefault;
-      if (!isFinal) {
-        VariableDeclaration parameter =
-            new VariableDeclaration("#externalFieldValue")
-              ..isCovariantByDeclaration = isCovariantByDeclaration
-              ..fileOffset = charOffset;
-        _setter = new Procedure(
-            nameScheme.getProcedureName(ProcedureKind.Setter, name),
-            ProcedureKind.Method,
-            new FunctionNode(null,
-                positionalParameters: [
-                  new VariableDeclaration(extensionThisName)..fileOffset,
-                  parameter
-                ],
-                returnType: const VoidType())
-              ..fileOffset = charOffset
-              ..fileEndOffset = charEndOffset,
-            fileUri: fileUri,
-            reference: setterReference)
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = isNonNullableByDefault;
-      }
-    } else {
-      _getter = new Procedure(
-          nameScheme.getFieldName(FieldNameType.Getter, name,
-              isSynthesized: true),
-          ProcedureKind.Getter,
-          new FunctionNode(null),
-          fileUri: fileUri,
-          reference: getterReference)
-        ..fileOffset = charOffset
-        ..fileEndOffset = charEndOffset
-        ..isNonNullableByDefault = isNonNullableByDefault;
-      if (!isFinal) {
-        VariableDeclaration parameter =
-            new VariableDeclaration("#externalFieldValue")
-              ..isCovariantByDeclaration = isCovariantByDeclaration
-              ..fileOffset = charOffset;
-        _setter = new Procedure(
-            nameScheme.getFieldName(FieldNameType.Setter, name,
-                isSynthesized: true),
-            ProcedureKind.Setter,
-            new FunctionNode(null,
-                positionalParameters: [parameter], returnType: const VoidType())
-              ..fileOffset = charOffset
-              ..fileEndOffset = charEndOffset,
-            fileUri: fileUri,
-            reference: setterReference)
-          ..fileOffset = charOffset
-          ..fileEndOffset = charEndOffset
-          ..isNonNullableByDefault = isNonNullableByDefault;
-      }
-    }
-  }
-
-  @override
-  DartType get type {
-    assert(_type != null,
-        "Type has not been computed for field ${_fieldBuilder.name}.");
-    return _type!;
-  }
-
-  @override
-  void set type(DartType value) {
-    assert(_type == null || _type is ImplicitFieldType,
-        "Type has already been computed for field ${_fieldBuilder.name}.");
-    _type = value;
-    if (value is! ImplicitFieldType) {
-      if (_isExtensionInstanceMember) {
-        SourceExtensionBuilder extensionBuilder =
-            _fieldBuilder.parent as SourceExtensionBuilder;
-        DartType onType = extensionBuilder.extension.onType;
-        List<TypeParameter> typeParameters =
-            extensionBuilder.extension.typeParameters;
-        if (typeParameters.isNotEmpty) {
-          FreshTypeParameters getterTypeParameters =
-              getFreshTypeParameters(typeParameters);
-          _getter.function.positionalParameters.first.type =
-              getterTypeParameters.substitute(onType);
-          _getter.function.returnType = getterTypeParameters.substitute(value);
-          _getter.function.typeParameters =
-              getterTypeParameters.freshTypeParameters;
-          setParents(
-              getterTypeParameters.freshTypeParameters, _getter.function);
-
-          Procedure? setter = _setter;
-          if (setter != null) {
-            FreshTypeParameters setterTypeParameters =
-                getFreshTypeParameters(typeParameters);
-            setter.function.positionalParameters.first.type =
-                setterTypeParameters.substitute(onType);
-            setter.function.positionalParameters[1].type =
-                setterTypeParameters.substitute(value);
-            setter.function.typeParameters =
-                setterTypeParameters.freshTypeParameters;
-            setParents(
-                setterTypeParameters.freshTypeParameters, setter.function);
-          }
-        } else {
-          _getter.function.returnType = value;
-          _setter?.function.positionalParameters[1].type = value;
-          _getter.function.positionalParameters.first.type = onType;
-          _setter?.function.positionalParameters.first.type = onType;
-        }
-      } else {
-        _getter.function.returnType = value;
-        Procedure? setter = _setter;
-        if (setter != null) {
-          if (setter.kind == ProcedureKind.Method) {
-            setter.function.positionalParameters[1].type = value;
-          } else {
-            setter.function.positionalParameters.first.type = value;
-          }
-        }
-      }
-    }
-  }
-
-  @override
-  void completeSignature(CoreTypes coreTypes) {}
-
-  @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer) {
-    //assert(initializer != null);
-  }
-
-  @override
-  List<Initializer> createInitializer(int fileOffset, Expression value,
-      {required bool isSynthetic}) {
-    throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
-  }
-
-  @override
-  void build(
-      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
-    bool isExtensionMember = fieldBuilder.isExtensionMember;
-    bool isInstanceMember = !fieldBuilder.isExtensionMember &&
-        !fieldBuilder.isStatic &&
-        !fieldBuilder.isTopLevel;
-    _getter..isConst = fieldBuilder.isConst;
-    _getter
-      ..isStatic = !isInstanceMember
-      ..isExtensionMember = isExtensionMember
-      ..isAbstract = isAbstract && !isExternal
-      ..isExternal = isExternal;
-    updatePrivateMemberName(_getter, libraryBuilder);
-
-    if (_setter != null) {
-      _setter!
-        ..isStatic = !isInstanceMember
-        ..isExtensionMember = isExtensionMember
-        ..isAbstract = isAbstract && !isExternal
-        ..isExternal = isExternal;
-      updatePrivateMemberName(_setter!, libraryBuilder);
-    }
-  }
-
-  @override
-  void registerMembers(
-      SourceLibraryBuilder library,
-      SourceFieldBuilder fieldBuilder,
-      void Function(Member, BuiltMemberKind) f) {
-    f(
-        _getter,
-        fieldBuilder.isExtensionMember
-            ? BuiltMemberKind.ExtensionGetter
-            : BuiltMemberKind.Method);
-    if (_setter != null) {
-      f(
-          _setter!,
-          fieldBuilder.isExtensionMember
-              ? BuiltMemberKind.ExtensionSetter
-              : BuiltMemberKind.Method);
-    }
-  }
-
-  @override
-  void setGenericCovariantImpl() {
-    _setter!.function.positionalParameters.first.isCovariantByClass = true;
-  }
-
-  @override
-  Field get field {
-    throw new UnsupportedError("ExternalFieldEncoding.field");
-  }
-
-  @override
-  Iterable<Annotatable> get annotatables {
-    List<Annotatable> list = [_getter];
-    if (_setter != null) {
-      list.add(_setter!);
-    }
-    return list;
-  }
-
-  @override
-  Member get readTarget => _getter;
-
-  @override
-  Member? get writeTarget => _setter;
-
-  @override
-  Iterable<Member> get exportedMembers {
-    if (_setter != null) {
-      return [_getter, _setter!];
-    }
-    return [_getter];
-  }
-
-  @override
-  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
-      <ClassMember>[
-        new _SynthesizedFieldClassMember(fieldBuilder, _getter,
-            _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
-            forSetter: false, isInternalImplementation: false)
-      ];
-
-  @override
-  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
-      _setter != null
-          ? <ClassMember>[
-              new _SynthesizedFieldClassMember(fieldBuilder, _setter!,
-                  _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
-                  forSetter: true, isInternalImplementation: false)
-            ]
-          : const <ClassMember>[];
-
-  @override
-  bool get isLateLowering => false;
-}
-
-enum _SynthesizedFieldMemberKind {
-  /// A `isSet` field used for late lowering.
-  LateIsSet,
-
-  /// A field used for the value of a late lowered field.
-  LateField,
-
-  /// A getter or setter used for late lowering.
-  LateGetterSetter,
-
-  /// A getter or setter used for abstract or external fields.
-  AbstractExternalGetterSetter,
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index 5c954d0..eefc5d1 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -9,36 +9,25 @@
         isMandatoryFormalParameterKind,
         isOptionalNamedFormalParameterKind,
         isOptionalPositionalFormalParameterKind;
-
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show FormalParameterKind;
-
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
 import 'package:kernel/ast.dart'
     show DartType, DynamicType, Expression, VariableDeclaration;
-
 import 'package:kernel/src/legacy_erasure.dart';
 
 import '../constant_context.dart' show ConstantContext;
-
-import '../modifier.dart';
-
-import '../scope.dart' show Scope;
-
-import '../source/source_library_builder.dart';
-
 import '../kernel/body_builder.dart' show BodyBuilder;
-
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-
+import '../modifier.dart';
+import '../scope.dart' show Scope;
+import '../source/source_factory_builder.dart';
+import '../source/source_field_builder.dart';
+import '../source/source_library_builder.dart';
 import '../util/helpers.dart' show DelayedActionPerformer;
-
 import 'builder.dart';
 import 'class_builder.dart';
 import 'constructor_builder.dart';
-import 'factory_builder.dart';
-import 'field_builder.dart';
 import 'library_builder.dart';
 import 'metadata_builder.dart';
 import 'modifier_builder.dart';
@@ -208,7 +197,7 @@
 
   void finalizeInitializingFormal(ClassBuilder classBuilder) {
     Builder? fieldBuilder = classBuilder.lookupLocalMember(name);
-    if (fieldBuilder is FieldBuilder) {
+    if (fieldBuilder is SourceFieldBuilder) {
       variable!.type = fieldBuilder.inferType();
     } else {
       variable!.type = const DynamicType();
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index 9bd4714..820d4bb 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -5,519 +5,10 @@
 library fasta.procedure_builder;
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
 
-import '../identifiers.dart';
-import '../scope.dart';
-
-import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/kernel_helper.dart';
-
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../messages.dart'
-    show
-        messagePatchDeclarationMismatch,
-        messagePatchDeclarationOrigin,
-        messagePatchNonExternal,
-        noLength,
-        templateRequiredNamedParameterHasDefaultValueError;
-
-import '../modifier.dart';
-
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import '../type_inference/type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly;
-
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'builder.dart';
-import 'class_builder.dart';
-import 'declaration_builder.dart';
-import 'extension_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'library_builder.dart';
 import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
 
 /// Common base class for constructor and procedure builders.
 abstract class FunctionBuilder implements MemberBuilder {
-  List<MetadataBuilder>? get metadata;
-
-  TypeBuilder? get returnType;
-
-  List<TypeVariableBuilder>? get typeVariables;
-
-  List<FormalParameterBuilder>? get formals;
-
-  AsyncMarker get asyncModifier;
-
-  @override
-  ProcedureKind? get kind;
-
-  @override
-  bool get isAbstract;
-
-  @override
-  bool get isConstructor;
-
-  @override
-  bool get isRegularMethod;
-
-  @override
-  bool get isGetter;
-
-  @override
-  bool get isSetter;
-
-  @override
-  bool get isOperator;
-
-  @override
-  bool get isFactory;
-
-  /// This is the formal parameter scope as specified in the Dart Programming
-  /// Language Specification, 4th ed, section 9.2.
-  Scope computeFormalParameterScope(Scope parent);
-
-  Scope computeFormalParameterInitializerScope(Scope parent);
-
-  /// This scope doesn't correspond to any scope specified in the Dart
-  /// Programming Language Specification, 4th ed. It's an unspecified extension
-  /// to support generic methods.
-  Scope computeTypeParameterScope(Scope parent);
-
-  FormalParameterBuilder? getFormal(Identifier identifier);
-
-  String? get nativeMethodName;
-
   FunctionNode get function;
-
-  Statement? get body;
-
-  void set body(Statement? newBody);
-
-  @override
-  bool get isNative;
-
-  /// Returns the [index]th parameter of this function.
-  ///
-  /// The index is the syntactical index, including both positional and named
-  /// parameter in the order they are declared, and excluding the synthesized
-  /// this parameter on extension instance members.
-  VariableDeclaration getFormalParameter(int index);
-
-  /// If this is an extension instance method or constructor with lowering
-  /// enabled, the tear off parameter corresponding to the [index]th parameter
-  /// on the instance method or constructor is returned.
-  ///
-  /// This is used to update the default value for the closure parameter when
-  /// it has been computed for the original parameter.
-  VariableDeclaration? getTearOffParameter(int index);
-
-  /// Returns the parameter for 'this' synthetically added to extension
-  /// instance members.
-  VariableDeclaration? get extensionThis;
-
-  /// Returns a list of synthetic type parameters added to extension instance
-  /// members.
-  List<TypeParameter>? get extensionTypeParameters;
-
-  void becomeNative(SourceLoader loader);
-
-  bool checkPatch(FunctionBuilder patch);
-
-  void reportPatchMismatch(Builder patch);
-}
-
-/// Common base class for constructor and procedure builders.
-abstract class FunctionBuilderImpl extends MemberBuilderImpl
-    implements FunctionBuilder {
-  @override
-  final List<MetadataBuilder>? metadata;
-
-  @override
-  final int modifiers;
-
-  @override
-  final TypeBuilder? returnType;
-
-  @override
-  final String name;
-
-  @override
-  final List<TypeVariableBuilder>? typeVariables;
-
-  @override
-  final List<FormalParameterBuilder>? formals;
-
-  /// If this procedure is an extension instance member, [_extensionThis] holds
-  /// the synthetically added `this` parameter.
-  VariableDeclaration? _extensionThis;
-
-  /// If this procedure is an extension instance member,
-  /// [_extensionTypeParameters] holds the type parameters copied from the
-  /// extension declaration.
-  List<TypeParameter>? _extensionTypeParameters;
-
-  FunctionBuilderImpl(
-      this.metadata,
-      this.modifiers,
-      this.returnType,
-      this.name,
-      this.typeVariables,
-      this.formals,
-      LibraryBuilder compilationUnit,
-      int charOffset,
-      this.nativeMethodName)
-      : super(compilationUnit, charOffset) {
-    if (formals != null) {
-      for (int i = 0; i < formals!.length; i++) {
-        formals![i].parent = this;
-      }
-    }
-  }
-
-  @override
-  String get debugName => "FunctionBuilder";
-
-  @override
-  AsyncMarker get asyncModifier;
-
-  @override
-  bool get isConstructor => false;
-
-  @override
-  bool get isAbstract => (modifiers & abstractMask) != 0;
-
-  @override
-  bool get isRegularMethod => identical(ProcedureKind.Method, kind);
-
-  @override
-  bool get isGetter => identical(ProcedureKind.Getter, kind);
-
-  @override
-  bool get isSetter => identical(ProcedureKind.Setter, kind);
-
-  @override
-  bool get isOperator => identical(ProcedureKind.Operator, kind);
-
-  @override
-  bool get isFactory => identical(ProcedureKind.Factory, kind);
-
-  @override
-  bool get isExternal => (modifiers & externalMask) != 0;
-
-  @override
-  bool get isAssignable => false;
-
-  @override
-  Scope computeFormalParameterScope(Scope parent) {
-    if (formals == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
-    for (FormalParameterBuilder formal in formals!) {
-      if (!isConstructor ||
-          !formal.isInitializingFormal && !formal.isSuperInitializingFormal) {
-        local[formal.name] = formal;
-      }
-    }
-    return new Scope(
-        local: local,
-        parent: parent,
-        debugName: "formal parameter",
-        isModifiable: false);
-  }
-
-  @override
-  Scope computeFormalParameterInitializerScope(Scope parent) {
-    // From
-    // [dartLangSpec.tex](../../../../../../docs/language/dartLangSpec.tex) at
-    // revision 94b23d3b125e9d246e07a2b43b61740759a0dace:
-    //
-    // When the formal parameter list of a non-redirecting generative
-    // constructor contains any initializing formals, a new scope is
-    // introduced, the _formal parameter initializer scope_, which is the
-    // current scope of the initializer list of the constructor, and which is
-    // enclosed in the scope where the constructor is declared.  Each
-    // initializing formal in the formal parameter list introduces a final
-    // local variable into the formal parameter initializer scope, but not into
-    // the formal parameter scope; every other formal parameter introduces a
-    // local variable into both the formal parameter scope and the formal
-    // parameter initializer scope.
-
-    if (formals == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
-    for (FormalParameterBuilder formal in formals!) {
-      local[formal.name] = formal.forFormalParameterInitializerScope();
-    }
-    return new Scope(
-        local: local,
-        parent: parent,
-        debugName: "formal parameter initializer",
-        isModifiable: false);
-  }
-
-  @override
-  Scope computeTypeParameterScope(Scope parent) {
-    if (typeVariables == null) return parent;
-    Map<String, Builder> local = <String, Builder>{};
-    for (TypeVariableBuilder variable in typeVariables!) {
-      local[variable.name] = variable;
-    }
-    return new Scope(
-        local: local,
-        parent: parent,
-        debugName: "type parameter",
-        isModifiable: false);
-  }
-
-  @override
-  FormalParameterBuilder? getFormal(Identifier identifier) {
-    if (formals != null) {
-      for (FormalParameterBuilder formal in formals!) {
-        if (formal.name == identifier.name &&
-            formal.charOffset == identifier.charOffset) {
-          return formal;
-        }
-      }
-      // If we have any formals we should find the one we're looking for.
-      assert(false, "$identifier not found in $formals");
-    }
-    return null;
-  }
-
-  @override
-  final String? nativeMethodName;
-
-  Statement? bodyInternal;
-
-  @override
-  void set body(Statement? newBody) {
-//    if (newBody != null) {
-//      if (isAbstract) {
-//        // TODO(danrubel): Is this check needed?
-//        return internalProblem(messageInternalProblemBodyOnAbstractMethod,
-//            newBody.fileOffset, fileUri);
-//      }
-//    }
-    bodyInternal = newBody;
-    // A forwarding semi-stub is a method that is abstract in the source code,
-    // but which needs to have a forwarding stub body in order to ensure that
-    // covariance checks occur.  We don't want to replace the forwarding stub
-    // body with null.
-    TreeNode? parent = function.parent;
-    if (!(newBody == null &&
-        parent is Procedure &&
-        parent.isForwardingSemiStub)) {
-      function.body = newBody;
-      newBody?.parent = function;
-    }
-  }
-
-  @override
-  Statement? get body => bodyInternal ??= new EmptyStatement();
-
-  @override
-  bool get isNative => nativeMethodName != null;
-
-  void buildFunction(SourceLibraryBuilder library) {
-    function.asyncMarker = asyncModifier;
-    function.body = body;
-    body?.parent = function;
-    IncludesTypeParametersNonCovariantly? needsCheckVisitor;
-    if (!isConstructor && !isFactory && parent is ClassBuilder) {
-      Class enclosingClass = classBuilder!.cls;
-      if (enclosingClass.typeParameters.isNotEmpty) {
-        needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
-            enclosingClass.typeParameters,
-            // We are checking the parameter types which are in a
-            // contravariant position.
-            initialVariance: Variance.contravariant);
-      }
-    }
-    if (typeVariables != null) {
-      for (TypeVariableBuilder t in typeVariables!) {
-        TypeParameter parameter = t.parameter;
-        function.typeParameters.add(parameter);
-        if (needsCheckVisitor != null) {
-          if (parameter.bound.accept(needsCheckVisitor)) {
-            parameter.isCovariantByClass = true;
-          }
-        }
-      }
-      setParents(function.typeParameters, function);
-    }
-    if (formals != null) {
-      for (FormalParameterBuilder formal in formals!) {
-        VariableDeclaration parameter = formal.build(library, 0);
-        if (needsCheckVisitor != null) {
-          if (parameter.type.accept(needsCheckVisitor)) {
-            parameter.isCovariantByClass = true;
-          }
-        }
-        if (formal.isNamed) {
-          function.namedParameters.add(parameter);
-        } else {
-          function.positionalParameters.add(parameter);
-        }
-        parameter.parent = function;
-        if (formal.isRequired) {
-          function.requiredParameterCount++;
-        }
-
-        if (library.isNonNullableByDefault) {
-          // Required named parameters can't have default values.
-          if (formal.isNamedRequired && formal.initializerToken != null) {
-            library.addProblem(
-                templateRequiredNamedParameterHasDefaultValueError
-                    .withArguments(formal.name),
-                formal.charOffset,
-                formal.name.length,
-                formal.fileUri);
-          }
-        }
-      }
-    }
-    if (!isExtensionInstanceMember &&
-        isSetter &&
-        (formals?.length != 1 || formals![0].isOptional)) {
-      // Replace illegal parameters by single dummy parameter.
-      // Do this after building the parameters, since the diet listener
-      // assumes that parameters are built, even if illegal in number.
-      VariableDeclaration parameter =
-          new VariableDeclarationImpl("#synthetic", 0);
-      function.positionalParameters.clear();
-      function.positionalParameters.add(parameter);
-      parameter.parent = function;
-      function.namedParameters.clear();
-      function.requiredParameterCount = 1;
-    }
-    if (returnType != null) {
-      function.returnType = returnType!.build(library);
-    }
-    if (isExtensionInstanceMember) {
-      ExtensionBuilder extensionBuilder = parent as ExtensionBuilder;
-      _extensionThis = function.positionalParameters.first;
-      if (extensionBuilder.typeParameters != null) {
-        int count = extensionBuilder.typeParameters!.length;
-        _extensionTypeParameters = new List<TypeParameter>.generate(
-            count, (int index) => function.typeParameters[index],
-            growable: false);
-      }
-    }
-  }
-
-  @override
-  VariableDeclaration getFormalParameter(int index) {
-    if (isExtensionInstanceMember) {
-      return formals![index + 1].variable!;
-    } else {
-      return formals![index].variable!;
-    }
-  }
-
-  @override
-  VariableDeclaration? getTearOffParameter(int index) => null;
-
-  @override
-  VariableDeclaration? get extensionThis {
-    assert(_extensionThis != null || !isExtensionInstanceMember,
-        "ProcedureBuilder.extensionThis has not been set.");
-    return _extensionThis;
-  }
-
-  @override
-  List<TypeParameter>? get extensionTypeParameters {
-    // Use [_extensionThis] as marker for whether extension type parameters have
-    // been computed.
-    assert(_extensionThis != null || !isExtensionInstanceMember,
-        "ProcedureBuilder.extensionTypeParameters has not been set.");
-    return _extensionTypeParameters;
-  }
-
-  bool _hasBuiltOutlineExpressions = false;
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
-    if (!_hasBuiltOutlineExpressions) {
-      DeclarationBuilder? classOrExtensionBuilder =
-          isClassMember || isExtensionMember
-              ? parent as DeclarationBuilder
-              : null;
-      Scope parentScope = classOrExtensionBuilder?.scope ?? library.scope;
-      MetadataBuilder.buildAnnotations(member, metadata, library,
-          classOrExtensionBuilder, this, fileUri, parentScope);
-      if (typeVariables != null) {
-        for (int i = 0; i < typeVariables!.length; i++) {
-          typeVariables![i].buildOutlineExpressions(
-              library,
-              classOrExtensionBuilder,
-              this,
-              coreTypes,
-              delayedActionPerformers,
-              computeTypeParameterScope(parentScope));
-        }
-      }
-
-      if (formals != null) {
-        // For const constructors we need to include default parameter values
-        // into the outline. For all other formals we need to call
-        // buildOutlineExpressions to clear initializerToken to prevent
-        // consuming too much memory.
-        for (FormalParameterBuilder formal in formals!) {
-          formal.buildOutlineExpressions(library, delayedActionPerformers);
-        }
-      }
-      _hasBuiltOutlineExpressions = true;
-    }
-  }
-
-  Member build(SourceLibraryBuilder library);
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    MemberBuilder constructor = loader.getNativeAnnotation();
-    Arguments arguments =
-        new Arguments(<Expression>[new StringLiteral(nativeMethodName!)]);
-    Expression annotation;
-    if (constructor.isConstructor) {
-      annotation = new ConstructorInvocation(
-          constructor.member as Constructor, arguments)
-        ..isConst = true;
-    } else {
-      annotation =
-          new StaticInvocation(constructor.member as Procedure, arguments)
-            ..isConst = true;
-    }
-    member.addAnnotation(annotation);
-  }
-
-  @override
-  bool checkPatch(FunctionBuilder patch) {
-    if (!isExternal) {
-      patch.library.addProblem(
-          messagePatchNonExternal, patch.charOffset, noLength, patch.fileUri!,
-          context: [
-            messagePatchDeclarationOrigin.withLocation(
-                fileUri, charOffset, noLength)
-          ]);
-      return false;
-    }
-    return true;
-  }
-
-  @override
-  void reportPatchMismatch(Builder patch) {
-    library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
-        noLength, patch.fileUri!, context: [
-      messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
-    ]);
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index f2c63b8..c86c3c0 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -69,6 +69,10 @@
   /// This is the canonical uri for the library, for instance 'dart:core'.
   Uri get importUri;
 
+  /// If true, the library is not supported through the 'dart.library.*' value
+  /// used in conditional imports and `bool.fromEnvironment` constants.
+  bool get isUnsupported;
+
   Iterator<Builder> get iterator;
 
   NameIterator get nameIterator;
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 5fc860b..719b64d 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -5,19 +5,9 @@
 library fasta.member_builder;
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-
-import '../../base/common.dart';
 
 import '../kernel/hierarchy/class_member.dart';
-import '../kernel/kernel_helper.dart';
 import '../modifier.dart';
-import '../problems.dart' show unsupported;
-import '../source/source_library_builder.dart';
-import '../type_inference/type_inference_engine.dart'
-    show InferenceDataForTesting;
-import '../util/helpers.dart' show DelayedActionPerformer;
-
 import 'builder.dart';
 import 'class_builder.dart';
 import 'declaration_builder.dart';
@@ -77,12 +67,6 @@
   /// setter of a field.
   bool get isConflictingSetter;
 
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes);
-
   /// Returns the [ClassMember]s for the non-setter members created for this
   /// member builder.
   ///
@@ -100,6 +84,9 @@
 
 abstract class MemberBuilderImpl extends ModifierBuilderImpl
     implements MemberBuilder {
+  @override
+  String get name;
+
   /// For top-level members, the parent is set correctly during
   /// construction. However, for class members, the parent is initially the
   /// library and updated later.
@@ -107,19 +94,30 @@
   Builder? parent;
 
   @override
-  String get name;
-
-  @override
   final Uri fileUri;
 
-  MemberDataForTesting? dataForTesting;
-
   MemberBuilderImpl(this.parent, int charOffset, [Uri? fileUri])
-      : dataForTesting =
-            retainDataForTesting ? new MemberDataForTesting() : null,
-        this.fileUri = (fileUri ?? parent?.fileUri)!,
+      : this.fileUri = (fileUri ?? parent?.fileUri)!,
         super(parent, charOffset);
 
+  /// The builder for the enclosing class, if any.
+  ClassBuilder? get classBuilder =>
+      parent is ClassBuilder ? parent as ClassBuilder : null;
+
+  @override
+  LibraryBuilder get library {
+    if (parent is LibraryBuilder) {
+      LibraryBuilder library = parent as LibraryBuilder;
+      return library.partOfLibrary ?? library;
+    } else if (parent is ExtensionBuilder) {
+      ExtensionBuilder extension = parent as ExtensionBuilder;
+      return extension.library;
+    } else {
+      ClassBuilder cls = parent as ClassBuilder;
+      return cls.library;
+    }
+  }
+
   @override
   bool get isDeclarationInstanceMember => isDeclarationMember && !isStatic;
 
@@ -144,98 +142,17 @@
   @override
   bool get isNative => false;
 
-  bool get isRedirectingGenerativeConstructor => false;
-
   @override
   bool get isExternal => (modifiers & externalMask) != 0;
 
   @override
   bool get isAbstract => (modifiers & abstractMask) != 0;
 
-  bool? _isConflictingSetter;
-
   @override
-  bool get isConflictingSetter {
-    return _isConflictingSetter ??= false;
-  }
-
-  void set isConflictingSetter(bool value) {
-    assert(_isConflictingSetter == null,
-        '$this.isConflictingSetter has already been fixed.');
-    _isConflictingSetter = value;
-  }
-
-  @override
-  LibraryBuilder get library {
-    if (parent is LibraryBuilder) {
-      LibraryBuilder library = parent as LibraryBuilder;
-      return library.partOfLibrary ?? library;
-    } else if (parent is ExtensionBuilder) {
-      ExtensionBuilder extension = parent as ExtensionBuilder;
-      return extension.library;
-    } else {
-      ClassBuilder cls = parent as ClassBuilder;
-      return cls.library;
-    }
-  }
-
-  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
-  @override
-  ProcedureKind? get kind => unsupported("kind", charOffset, fileUri);
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers,
-      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
-
-  /// Builds the core AST structures for this member as needed for the outline.
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
+  bool get isConflictingSetter => false;
 
   @override
   String get fullNameForErrors => name;
-
-  @override
-  StringBuffer printOn(StringBuffer buffer) {
-    if (isClassMember) {
-      buffer.write(classBuilder!.name);
-      buffer.write('.');
-    }
-    buffer.write(name);
-    return buffer;
-  }
-
-  /// The builder for the enclosing class or extension, if any.
-  DeclarationBuilder? get declarationBuilder =>
-      parent is DeclarationBuilder ? parent as DeclarationBuilder : null;
-
-  /// The builder for the enclosing class, if any.
-  ClassBuilder? get classBuilder =>
-      parent is ClassBuilder ? parent as ClassBuilder : null;
-}
-
-enum BuiltMemberKind {
-  Constructor,
-  RedirectingFactory,
-  Field,
-  Method,
-  ExtensionField,
-  ExtensionMethod,
-  ExtensionGetter,
-  ExtensionSetter,
-  ExtensionOperator,
-  ExtensionTearOff,
-  LateIsSetField,
-  LateGetter,
-  LateSetter,
-}
-
-class MemberDataForTesting {
-  final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
-
-  MemberBuilder? patchForTesting;
 }
 
 /// Base class for implementing [ClassMember] for a [MemberBuilder].
@@ -318,13 +235,3 @@
   @override
   String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
 }
-
-/// If the name of [member] is private, update it to use the library reference
-/// of [libraryBuilder].
-// TODO(johnniwinther): Avoid having to update private names by setting
-// the correct library reference when creating parts.
-void updatePrivateMemberName(Member member, LibraryBuilder libraryBuilder) {
-  if (member.name.isPrivate) {
-    member.name = new Name(member.name.text, libraryBuilder.library);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 306c9aa..e66b50a 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -114,7 +114,8 @@
 
   NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments,
       this.fileUri, this.charOffset,
-      {required this.instanceTypeVariableAccess});
+      {required this.instanceTypeVariableAccess})
+      : assert(name is String || name is QualifiedName);
 
   NamedTypeBuilder.fromTypeDeclarationBuilder(
       TypeDeclarationBuilder this.declaration, this.nullabilityBuilder,
diff --git a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
index e9920a6..d2f1000 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
@@ -19,6 +19,9 @@
 
   /// Used when the type is declared without any nullability suffixes.
   omitted,
+
+  /// Used when the type is nullable without any nullability suffix.
+  inherent,
 }
 
 class NullabilityBuilder {
@@ -30,8 +33,15 @@
   const NullabilityBuilder.omitted()
       : _syntacticNullability = SyntacticNullability.omitted;
 
+  const NullabilityBuilder.inherent()
+      : _syntacticNullability = SyntacticNullability.inherent;
+
   bool get isOmitted => _syntacticNullability == SyntacticNullability.omitted;
 
+  bool get isInherent => _syntacticNullability == SyntacticNullability.inherent;
+
+  bool get isNullable => _syntacticNullability == SyntacticNullability.nullable;
+
   factory NullabilityBuilder.fromNullability(Nullability nullability) {
     switch (nullability) {
       case Nullability.nullable:
@@ -55,6 +65,7 @@
       case SyntacticNullability.legacy:
         return Nullability.legacy;
       case SyntacticNullability.nullable:
+      case SyntacticNullability.inherent:
         return Nullability.nullable;
       case SyntacticNullability.omitted:
         return ifOmitted;
@@ -70,6 +81,7 @@
         sb.write("?");
         return;
       case SyntacticNullability.omitted:
+      case SyntacticNullability.inherent:
         // Do nothing.
         return;
     }
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index f09dc0d..85e54ac 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -3,564 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/type_algebra.dart';
 
-import '../kernel/hierarchy/class_member.dart';
-import '../kernel/hierarchy/members_builder.dart';
-import '../kernel/member_covariance.dart';
-
-import '../source/name_scheme.dart';
-import '../source/source_loader.dart' show SourceLoader;
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import 'builder.dart';
-import 'extension_builder.dart';
-import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
 
 abstract class ProcedureBuilder implements FunctionBuilder {
-  int get charOpenParenOffset;
-
-  ProcedureBuilder? get patchForTesting;
-
-  AsyncMarker get actualAsyncModifier;
-
   Procedure get procedure;
 
   @override
   ProcedureKind get kind;
-
-  Procedure get actualProcedure;
-
-  @override
-  ProcedureBuilder get origin;
-
-  void set asyncModifier(AsyncMarker newModifier);
-
-  bool get isEligibleForTopLevelInference;
-
-  /// Returns `true` if this procedure is declared in an extension declaration.
-  bool get isExtensionMethod;
-}
-
-class SourceProcedureBuilder extends FunctionBuilderImpl
-    implements ProcedureBuilder {
-  @override
-  final int charOpenParenOffset;
-
-  @override
-  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
-
-  @override
-  final bool isExtensionInstanceMember;
-
-  late Procedure _procedure;
-
-  final Reference? _tearOffReference;
-
-  /// If this is an extension instance method then [_extensionTearOff] holds
-  /// the synthetically created tear off function.
-  Procedure? _extensionTearOff;
-
-  /// If this is an extension instance method then
-  /// [_extensionTearOffParameterMap] holds a map from the parameters of
-  /// the methods to the parameter of the closure returned in the tear-off.
-  ///
-  /// This map is used to set the default values on the closure parameters when
-  /// these have been built.
-  Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
-
-  @override
-  final ProcedureKind kind;
-
-  SourceProcedureBuilder? actualOrigin;
-
-  SourceProcedureBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder? returnType,
-      String name,
-      List<TypeVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      this.kind,
-      SourceLibraryBuilder libraryBuilder,
-      int startCharOffset,
-      int charOffset,
-      this.charOpenParenOffset,
-      int charEndOffset,
-      Reference? procedureReference,
-      this._tearOffReference,
-      AsyncMarker asyncModifier,
-      NameScheme nameScheme,
-      {required bool isExtensionMember,
-      required bool isInstanceMember,
-      String? nativeMethodName})
-      // ignore: unnecessary_null_comparison
-      : assert(isExtensionMember != null),
-        // ignore: unnecessary_null_comparison
-        assert(isInstanceMember != null),
-        assert(kind != ProcedureKind.Factory),
-        this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
-        super(metadata, modifiers, returnType, name, typeVariables, formals,
-            libraryBuilder, charOffset, nativeMethodName) {
-    _procedure = new Procedure(
-        nameScheme.getProcedureName(kind, name),
-        isExtensionInstanceMember ? ProcedureKind.Method : kind,
-        new FunctionNode(null),
-        fileUri: libraryBuilder.fileUri,
-        reference: procedureReference)
-      ..startFileOffset = startCharOffset
-      ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
-    this.asyncModifier = asyncModifier;
-    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
-      _extensionTearOff ??= new Procedure(
-          nameScheme.getProcedureName(ProcedureKind.Getter, name),
-          ProcedureKind.Method,
-          new FunctionNode(null),
-          isStatic: true,
-          isExtensionMember: true,
-          reference: _tearOffReference,
-          fileUri: fileUri)
-        ..isNonNullableByDefault = library.isNonNullableByDefault;
-    }
-  }
-
-  @override
-  ProcedureBuilder? get patchForTesting =>
-      dataForTesting?.patchForTesting as ProcedureBuilder?;
-
-  @override
-  AsyncMarker get asyncModifier => actualAsyncModifier;
-
-  @override
-  Statement? get body {
-    if (bodyInternal == null && !isAbstract && !isExternal) {
-      bodyInternal = new EmptyStatement();
-    }
-    return bodyInternal;
-  }
-
-  @override
-  void set asyncModifier(AsyncMarker newModifier) {
-    actualAsyncModifier = newModifier;
-    function.asyncMarker = actualAsyncModifier;
-    function.dartAsyncMarker = actualAsyncModifier;
-  }
-
-  @override
-  bool get isEligibleForTopLevelInference {
-    if (isDeclarationInstanceMember) {
-      if (returnType == null) return true;
-      if (formals != null) {
-        for (FormalParameterBuilder formal in formals!) {
-          if (formal.type == null) return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  @override
-  bool get isExtensionMethod {
-    return parent is ExtensionBuilder;
-  }
-
-  @override
-  Member get member => procedure;
-
-  @override
-  SourceProcedureBuilder get origin => actualOrigin ?? this;
-
-  @override
-  Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
-  @override
-  Procedure get actualProcedure => _procedure;
-
-  @override
-  FunctionNode get function => _procedure.function;
-
-  bool _typeEnsured = false;
-  Set<ClassMember>? _overrideDependencies;
-
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    assert(
-        overriddenMembers.every((overriddenMember) =>
-            overriddenMember.classBuilder != classBuilder),
-        "Unexpected override dependencies for $this: $overriddenMembers");
-    _overrideDependencies ??= {};
-    _overrideDependencies!.addAll(overriddenMembers);
-  }
-
-  void _ensureTypes(ClassMembersBuilder membersBuilder) {
-    if (_typeEnsured) return;
-    if (_overrideDependencies != null) {
-      if (isGetter) {
-        membersBuilder.inferGetterType(this, _overrideDependencies!);
-      } else if (isSetter) {
-        membersBuilder.inferSetterType(this, _overrideDependencies!);
-      } else {
-        membersBuilder.inferMethodType(this, _overrideDependencies!);
-      }
-      _overrideDependencies = null;
-    }
-    _typeEnsured = true;
-  }
-
-  @override
-  Member? get readTarget {
-    switch (kind) {
-      case ProcedureKind.Method:
-        return extensionTearOff ?? procedure;
-      case ProcedureKind.Getter:
-        return procedure;
-      case ProcedureKind.Factory:
-        return procedure;
-      case ProcedureKind.Operator:
-      case ProcedureKind.Setter:
-        return null;
-    }
-  }
-
-  @override
-  Member? get writeTarget {
-    switch (kind) {
-      case ProcedureKind.Setter:
-        return procedure;
-      case ProcedureKind.Method:
-      case ProcedureKind.Getter:
-      case ProcedureKind.Operator:
-      case ProcedureKind.Factory:
-        return null;
-    }
-  }
-
-  @override
-  Member? get invokeTarget {
-    switch (kind) {
-      case ProcedureKind.Method:
-      case ProcedureKind.Getter:
-      case ProcedureKind.Operator:
-      case ProcedureKind.Factory:
-        return procedure;
-      case ProcedureKind.Setter:
-        return null;
-    }
-  }
-
-  @override
-  Iterable<Member> get exportedMembers => [procedure];
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    Member member = build(library);
-    if (isExtensionMethod) {
-      switch (kind) {
-        case ProcedureKind.Method:
-          f(member, BuiltMemberKind.ExtensionMethod);
-          break;
-        case ProcedureKind.Getter:
-          f(member, BuiltMemberKind.ExtensionGetter);
-          break;
-        case ProcedureKind.Setter:
-          f(member, BuiltMemberKind.ExtensionSetter);
-          break;
-        case ProcedureKind.Operator:
-          f(member, BuiltMemberKind.ExtensionOperator);
-          break;
-        case ProcedureKind.Factory:
-          throw new UnsupportedError(
-              'Unexpected extension method kind ${kind}');
-      }
-      if (extensionTearOff != null) {
-        f(extensionTearOff!, BuiltMemberKind.ExtensionTearOff);
-      }
-    } else {
-      f(member, BuiltMemberKind.Method);
-    }
-  }
-
-  @override
-  Procedure build(SourceLibraryBuilder libraryBuilder) {
-    buildFunction(libraryBuilder);
-    _procedure.function.fileOffset = charOpenParenOffset;
-    _procedure.function.fileEndOffset = _procedure.fileEndOffset;
-    _procedure.isAbstract = isAbstract;
-    _procedure.isExternal = isExternal;
-    _procedure.isConst = isConst;
-    updatePrivateMemberName(_procedure, libraryBuilder);
-    if (isExtensionMethod) {
-      _procedure.isExtensionMember = true;
-      _procedure.isStatic = true;
-      if (isExtensionInstanceMember) {
-        assert(_procedure.kind == ProcedureKind.Method);
-      }
-    } else {
-      _procedure.isStatic = isStatic;
-    }
-    if (extensionTearOff != null) {
-      _buildExtensionTearOff(libraryBuilder, parent as ExtensionBuilder);
-      updatePrivateMemberName(extensionTearOff!, libraryBuilder);
-    }
-    return _procedure;
-  }
-
-  /// Creates a top level function that creates a tear off of an extension
-  /// instance method.
-  ///
-  /// For this declaration
-  ///
-  ///     extension E<T> on A<T> {
-  ///       X method<S>(S s, Y y) {}
-  ///     }
-  ///
-  /// we create the top level function
-  ///
-  ///     X E|method<T, S>(A<T> #this, S s, Y y) {}
-  ///
-  /// and the tear off function
-  ///
-  ///     X Function<S>(S, Y) E|get#method<T>(A<T> #this) {
-  ///       return (S s, Y y) => E|method<T, S>(#this, s, y);
-  ///     }
-  ///
-  void _buildExtensionTearOff(
-      SourceLibraryBuilder libraryBuilder, ExtensionBuilder extensionBuilder) {
-    assert(
-        _extensionTearOff != null, "No extension tear off created for $this.");
-
-    _extensionTearOffParameterMap = {};
-
-    int fileOffset = _procedure.fileOffset;
-    int fileEndOffset = _procedure.fileEndOffset;
-
-    int extensionTypeParameterCount =
-        extensionBuilder.typeParameters?.length ?? 0;
-
-    List<TypeParameter> typeParameters = <TypeParameter>[];
-
-    Map<TypeParameter, DartType> substitutionMap = {};
-    List<DartType> typeArguments = <DartType>[];
-    for (TypeParameter typeParameter in function.typeParameters) {
-      TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
-      typeParameters.add(newTypeParameter);
-      typeArguments.add(substitutionMap[typeParameter] =
-          new TypeParameterType.forAlphaRenaming(
-              typeParameter, newTypeParameter));
-    }
-
-    List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
-    List<TypeParameter> closureTypeParameters = <TypeParameter>[];
-    Substitution substitution = Substitution.fromMap(substitutionMap);
-    for (int index = 0; index < typeParameters.length; index++) {
-      TypeParameter newTypeParameter = typeParameters[index];
-      newTypeParameter.bound =
-          substitution.substituteType(function.typeParameters[index].bound);
-      newTypeParameter.defaultType = function.typeParameters[index].defaultType;
-      if (index < extensionTypeParameterCount) {
-        tearOffTypeParameters.add(newTypeParameter);
-      } else {
-        closureTypeParameters.add(newTypeParameter);
-      }
-    }
-
-    VariableDeclaration copyParameter(
-        VariableDeclaration parameter, DartType type,
-        {required bool isOptional}) {
-      VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
-          type: type,
-          isFinal: parameter.isFinal,
-          isLowered: parameter.isLowered)
-        ..fileOffset = parameter.fileOffset;
-      _extensionTearOffParameterMap![parameter] = newParameter;
-      return newParameter;
-    }
-
-    VariableDeclaration extensionThis = copyParameter(
-        function.positionalParameters.first,
-        substitution.substituteType(function.positionalParameters.first.type),
-        isOptional: false);
-
-    DartType closureReturnType =
-        substitution.substituteType(function.returnType);
-    List<VariableDeclaration> closurePositionalParameters = [];
-    List<Expression> closurePositionalArguments = [];
-
-    for (int position = 0;
-        position < function.positionalParameters.length;
-        position++) {
-      VariableDeclaration parameter = function.positionalParameters[position];
-      if (position == 0) {
-        /// Pass `this` as a captured variable.
-        closurePositionalArguments
-            .add(new VariableGet(extensionThis)..fileOffset = fileOffset);
-      } else {
-        DartType type = substitution.substituteType(parameter.type);
-        VariableDeclaration newParameter = copyParameter(parameter, type,
-            isOptional: position >= function.requiredParameterCount);
-        closurePositionalParameters.add(newParameter);
-        closurePositionalArguments
-            .add(new VariableGet(newParameter)..fileOffset = fileOffset);
-      }
-    }
-    List<VariableDeclaration> closureNamedParameters = [];
-    List<NamedExpression> closureNamedArguments = [];
-    for (VariableDeclaration parameter in function.namedParameters) {
-      DartType type = substitution.substituteType(parameter.type);
-      VariableDeclaration newParameter =
-          copyParameter(parameter, type, isOptional: true);
-      closureNamedParameters.add(newParameter);
-      closureNamedArguments.add(new NamedExpression(parameter.name!,
-          new VariableGet(newParameter)..fileOffset = fileOffset));
-    }
-
-    Statement closureBody = new ReturnStatement(
-        new StaticInvocation(
-            _procedure,
-            new Arguments(closurePositionalArguments,
-                types: typeArguments, named: closureNamedArguments))
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
-
-    FunctionExpression closure = new FunctionExpression(
-        new FunctionNode(closureBody,
-            typeParameters: closureTypeParameters,
-            positionalParameters: closurePositionalParameters,
-            namedParameters: closureNamedParameters,
-            requiredParameterCount:
-                _procedure.function.requiredParameterCount - 1,
-            returnType: closureReturnType)
-          ..fileOffset = fileOffset
-          ..fileEndOffset = fileEndOffset)
-      ..fileOffset = fileOffset;
-
-    _extensionTearOff!
-      ..function = (new FunctionNode(
-          new ReturnStatement(closure)..fileOffset = fileOffset,
-          typeParameters: tearOffTypeParameters,
-          positionalParameters: [extensionThis],
-          requiredParameterCount: 1,
-          returnType: closure.function.computeFunctionType(library.nonNullable))
-        ..fileOffset = fileOffset
-        ..fileEndOffset = fileEndOffset)
-      ..fileUri = fileUri
-      ..fileOffset = fileOffset
-      ..fileEndOffset = fileEndOffset;
-    _extensionTearOff!.function.parent = _extensionTearOff;
-  }
-
-  Procedure? get extensionTearOff => _extensionTearOff;
-
-  @override
-  VariableDeclaration? getTearOffParameter(int index) {
-    return _extensionTearOffParameterMap?[getFormalParameter(index)];
-  }
-
-  List<ClassMember>? _localMembers;
-  List<ClassMember>? _localSetters;
-
-  @override
-  List<ClassMember> get localMembers => _localMembers ??= isSetter
-      ? const <ClassMember>[]
-      : <ClassMember>[new SourceProcedureMember(this)];
-
-  @override
-  List<ClassMember> get localSetters =>
-      _localSetters ??= isSetter && !isConflictingSetter
-          ? <ClassMember>[new SourceProcedureMember(this)]
-          : const <ClassMember>[];
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    _procedure.isExternal = true;
-    super.becomeNative(loader);
-  }
-
-  @override
-  void applyPatch(Builder patch) {
-    if (patch is SourceProcedureBuilder) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
-    }
-  }
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-
-    // TODO(ahe): restore file-offset once we track both origin and patch file
-    // URIs. See https://github.com/dart-lang/sdk/issues/31579
-    origin.procedure.fileUri = fileUri;
-    origin.procedure.startFileOffset = _procedure.startFileOffset;
-    origin.procedure.fileOffset = _procedure.fileOffset;
-    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
-    origin.procedure.annotations
-        .forEach((m) => m.fileOffset = _procedure.fileOffset);
-
-    origin.procedure.isAbstract = _procedure.isAbstract;
-    origin.procedure.isExternal = _procedure.isExternal;
-    origin.procedure.function = _procedure.function;
-    origin.procedure.function.parent = origin.procedure;
-    origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
-    return 1;
-  }
-}
-
-class SourceProcedureMember extends BuilderClassMember {
-  @override
-  final SourceProcedureBuilder memberBuilder;
-
-  Covariance? _covariance;
-
-  SourceProcedureMember(this.memberBuilder);
-
-  @override
-  bool get isSourceDeclaration => true;
-
-  @override
-  void inferType(ClassMembersBuilder membersBuilder) {
-    memberBuilder._ensureTypes(membersBuilder);
-  }
-
-  @override
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    memberBuilder.registerOverrideDependency(overriddenMembers);
-  }
-
-  @override
-  Member getMember(ClassMembersBuilder membersBuilder) {
-    memberBuilder._ensureTypes(membersBuilder);
-    return memberBuilder.member;
-  }
-
-  @override
-  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
-    return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
-        forSetter: forSetter);
-  }
-
-  @override
-  bool get forSetter => isSetter;
-
-  @override
-  bool get isProperty =>
-      memberBuilder.kind == ProcedureKind.Getter ||
-      memberBuilder.kind == ProcedureKind.Setter;
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    return other is SourceProcedureMember &&
-        memberBuilder == other.memberBuilder;
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index 2430ab7a..077db8d 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -6,7 +6,7 @@
 
 import 'package:kernel/ast.dart'
     show DartType, Nullability, TypeParameter, TypeParameterType;
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 
 import '../fasta_codes.dart'
     show
@@ -201,7 +201,7 @@
       SourceLibraryBuilder libraryBuilder,
       DeclarationBuilder? classOrExtensionBuilder,
       MemberBuilder? memberBuilder,
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       Scope scope) {
     MetadataBuilder.buildAnnotations(parameter, metadata, libraryBuilder,
diff --git a/pkg/front_end/lib/src/fasta/builder_graph.dart b/pkg/front_end/lib/src/fasta/builder_graph.dart
index 9e2b434..fdae514 100644
--- a/pkg/front_end/lib/src/fasta/builder_graph.dart
+++ b/pkg/front_end/lib/src/fasta/builder_graph.dart
@@ -23,13 +23,15 @@
 class BuilderGraph implements Graph<Uri> {
   final Map<Uri, LibraryBuilder> builders;
 
+  final Map<Uri, List<Uri>> _neighborsCache = {};
+
   BuilderGraph(this.builders);
 
   @override
   Iterable<Uri> get vertices => builders.keys;
 
-  @override
-  Iterable<Uri> neighborsOf(Uri vertex) sync* {
+  List<Uri> _computeNeighborsOf(Uri vertex) {
+    List<Uri> neighbors = [];
     LibraryBuilder? library = builders[vertex];
     if (library == null) {
       throw "Library not found: $vertex";
@@ -40,20 +42,20 @@
         if (import.imported != null) {
           Uri uri = import.imported!.importUri;
           if (builders.containsKey(uri)) {
-            yield uri;
+            neighbors.add(uri);
           }
         }
       }
       for (Export export in library.exports) {
         Uri uri = export.exported.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
       for (LibraryBuilder part in library.parts) {
         Uri uri = part.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
     } else if (library is DillLibraryBuilder) {
@@ -61,7 +63,7 @@
       for (LibraryDependency dependency in library.library.dependencies) {
         Uri uri = dependency.targetLibrary.importUri;
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
 
@@ -69,9 +71,14 @@
       for (LibraryPart part in library.library.parts) {
         Uri uri = getPartUri(library.importUri, part);
         if (builders.containsKey(uri)) {
-          yield uri;
+          neighbors.add(uri);
         }
       }
     }
+    return neighbors;
   }
+
+  @override
+  Iterable<Uri> neighborsOf(Uri vertex) =>
+      _neighborsCache[vertex] ??= _computeNeighborsOf(vertex);
 }
diff --git a/pkg/front_end/lib/src/fasta/combinator.dart b/pkg/front_end/lib/src/fasta/combinator.dart
index 9f07af0..4ac777e 100644
--- a/pkg/front_end/lib/src/fasta/combinator.dart
+++ b/pkg/front_end/lib/src/fasta/combinator.dart
@@ -10,10 +10,10 @@
   CombinatorBuilder(this.isShow, this.names, int charOffset, Uri fileUri);
 
   CombinatorBuilder.show(Iterable<String> names, int charOffset, Uri fileUri)
-      : this(true, new Set<String>.from(names), charOffset, fileUri);
+      : this(true, new Set<String>.of(names), charOffset, fileUri);
 
   CombinatorBuilder.hide(Iterable<String> names, int charOffset, Uri fileUri)
-      : this(false, new Set<String>.from(names), charOffset, fileUri);
+      : this(false, new Set<String>.of(names), charOffset, fileUri);
 
   bool get isHide => !isShow;
 }
diff --git a/pkg/front_end/lib/src/fasta/denylisted_classes.dart b/pkg/front_end/lib/src/fasta/denylisted_classes.dart
index 5df3707..345ec12 100644
--- a/pkg/front_end/lib/src/fasta/denylisted_classes.dart
+++ b/pkg/front_end/lib/src/fasta/denylisted_classes.dart
@@ -8,7 +8,6 @@
   "int",
   "num",
   "double",
-  "Enum",
   "String",
   "Null"
 ];
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 9ccfd18..18b8478 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
@@ -47,6 +47,9 @@
             cls.fileOffset);
 
   @override
+  DillClassBuilder get origin => this;
+
+  @override
   DillLibraryBuilder get library => super.library as DillLibraryBuilder;
 
   @override
@@ -77,9 +80,6 @@
     return supertype;
   }
 
-  @override
-  Class get actualCls => cls;
-
   void addField(Field field) {
     DillFieldBuilder builder = new DillFieldBuilder(field, this);
     String name = field.name.text;
@@ -171,6 +171,12 @@
     return super.interfaceBuilders;
   }
 
+  @override
+  void forEachConstructor(void Function(String, MemberBuilder) f,
+      {bool includeInjectedConstructors: false}) {
+    constructors.forEach(f);
+  }
+
   void clearCachedValues() {
     supertypeBuilder = null;
     interfaceBuilders = null;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
index 097bdc1..01f0010 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 
 import '../builder/extension_builder.dart';
 import '../builder/library_builder.dart';
@@ -108,7 +108,7 @@
   @override
   void buildOutlineExpressions(
       LibraryBuilder library,
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     // TODO(johnniwinther): Remove the need for this.
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 b367503..d09fac5 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
@@ -131,6 +131,9 @@
   }
 
   @override
+  bool get isUnsupported => library.isUnsupported;
+
+  @override
   bool get isSynthetic => library.isSynthetic;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index d800f03..21cde4c 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -5,17 +5,17 @@
 library fasta.dill_member_builder;
 
 import 'package:kernel/ast.dart'
-    show Constructor, Field, Member, Procedure, ProcedureKind;
+    show Constructor, Field, FunctionNode, Member, Procedure, ProcedureKind;
 
 import '../builder/builder.dart';
+import '../builder/constructor_builder.dart';
+import '../builder/field_builder.dart';
 import '../builder/member_builder.dart';
-import '../builder/library_builder.dart';
 
+import '../builder/procedure_builder.dart';
 import '../kernel/hierarchy/class_member.dart' show ClassMember;
 import '../kernel/hierarchy/members_builder.dart' show ClassMembersBuilder;
 import '../kernel/member_covariance.dart';
-import '../kernel/utils.dart'
-    show isRedirectingGenerativeConstructorImplementation;
 
 import '../modifier.dart'
     show abstractMask, constMask, externalMask, finalMask, lateMask, staticMask;
@@ -67,12 +67,6 @@
   bool get isFactory => identical(ProcedureKind.Factory, kind);
 
   @override
-  bool get isRedirectingGenerativeConstructor {
-    return isConstructor &&
-        isRedirectingGenerativeConstructorImplementation(member as Constructor);
-  }
-
-  @override
   bool get isSynthetic {
     final Member member = this.member;
     return member is Constructor && member.isSynthetic;
@@ -81,12 +75,6 @@
   @override
   bool get isAssignable => false;
 
-  @override
-  void buildMembers(
-      LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    throw new UnsupportedError('DillMemberBuilder.buildMembers');
-  }
-
   List<ClassMember>? _localMembers;
   List<ClassMember>? _localSetters;
 
@@ -102,7 +90,8 @@
           : const <ClassMember>[];
 }
 
-class DillFieldBuilder extends DillMemberBuilder {
+class DillFieldBuilder extends DillMemberBuilder implements FieldBuilder {
+  @override
   final Field field;
 
   DillFieldBuilder(this.field, Builder parent) : super(field, parent);
@@ -126,10 +115,23 @@
   bool get isAssignable => field.hasSetter;
 }
 
-class DillGetterBuilder extends DillMemberBuilder {
+abstract class DillProcedureBuilder extends DillMemberBuilder
+    implements ProcedureBuilder {
+  @override
   final Procedure procedure;
 
-  DillGetterBuilder(this.procedure, Builder parent)
+  DillProcedureBuilder(this.procedure, Builder parent)
+      : super(procedure, parent);
+
+  @override
+  ProcedureKind get kind => procedure.kind;
+
+  @override
+  FunctionNode get function => procedure.function;
+}
+
+class DillGetterBuilder extends DillProcedureBuilder {
+  DillGetterBuilder(Procedure procedure, Builder parent)
       : assert(procedure.kind == ProcedureKind.Getter),
         super(procedure, parent);
 
@@ -146,10 +148,8 @@
   Member get invokeTarget => procedure;
 }
 
-class DillSetterBuilder extends DillMemberBuilder {
-  final Procedure procedure;
-
-  DillSetterBuilder(this.procedure, Builder parent)
+class DillSetterBuilder extends DillProcedureBuilder {
+  DillSetterBuilder(Procedure procedure, Builder parent)
       : assert(procedure.kind == ProcedureKind.Setter),
         super(procedure, parent);
 
@@ -166,10 +166,8 @@
   Member? get invokeTarget => null;
 }
 
-class DillMethodBuilder extends DillMemberBuilder {
-  final Procedure procedure;
-
-  DillMethodBuilder(this.procedure, Builder parent)
+class DillMethodBuilder extends DillProcedureBuilder {
+  DillMethodBuilder(Procedure procedure, Builder parent)
       : assert(procedure.kind == ProcedureKind.Method),
         super(procedure, parent);
 
@@ -186,10 +184,8 @@
   Member get invokeTarget => procedure;
 }
 
-class DillOperatorBuilder extends DillMemberBuilder {
-  final Procedure procedure;
-
-  DillOperatorBuilder(this.procedure, Builder parent)
+class DillOperatorBuilder extends DillProcedureBuilder {
+  DillOperatorBuilder(Procedure procedure, Builder parent)
       : assert(procedure.kind == ProcedureKind.Operator),
         super(procedure, parent);
 
@@ -206,11 +202,10 @@
   Member get invokeTarget => procedure;
 }
 
-class DillFactoryBuilder extends DillMemberBuilder {
-  final Procedure procedure;
+class DillFactoryBuilder extends DillProcedureBuilder {
   final Procedure? _factoryTearOff;
 
-  DillFactoryBuilder(this.procedure, this._factoryTearOff, Builder parent)
+  DillFactoryBuilder(Procedure procedure, this._factoryTearOff, Builder parent)
       : super(procedure, parent);
 
   @override
@@ -226,7 +221,9 @@
   Member get invokeTarget => procedure;
 }
 
-class DillConstructorBuilder extends DillMemberBuilder {
+class DillConstructorBuilder extends DillMemberBuilder
+    implements ConstructorBuilder {
+  @override
   final Constructor constructor;
   final Procedure? _constructorTearOff;
 
@@ -235,6 +232,9 @@
       : super(constructor, parent);
 
   @override
+  FunctionNode get function => constructor.function;
+
+  @override
   Constructor get member => constructor;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/get_dependencies.dart b/pkg/front_end/lib/src/fasta/get_dependencies.dart
index 1db1afa..284b335 100644
--- a/pkg/front_end/lib/src/fasta/get_dependencies.dart
+++ b/pkg/front_end/lib/src/fasta/get_dependencies.dart
@@ -54,6 +54,6 @@
     kernelTarget.setEntryPoints(<Uri>[script]);
     dillTarget.buildOutlines();
     await kernelTarget.loader.buildOutlines();
-    return new List<Uri>.from(c.dependencies);
+    return new List<Uri>.of(c.dependencies);
   });
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 31d90c59..2aabaff 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -126,7 +126,7 @@
 
 import 'kernel/internal_ast.dart' show VariableDeclarationImpl;
 
-import 'kernel/kernel_target.dart' show KernelTarget;
+import 'kernel/kernel_target.dart' show BuildResult, KernelTarget;
 
 import 'library_graph.dart' show LibraryGraph;
 
@@ -351,13 +351,17 @@
       // Technically, it's the combination of
       // `currentKernelTarget.loader.libraries` and
       // `_dillLoadedData.loader.libraries`.
-      Component? componentWithDill = await currentKernelTarget.buildOutlines();
+      BuildResult buildResult = await currentKernelTarget.buildOutlines();
+      Component? componentWithDill = buildResult.component;
 
       if (!outlineOnly) {
         // Checkpoint: Build the actual bodies.
-        componentWithDill =
-            await currentKernelTarget.buildComponent(verify: c.options.verify);
+        buildResult = await currentKernelTarget.buildComponent(
+            macroApplications: buildResult.macroApplications,
+            verify: c.options.verify);
+        componentWithDill = buildResult.component;
       }
+      buildResult.macroApplications?.close();
       hierarchy ??= currentKernelTarget.loader.hierarchy;
       if (currentKernelTarget.classHierarchyChanges != null) {
         hierarchy.applyTreeChanges(
@@ -390,7 +394,7 @@
       // Compute which libraries to output and which (previous) errors/warnings
       // we have to reissue. In the process do some cleanup too.
       List<Library> compiledLibraries =
-          new List<Library>.from(currentKernelTarget.loader.libraries);
+          new List<Library>.of(currentKernelTarget.loader.libraries);
       Map<Uri, Source> uriToSource = componentWithDill!.uriToSource;
       _experimentalCompilationPostCompilePatchup(
           experimentalInvalidation, compiledLibraries, uriToSource);
@@ -478,6 +482,7 @@
         convertedLibraries[builder] = [dillBuilder];
       }
     }
+    nextGoodKernelTarget.loader.clearSourceLibraryBuilders();
     if (changed) {
       // We suppress finalization errors because they have already been
       // reported.
@@ -521,6 +526,7 @@
     }
     nextGoodKernelTarget.loader.buildersCreatedWithReferences.clear();
     nextGoodKernelTarget.loader.hierarchyBuilder.clear();
+    nextGoodKernelTarget.loader.membersBuilder.clear();
     nextGoodKernelTarget.loader.referenceFromIndex = null;
     convertedLibraries = null;
     experimentalInvalidation = null;
@@ -1731,9 +1737,18 @@
         packageLanguageVersion:
             new ImplicitLanguageVersion(libraryBuilder.library.languageVersion),
         loader: lastGoodKernelTarget.loader,
-        scope: libraryBuilder.scope.createNestedScope("expression"),
         nameOrigin: libraryBuilder,
+        isUnsupported: libraryBuilder.isUnsupported,
       );
+      libraryBuilder.scope.forEachLocalMember((name, member) {
+        debugLibrary.scope.addLocalMember(name, member, setter: false);
+      });
+      libraryBuilder.scope.forEachLocalSetter((name, member) {
+        debugLibrary.scope.addLocalMember(name, member, setter: true);
+      });
+      libraryBuilder.scope.forEachLocalExtension((member) {
+        debugLibrary.scope.addExtension(member);
+      });
       _ticker.logMs("Created debug library");
 
       if (libraryBuilder is DillLibraryBuilder) {
@@ -2040,7 +2055,7 @@
     IncrementalKernelTarget? lastGoodKernelTarget = this._lastGoodKernelTarget;
     if (lastGoodKernelTarget != null) {
       Set<Uri> uris =
-          new Set<Uri>.from(lastGoodKernelTarget.loader.libraryImportUris);
+          new Set<Uri>.of(lastGoodKernelTarget.loader.libraryImportUris);
       uris.removeAll(_dillLoadedData!.loader.libraryImportUris);
       if (_previousSourceBuilders != null) {
         for (Library library in _previousSourceBuilders!) {
@@ -2289,9 +2304,10 @@
 }
 
 class _InitializationFromComponent extends _InitializationStrategy {
-  Component componentToInitializeFrom;
+  Component? _componentToInitializeFrom;
 
-  _InitializationFromComponent(this.componentToInitializeFrom);
+  _InitializationFromComponent(Component componentToInitializeFrom)
+      : _componentToInitializeFrom = componentToInitializeFrom;
 
   @override
   Future<int> initialize(
@@ -2302,6 +2318,11 @@
       _ComponentProblems componentProblems,
       IncrementalSerializer? incrementalSerializer,
       RecorderForTesting? recorderForTesting) {
+    Component? componentToInitializeFrom = _componentToInitializeFrom;
+    _componentToInitializeFrom = null;
+    if (componentToInitializeFrom == null) {
+      throw const InitializeFromComponentError("Initialized twice.");
+    }
     dillLoadedData.ticker.logMs("About to initializeFromComponent");
 
     Component component = data.component = new Component(
@@ -2565,7 +2586,7 @@
 
     // Save any new component-problems.
     _addProblemsAsJson(componentWithDill.problemsAsJson);
-    return new List<String>.from(issuedProblems);
+    return new List<String>.of(issuedProblems);
   }
 
   void saveComponentProblems(Component component) {
diff --git a/pkg/front_end/lib/src/fasta/incremental_serializer.dart b/pkg/front_end/lib/src/fasta/incremental_serializer.dart
index 5803a9a..7289a11 100644
--- a/pkg/front_end/lib/src/fasta/incremental_serializer.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_serializer.dart
@@ -175,7 +175,7 @@
   }
 
   bool isSelfContained(Component component) {
-    Set<Library> got = new Set<Library>.from(component.libraries);
+    Set<Library> got = new Set<Library>.of(component.libraries);
     for (Library lib in component.libraries) {
       for (LibraryDependency dependency in lib.dependencies) {
         if (!got.contains(dependency.targetLibrary)) {
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 44ee19e..89b7847 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5,9 +5,7 @@
 library fasta.body_builder;
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show
         Assert,
@@ -20,7 +18,6 @@
         lengthForToken,
         lengthOfSpan,
         optional;
-
 import 'package:_fe_analyzer_shared/src/parser/quote.dart'
     show
         Quote,
@@ -32,13 +29,10 @@
 import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
     show FixedNullableList, GrowableList, NullValue, ParserRecovery;
 import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
 import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
     show isBinaryOperator, isMinusOperator, isUserDefinableOperator;
-
 import 'package:_fe_analyzer_shared/src/util/link.dart';
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/clone.dart';
@@ -52,12 +46,9 @@
 import '../builder/class_builder.dart';
 import '../builder/constructor_builder.dart';
 import '../builder/declaration_builder.dart';
-import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
-import '../builder/factory_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/formal_parameter_builder.dart';
-import '../builder/function_builder.dart';
 import '../builder/function_type_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
@@ -66,20 +57,15 @@
 import '../builder/named_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/prefix_builder.dart';
-import '../builder/procedure_builder.dart';
 import '../builder/type_alias_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
 import '../builder/variable_builder.dart';
 import '../builder/void_type_declaration_builder.dart';
-
 import '../constant_context.dart' show ConstantContext;
-
 import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
-
 import '../fasta_codes.dart' as fasta;
-
 import '../fasta_codes.dart'
     show
         LocatedMessage,
@@ -87,36 +73,31 @@
         Template,
         noLength,
         templateExperimentNotEnabled;
-
 import '../identifiers.dart'
     show Identifier, InitializedIdentifier, QualifiedName, flattenName;
-
-import '../kernel/utils.dart';
-
 import '../messages.dart' as messages show getLocationFromUri;
-
 import '../modifier.dart'
     show Modifier, constMask, covariantMask, finalMask, lateMask, requiredMask;
-
 import '../names.dart' show emptyName, minusName, plusName;
-
 import '../problems.dart'
     show internalProblem, unexpected, unhandled, unsupported;
-
 import '../scope.dart';
-
 import '../source/diet_parser.dart';
 import '../source/scope_listener.dart' show JumpTargetKind, ScopeListener;
+import '../source/source_class_builder.dart';
+import '../source/source_constructor_builder.dart';
+import '../source/source_enum_builder.dart';
+import '../source/source_factory_builder.dart';
+import '../source/source_field_builder.dart';
+import '../source/source_function_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_procedure_builder.dart';
 import '../source/stack_listener_impl.dart' show offsetForToken;
 import '../source/value_kinds.dart';
-
 import '../type_inference/type_inferrer.dart'
     show TypeInferrer, InferredFunctionBody, InitializerInferenceResult;
 import '../type_inference/type_schema.dart' show UnknownType;
-
 import '../util/helpers.dart' show DelayedActionPerformer;
-
 import 'collections.dart';
 import 'constness.dart' show Constness;
 import 'constructor_tearoff_lowering.dart';
@@ -158,8 +139,13 @@
   /// if any.
   final DeclarationBuilder? declarationBuilder;
 
-  /// The class or mixin declaration in which [member] is declared, if any.
-  final ClassBuilder? classBuilder;
+  /// The source class or mixin declaration in which [member] is declared, if
+  /// any.
+  ///
+  /// If [member] is a synthesized member for expression evaluation the
+  /// enclosing declaration might be a [DillClassBuilder]. This can be accessed
+  /// through [declarationBuilder].
+  final SourceClassBuilder? sourceClassBuilder;
 
   final ClassHierarchy hierarchy;
 
@@ -361,8 +347,9 @@
       required this.uri,
       required this.typeInferrer})
       : forest = const Forest(),
-        classBuilder =
-            declarationBuilder is ClassBuilder ? declarationBuilder : null,
+        sourceClassBuilder = declarationBuilder is SourceClassBuilder
+            ? declarationBuilder
+            : null,
         enableNative = libraryBuilder.loader.target.backendTarget
             .enableNative(libraryBuilder.importUri),
         stringExpectedAfterNative = libraryBuilder
@@ -371,8 +358,9 @@
             libraryBuilder.importUri.scheme == 'dart' &&
                 (libraryBuilder.importUri.path == "_builtin" ||
                     libraryBuilder.importUri.path == "ui"),
-        needsImplicitSuperInitializer = declarationBuilder is ClassBuilder &&
-            coreTypes.objectClass != declarationBuilder.cls,
+        needsImplicitSuperInitializer =
+            declarationBuilder is SourceClassBuilder &&
+                coreTypes.objectClass != declarationBuilder.cls,
         super(enclosingScope) {
     formalParameterScope?.forEach((String name, Builder builder) {
       if (builder is VariableBuilder) {
@@ -412,12 +400,13 @@
       DeclarationBuilder? declarationBuilder,
       ModifierBuilder member,
       Scope scope,
-      Uri fileUri)
+      Uri fileUri,
+      {Scope? formalParameterScope})
       : this(
             libraryBuilder: library,
             member: member,
             enclosingScope: scope,
-            formalParameterScope: null,
+            formalParameterScope: formalParameterScope,
             hierarchy: library.loader.hierarchy,
             coreTypes: library.loader.coreTypes,
             declarationBuilder: declarationBuilder,
@@ -810,7 +799,7 @@
     debugEvent("finishFields");
     assert(checkState(null, [/*field count*/ ValueKinds.Integer]));
     int count = pop() as int;
-    List<FieldBuilder> fields = <FieldBuilder>[];
+    List<SourceFieldBuilder> fields = [];
     for (int i = 0; i < count; i++) {
       assert(checkState(null, [
         ValueKinds.FieldInitializerOrNull,
@@ -826,9 +815,9 @@
       } else {
         declaration = libraryBuilder.lookupLocalMember(name, required: true)!;
       }
-      FieldBuilder fieldBuilder;
+      SourceFieldBuilder fieldBuilder;
       if (declaration.isField && declaration.next == null) {
-        fieldBuilder = declaration as FieldBuilder;
+        fieldBuilder = declaration as SourceFieldBuilder;
       } else {
         continue;
       }
@@ -853,8 +842,9 @@
             typeAliasedFactoryInvocations.remove(initializer);
           }
         } else {
-          initializer = typeInferrer.inferFieldInitializer(
-              this, fieldBuilder.builtType, initializer);
+          initializer = typeInferrer
+              .inferFieldInitializer(this, fieldBuilder.builtType, initializer)
+              .expression;
 
           if (transformCollections || transformSetLiterals) {
             // Wrap the initializer in a temporary parent expression; the
@@ -939,9 +929,9 @@
   }
 
   void prepareInitializers() {
-    FunctionBuilder member = this.member as FunctionBuilder;
+    SourceFunctionBuilder member = this.member as SourceFunctionBuilder;
     scope = member.computeFormalParameterInitializerScope(scope);
-    if (member is ConstructorBuilder) {
+    if (member is DeclaredSourceConstructorBuilder) {
       member.prepareInitializers();
       if (member.formals != null) {
         for (FormalParameterBuilder formal in member.formals!) {
@@ -1054,7 +1044,7 @@
   }
 
   DartType _computeReturnTypeContext(MemberBuilder member) {
-    if (member is ProcedureBuilder) {
+    if (member is SourceProcedureBuilder) {
       final bool isReturnTypeUndeclared = member.returnType == null &&
           member.function.returnType is DynamicType;
       return isReturnTypeUndeclared && libraryBuilder.isNonNullableByDefault
@@ -1073,7 +1063,7 @@
     debugEvent("finishFunction");
     typeInferrer.assignedVariables.finish();
 
-    final FunctionBuilder builder = member as FunctionBuilder;
+    final SourceFunctionBuilder builder = member as SourceFunctionBuilder;
     if (extensionThis != null) {
       typeInferrer.flowAnalysis.declare(extensionThis!, true);
     }
@@ -1085,7 +1075,8 @@
       for (int i = 0; i < formals.parameters!.length; i++) {
         FormalParameterBuilder parameter = formals.parameters![i];
         Expression? initializer = parameter.variable!.initializer;
-        if (parameter.isOptional || initializer != null) {
+        if (!parameter.isSuperInitializingFormal &&
+            (parameter.isOptional || initializer != null)) {
           if (!parameter.initializerWasInferred) {
             parameter.initializerWasInferred = true;
             if (parameter.isOptional) {
@@ -1124,9 +1115,9 @@
         }
       }
     }
-    if (builder is ConstructorBuilder) {
+    if (builder is DeclaredSourceConstructorBuilder) {
       finishConstructor(builder, asyncModifier, body);
-    } else if (builder is ProcedureBuilder) {
+    } else if (builder is SourceProcedureBuilder) {
       builder.asyncModifier = asyncModifier;
     } else if (builder is SourceFactoryBuilder) {
       builder.asyncModifier = asyncModifier;
@@ -1395,6 +1386,11 @@
   void _unaliasTypeAliasedConstructorInvocations() {
     for (TypeAliasedConstructorInvocation invocation
         in typeAliasedConstructorInvocations) {
+      if (!invocation.hasBeenInferred) {
+        assert(
+            isOrphaned(invocation), "Node $invocation has not been inferred.");
+        continue;
+      }
       bool inferred = !hasExplicitTypeArguments(invocation.arguments);
       DartType aliasedType = new TypedefType(
           invocation.typeAliasBuilder.typedef,
@@ -1424,6 +1420,11 @@
         typeAliasedFactoryInvocations.toList();
     typeAliasedFactoryInvocations.clear();
     for (TypeAliasedFactoryInvocation invocation in invocations) {
+      if (!invocation.hasBeenInferred) {
+        assert(
+            isOrphaned(invocation), "Node $invocation has not been inferred.");
+        continue;
+      }
       bool inferred = !hasExplicitTypeArguments(invocation.arguments);
       DartType aliasedType = new TypedefType(
           invocation.typeAliasBuilder.typedef,
@@ -1621,7 +1622,7 @@
     return fakeReturn.expression!;
   }
 
-  void parseInitializers(Token token) {
+  void parseInitializers(Token token, {bool doFinishConstructor = true}) {
     Parser parser = new Parser(this,
         useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
     if (!token.isEof) {
@@ -1630,9 +1631,10 @@
     } else {
       handleNoInitializers();
     }
-    // We are passing [AsyncMarker.Sync] because the error will be reported
-    // already.
-    finishConstructor(member as ConstructorBuilder, AsyncMarker.Sync, null);
+    if (doFinishConstructor) {
+      finishConstructor(
+          member as DeclaredSourceConstructorBuilder, AsyncMarker.Sync, null);
+    }
   }
 
   Expression parseFieldInitializer(Token token) {
@@ -1662,8 +1664,17 @@
     return annotation;
   }
 
-  void finishConstructor(
-      ConstructorBuilder builder, AsyncMarker asyncModifier, Statement? body) {
+  Arguments parseArguments(Token token) {
+    Parser parser = new Parser(this,
+        useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
+    token = parser.parseArgumentsRest(token);
+    Arguments arguments = pop() as Arguments;
+    checkEmpty(token.charOffset);
+    return arguments;
+  }
+
+  void finishConstructor(DeclaredSourceConstructorBuilder builder,
+      AsyncMarker asyncModifier, Statement? body) {
     /// Quotes below are from [Dart Programming Language Specification, 4th
     /// Edition](
     /// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf).
@@ -1723,11 +1734,13 @@
                   ]);
             } else {
               arguments.positional.addAll(positionalSuperParametersAsArguments);
+              setParents(positionalSuperParametersAsArguments, arguments);
             }
           }
           if (namedSuperParametersAsArguments != null) {
             // TODO(cstefantsova): Report name conflicts.
             arguments.named.addAll(namedSuperParametersAsArguments);
+            setParents(namedSuperParametersAsArguments, arguments);
           }
 
           LocatedMessage? message = checkArgumentsForFunction(
@@ -1766,6 +1779,37 @@
       constructor.initializers.add(buildInvalidInitializer(buildProblem(
           fasta.messageConstructorNotSync, body!.fileOffset, noLength)));
     }
+    if (libraryBuilder.enableEnhancedEnumsInLibrary &&
+        sourceClassBuilder is SourceEnumBuilder &&
+        constructor.initializers.isNotEmpty &&
+        constructor.initializers.last is RedirectingInitializer) {
+      RedirectingInitializer redirectingInitializer =
+          constructor.initializers.last as RedirectingInitializer;
+      redirectingInitializer.arguments.positional.insertAll(0, [
+        new VariableGet(constructor.function.positionalParameters[0])
+          ..parent = redirectingInitializer.arguments,
+        new VariableGet(constructor.function.positionalParameters[1])
+          ..parent = redirectingInitializer.arguments
+      ]);
+
+      LocatedMessage? message = checkArgumentsForFunction(
+          redirectingInitializer.target.function,
+          redirectingInitializer.arguments,
+          builder.charOffset, const <TypeParameter>[]);
+      if (message != null) {
+        Initializer invalidInitializer = buildInvalidInitializer(
+            buildUnresolvedError(
+                forest.createNullLiteral(redirectingInitializer.fileOffset),
+                constructorNameForDiagnostics(builder.name, isSuper: false),
+                redirectingInitializer.arguments,
+                redirectingInitializer.fileOffset,
+                isSuper: false,
+                message: message,
+                kind: UnresolvedKind.Constructor));
+        constructor.initializers.removeLast();
+        constructor.initializers.add(invalidInitializer..parent = constructor);
+      }
+    }
     if (needsImplicitSuperInitializer) {
       /// >If no superinitializer is provided, an implicit superinitializer
       /// >of the form super() is added at the end of k’s initializer list,
@@ -1773,10 +1817,25 @@
       Constructor? superTarget = lookupConstructor(emptyName, isSuper: true);
       Initializer initializer;
       Arguments arguments;
+      List<Expression>? positionalArguments;
+      List<NamedExpression>? namedArguments;
       if (libraryBuilder.enableSuperParametersInLibrary) {
+        positionalArguments = positionalSuperParametersAsArguments;
+        namedArguments = namedSuperParametersAsArguments;
+      }
+      if (sourceClassBuilder is SourceEnumBuilder) {
+        assert(constructor.function.positionalParameters.length >= 2 &&
+            constructor.function.positionalParameters[0].name == "index" &&
+            constructor.function.positionalParameters[1].name == "name");
+        (positionalArguments ??= <Expression>[]).insertAll(0, [
+          new VariableGet(constructor.function.positionalParameters[0]),
+          new VariableGet(constructor.function.positionalParameters[1])
+        ]);
+      }
+      if (positionalArguments != null || namedArguments != null) {
         arguments = forest.createArguments(
-            noLocation, positionalSuperParametersAsArguments ?? <Expression>[],
-            named: namedSuperParametersAsArguments);
+            noLocation, positionalArguments ?? <Expression>[],
+            named: namedArguments);
       } else {
         arguments = forest.createArgumentsEmpty(noLocation);
       }
@@ -1784,7 +1843,8 @@
           checkArgumentsForFunction(superTarget.function, arguments,
                   builder.charOffset, const <TypeParameter>[]) !=
               null) {
-        String superclass = classBuilder!.supertypeBuilder!.fullNameForErrors;
+        String superclass =
+            sourceClassBuilder!.supertypeBuilder!.fullNameForErrors;
         int length = constructor.name.text.length;
         if (length == 0) {
           length = (constructor.parent as Class).name.length;
@@ -1840,7 +1900,7 @@
     }
     List<Object?>? argumentsOriginalOrder;
     if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
-      argumentsOriginalOrder = new List<Object?>.from(arguments);
+      argumentsOriginalOrder = new List<Object?>.of(arguments);
     }
     int firstNamedArgumentIndex = arguments.length;
     int positionalCount = 0;
@@ -1890,6 +1950,7 @@
         assert(
             positionalIndex == positional.length && namedIndex == named.length);
       } else {
+        // arguments have non-null Expression entries after the initial loop.
         positional = new List<Expression>.from(
             arguments.getRange(0, firstNamedArgumentIndex));
         named = new List<NamedExpression>.from(
@@ -1901,6 +1962,8 @@
     } else {
       // TODO(kmillikin): Find a way to avoid allocating a second list in the
       // case where there were no named arguments, which is a common one.
+
+      // arguments have non-null Expression entries after the initial loop.
       push(forest.createArguments(
           beginToken.offset, new List<Expression>.from(arguments),
           argumentsOriginalOrder: argumentsOriginalOrder));
@@ -2521,15 +2584,15 @@
   }
 
   @override
-  Member? lookupInstanceMember(Name name,
-      {bool isSetter: false, bool isSuper: false}) {
-    return classBuilder!.lookupInstanceMember(hierarchy, name,
-        isSetter: isSetter, isSuper: isSuper);
+  Member? lookupSuperMember(Name name, {bool isSetter: false}) {
+    return (declarationBuilder as ClassBuilder).lookupInstanceMember(
+        hierarchy, name,
+        isSetter: isSetter, isSuper: true);
   }
 
   @override
   Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
-    return classBuilder!.lookupConstructor(name, isSuper: isSuper);
+    return sourceClassBuilder!.lookupConstructor(name, isSuper: isSuper);
   }
 
   @override
@@ -2608,9 +2671,9 @@
     Builder? declaration = scope.lookup(name, charOffset, uri);
     if (declaration == null &&
         prefix == null &&
-        (classBuilder?.isPatch ?? false)) {
+        (sourceClassBuilder?.isPatch ?? false)) {
       // The scope of a patched method includes the origin class.
-      declaration = classBuilder!.origin
+      declaration = sourceClassBuilder!.origin
           .findStaticBuilder(name, charOffset, uri, libraryBuilder);
     }
     if (declaration != null &&
@@ -3078,12 +3141,12 @@
     constantContext = member.isConst
         ? ConstantContext.inferred
         : !member.isStatic &&
-                classBuilder != null &&
-                classBuilder!.declaresConstConstructor
+                sourceClassBuilder != null &&
+                sourceClassBuilder!.declaresConstConstructor
             ? ConstantContext.required
             : ConstantContext.none;
-    if (member is FieldBuilder) {
-      FieldBuilder fieldBuilder = member as FieldBuilder;
+    if (member is SourceFieldBuilder) {
+      SourceFieldBuilder fieldBuilder = member as SourceFieldBuilder;
       inLateFieldInitializer = fieldBuilder.isLate;
       if (fieldBuilder.isAbstract) {
         addProblem(
@@ -3113,8 +3176,8 @@
     constantContext = member.isConst
         ? ConstantContext.inferred
         : !member.isStatic &&
-                classBuilder != null &&
-                classBuilder!.declaresConstConstructor
+                sourceClassBuilder != null &&
+                sourceClassBuilder!.declaresConstConstructor
             ? ConstantContext.required
             : ConstantContext.none;
     if (constantContext == ConstantContext.inferred) {
@@ -3988,7 +4051,7 @@
     push(new NamedTypeBuilder.fromTypeDeclarationBuilder(
         new VoidTypeDeclarationBuilder(
             const VoidType(), libraryBuilder, offset),
-        const NullabilityBuilder.nullable(),
+        const NullabilityBuilder.inherent(),
         fileUri: uri,
         charOffset: offset,
         instanceTypeVariableAccess:
@@ -4162,7 +4225,7 @@
     if (!inCatchClause &&
         functionNestingLevel == 0 &&
         memberKind != MemberKind.GeneralizedFunctionType) {
-      FunctionBuilder member = this.member as FunctionBuilder;
+      SourceFunctionBuilder member = this.member as SourceFunctionBuilder;
       parameter = member.getFormal(name!);
       if (parameter == null) {
         // This happens when the list of formals (originally) contains a
@@ -4824,8 +4887,8 @@
     }
     List<NamedExpression> named = forest.argumentsNamed(arguments);
     if (named.isNotEmpty) {
-      Set<String> parameterNames =
-          new Set.from(function.namedParameters.map((a) => a.name));
+      Set<String?> parameterNames =
+          new Set.of(function.namedParameters.map((a) => a.name));
       for (NamedExpression argument in named) {
         if (!parameterNames.contains(argument.name)) {
           return fasta.templateNoSuchNamedParameter
@@ -4836,7 +4899,7 @@
     }
     if (function.namedParameters.isNotEmpty) {
       if (libraryBuilder.isNonNullableByDefault) {
-        Set<String> argumentNames = new Set.from(named.map((a) => a.name));
+        Set<String> argumentNames = new Set.of(named.map((a) => a.name));
         for (VariableDeclaration parameter in function.namedParameters) {
           if (parameter.isRequired && !argumentNames.contains(parameter.name)) {
             return fasta.templateValueForRequiredParameterNotProvidedError
@@ -4897,7 +4960,7 @@
     List<NamedExpression> named = forest.argumentsNamed(arguments);
     if (named.isNotEmpty) {
       Set<String> names =
-          new Set.from(function.namedParameters.map((a) => a.name));
+          new Set.of(function.namedParameters.map((a) => a.name));
       for (NamedExpression argument in named) {
         if (!names.contains(argument.name)) {
           return fasta.templateNoSuchNamedParameter
@@ -4908,7 +4971,7 @@
     }
     if (function.namedParameters.isNotEmpty) {
       if (libraryBuilder.isNonNullableByDefault) {
-        Set<String> argumentNames = new Set.from(named.map((a) => a.name));
+        Set<String> argumentNames = new Set.of(named.map((a) => a.name));
         for (NamedType parameter in function.namedParameters) {
           if (parameter.isRequired && !argumentNames.contains(parameter.name)) {
             return fasta.templateValueForRequiredParameterNotProvidedError
@@ -5306,10 +5369,6 @@
       }
     }
     if (type is ClassBuilder) {
-      if (type is EnumBuilder) {
-        return buildProblem(fasta.messageEnumInstantiation,
-            nameToken.charOffset, nameToken.length);
-      }
       MemberBuilder? b =
           type.findConstructorOrFactory(name, charOffset, uri, libraryBuilder);
       Member? target;
@@ -5331,6 +5390,13 @@
       } else {
         target = b.member;
       }
+      if (type is SourceEnumBuilder &&
+          !(libraryBuilder.enableEnhancedEnumsInLibrary &&
+              target is Procedure &&
+              target.kind == ProcedureKind.Factory)) {
+        return buildProblem(fasta.messageEnumInstantiation,
+            nameToken.charOffset, nameToken.length);
+      }
       if (target is Constructor ||
           (target is Procedure && target.kind == ProcedureKind.Factory)) {
         Expression invocation;
@@ -5989,7 +6055,7 @@
               noLocation,
               noLocation,
               // New list because the declarations are not a growable list.
-              new List<Statement>.from(
+              new List<Statement>.of(
                   forest.variablesDeclarationExtractDeclarations(lvalue)));
         } else {
           effects = forest.createExpressionStatement(
@@ -6815,7 +6881,8 @@
                 name.length),
             fieldNameOffset)
       ];
-    } else if (builder is FieldBuilder && builder.isDeclarationInstanceMember) {
+    } else if (builder is SourceFieldBuilder &&
+        builder.isDeclarationInstanceMember) {
       initializedFields ??= <String, int>{};
       if (initializedFields!.containsKey(name)) {
         return <Initializer>[
@@ -6882,11 +6949,12 @@
                 uri,
                 context: [
                   fasta.messageInitializingFormalTypeMismatchField.withLocation(
-                      builder.fileUri!, builder.charOffset, noLength)
+                      builder.fileUri, builder.charOffset, noLength)
                 ]);
           }
         }
-        ConstructorBuilder constructorBuilder = member as ConstructorBuilder;
+        DeclaredSourceConstructorBuilder constructorBuilder =
+            member as DeclaredSourceConstructorBuilder;
         constructorBuilder.registerInitializedField(builder);
         return builder.buildInitializer(assignmentOffset, expression,
             isSynthetic: formal != null);
@@ -6921,7 +6989,7 @@
   Initializer buildRedirectingInitializer(
       Constructor constructor, Arguments arguments,
       [int charOffset = -1]) {
-    if (classBuilder!
+    if (sourceClassBuilder!
         .checkConstructorCyclic(member.name!, constructor.name.text)) {
       int length = constructor.name.text.length;
       if (length == 0) length = "this".length;
@@ -7081,7 +7149,7 @@
       Arguments? arguments, Expression expression) {
     if (arguments == null) return expression;
     List<Expression> expressions =
-        new List<Expression>.from(forest.argumentsPositional(arguments));
+        new List<Expression>.of(forest.argumentsPositional(arguments));
     for (NamedExpression named in forest.argumentsNamed(arguments)) {
       expressions.add(named.value);
     }
@@ -7141,7 +7209,7 @@
           offset,
           name.text.length);
     }
-    Member? target = lookupInstanceMember(name, isSuper: true);
+    Member? target = lookupSuperMember(name);
 
     if (target == null || (target is Procedure && !target.isAccessor)) {
       if (target == null) {
@@ -7270,7 +7338,7 @@
   String constructorNameForDiagnostics(String name,
       {String? className, bool isSuper: false}) {
     if (className == null) {
-      Class cls = classBuilder!.cls;
+      Class cls = sourceClassBuilder!.cls;
       if (isSuper) {
         cls = cls.superclass!;
         while (cls.isMixinApplication) {
@@ -7682,3 +7750,43 @@
     return super.visitArguments(node);
   }
 }
+
+/// Returns `true` if [node] is not part of its parent member.
+///
+/// This computation is costly and should only be used in assertions to verify
+/// that [node] has been removed from the AST.
+bool isOrphaned(TreeNode node) {
+  TreeNode? parent = node;
+  Member? member;
+  while (parent != null) {
+    if (parent is Member) {
+      member = parent;
+      break;
+    }
+    parent = parent.parent;
+  }
+  if (member == null) {
+    return true;
+  }
+  _FindChildVisitor visitor = new _FindChildVisitor(node);
+  member.accept(visitor);
+  return !visitor.foundNode;
+}
+
+class _FindChildVisitor extends Visitor<void> with VisitorVoidMixin {
+  final TreeNode soughtNode;
+  bool foundNode = false;
+
+  _FindChildVisitor(this.soughtNode);
+
+  @override
+  void defaultNode(Node node) {
+    if (!foundNode) {
+      if (identical(node, soughtNode)) {
+        foundNode = true;
+      } else {
+        node.visitChildren(this);
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index cf785bd..88168b6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -39,8 +39,8 @@
 part 'constant_collection_builders.dart';
 
 Component transformComponent(
+    Target target,
     Component component,
-    ConstantsBackend backend,
     Map<String, String> environmentDefines,
     ErrorReporter errorReporter,
     EvaluationMode evaluationMode,
@@ -70,7 +70,7 @@
   final TypeEnvironment typeEnvironment =
       new TypeEnvironment(coreTypes, hierarchy);
 
-  transformLibraries(component.libraries, backend, environmentDefines,
+  transformLibraries(component, component.libraries, target, environmentDefines,
       typeEnvironment, errorReporter, evaluationMode,
       enableTripleShift: enableTripleShift,
       enableConstFunctions: enableConstFunctions,
@@ -81,8 +81,9 @@
 }
 
 ConstantEvaluationData transformLibraries(
+    Component component,
     List<Library> libraries,
-    ConstantsBackend backend,
+    Target target,
     Map<String, String>? environmentDefines,
     TypeEnvironment typeEnvironment,
     ErrorReporter errorReporter,
@@ -103,13 +104,14 @@
   // ignore: unnecessary_null_comparison
   assert(enableConstructorTearOff != null);
   final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
-      backend,
+      target,
       environmentDefines,
       evaluateAnnotations,
       enableTripleShift,
       enableConstFunctions,
       enableConstructorTearOff,
       errorOnUnevaluatedConstant,
+      component,
       typeEnvironment,
       errorReporter,
       evaluationMode);
@@ -124,7 +126,8 @@
 
 void transformProcedure(
     Procedure procedure,
-    ConstantsBackend backend,
+    Target target,
+    Component component,
     Map<String, String>? environmentDefines,
     TypeEnvironment typeEnvironment,
     ErrorReporter errorReporter,
@@ -145,13 +148,14 @@
   // ignore: unnecessary_null_comparison
   assert(enableConstructorTearOff != null);
   final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
-      backend,
+      target,
       environmentDefines,
       evaluateAnnotations,
       enableTripleShift,
       enableConstFunctions,
       enableConstructorTearOff,
       errorOnUnevaluatedConstant,
+      component,
       typeEnvironment,
       errorReporter,
       evaluationMode);
@@ -282,7 +286,7 @@
       Reference reference = entry.key;
       Constant? value = visitConstant(entry.value);
       if (value != null) {
-        fieldValues ??= new Map<Reference, Constant>.from(node.fieldValues);
+        fieldValues ??= new Map<Reference, Constant>.of(node.fieldValues);
         fieldValues[reference] = value;
       }
     }
@@ -341,18 +345,25 @@
   final bool errorOnUnevaluatedConstant;
 
   ConstantsTransformer(
-      this.backend,
+      Target target,
       Map<String, String>? environmentDefines,
       this.evaluateAnnotations,
       this.enableTripleShift,
       this.enableConstFunctions,
       this.enableConstructorTearOff,
       this.errorOnUnevaluatedConstant,
+      Component component,
       this.typeEnvironment,
       ErrorReporter errorReporter,
       EvaluationMode evaluationMode)
-      : constantEvaluator = new ConstantEvaluator(
-            backend, environmentDefines, typeEnvironment, errorReporter,
+      : this.backend = target.constantsBackend,
+        constantEvaluator = new ConstantEvaluator(
+            target.dartLibrarySupport,
+            target.constantsBackend,
+            component,
+            environmentDefines,
+            typeEnvironment,
+            errorReporter,
             enableTripleShift: enableTripleShift,
             enableConstFunctions: enableConstFunctions,
             errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
@@ -871,11 +882,13 @@
 }
 
 class ConstantEvaluator implements ExpressionVisitor<Constant> {
+  final DartLibrarySupport dartLibrarySupport;
   final ConstantsBackend backend;
   final NumberSemantics numberSemantics;
   late ConstantIntFolder intFolder;
-  Map<String, String>? environmentDefines;
+  Map<String, String>? _environmentDefines;
   final bool errorOnUnevaluatedConstant;
+  final Component component;
   final CoreTypes coreTypes;
   final TypeEnvironment typeEnvironment;
   StaticTypeContext? _staticTypeContext;
@@ -914,8 +927,8 @@
 
   late ConstantWeakener _weakener;
 
-  ConstantEvaluator(this.backend, this.environmentDefines, this.typeEnvironment,
-      this.errorReporter,
+  ConstantEvaluator(this.dartLibrarySupport, this.backend, this.component,
+      this._environmentDefines, this.typeEnvironment, this.errorReporter,
       {this.enableTripleShift = false,
       this.enableConstFunctions = false,
       this.errorOnUnevaluatedConstant = false,
@@ -925,7 +938,7 @@
         canonicalizationCache = <Constant, Constant>{},
         nodeCache = <Node, Constant?>{},
         env = new EvaluationEnvironment() {
-    if (environmentDefines == null && !backend.supportsUnevaluatedConstants) {
+    if (_environmentDefines == null && !backend.supportsUnevaluatedConstants) {
       throw new ArgumentError(
           "No 'environmentDefines' passed to the constant evaluator but the "
           "ConstantsBackend does not support unevaluated constants.");
@@ -947,6 +960,43 @@
     _weakener = new ConstantWeakener(this);
   }
 
+  Map<String, String>? _supportedLibrariesCache;
+
+  Map<String, String> _computeSupportedLibraries() {
+    Map<String, String> map = {};
+    for (Library library in component.libraries) {
+      if (library.importUri.scheme == 'dart') {
+        map[library.importUri.path] =
+            DartLibrarySupport.getDartLibrarySupportValue(
+                library.importUri.path,
+                libraryExists: true,
+                isSynthetic: library.isSynthetic,
+                isUnsupported: library.isUnsupported,
+                dartLibrarySupport: dartLibrarySupport);
+      }
+    }
+    return map;
+  }
+
+  String? lookupEnvironment(String key) {
+    if (DartLibrarySupport.isDartLibraryQualifier(key)) {
+      String libraryName = DartLibrarySupport.getDartLibraryName(key);
+      String? value = (_supportedLibrariesCache ??=
+          _computeSupportedLibraries())[libraryName];
+      return value ?? "";
+    }
+    return _environmentDefines![key];
+  }
+
+  bool hasEnvironmentKey(String key) {
+    if (key.startsWith(DartLibrarySupport.dartLibraryPrefix)) {
+      return true;
+    }
+    return _environmentDefines!.containsKey(key);
+  }
+
+  bool get hasEnvironment => _environmentDefines != null;
+
   DartType convertType(DartType type) {
     switch (evaluationMode) {
       case EvaluationMode.strong:
@@ -1375,7 +1425,7 @@
     Constant constant = node.constant;
     Constant result = constant;
     if (constant is UnevaluatedConstant) {
-      if (environmentDefines != null) {
+      if (hasEnvironment) {
         result = _evaluateSubexpression(constant.expression);
         if (result is AbortConstant) return result;
       } else {
@@ -1999,14 +2049,12 @@
               statement.condition,
               templateConstEvalFailedAssertionWithMessage
                   .withArguments(message.value));
-        } else {
+        } else if (message is NullConstant) {
           return createEvaluationErrorConstant(
-              statement.message!,
-              templateConstEvalInvalidType.withArguments(
-                  message,
-                  typeEnvironment.coreTypes.stringLegacyRawType,
-                  message.getType(_staticTypeContext!),
-                  isNonNullableByDefault));
+              statement.condition, messageConstEvalFailedAssertion);
+        } else {
+          return createEvaluationErrorConstant(statement.message!,
+              messageConstEvalFailedAssertionWithNonStringMessage);
         }
       }
     } else {
@@ -2904,7 +2952,7 @@
 
   Constant _handleFromEnvironment(
       Procedure target, StringConstant name, Map<String, Constant> named) {
-    String? value = environmentDefines![name.value];
+    String? value = lookupEnvironment(name.value);
     Constant? defaultValue = named["defaultValue"];
     if (target.enclosingClass == coreTypes.boolClass) {
       Constant boolConstant;
@@ -2963,9 +3011,7 @@
   }
 
   Constant _handleHasEnvironment(StringConstant name) {
-    return environmentDefines!.containsKey(name.value)
-        ? trueConstant
-        : falseConstant;
+    return hasEnvironmentKey(name.value) ? trueConstant : falseConstant;
   }
 
   @override
@@ -3017,7 +3063,7 @@
             positionals.length == 1 &&
             (target.name.text == "fromEnvironment" ||
                 target.name.text == "hasEnvironment")) {
-          if (environmentDefines != null) {
+          if (hasEnvironment) {
             // Evaluate environment constant.
             Constant name = positionals.single;
             if (name is StringConstant) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 244a71d..0cbb45a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -4,8 +4,9 @@
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/type_algebra.dart';
-import '../builder/member_builder.dart';
+
 import '../source/source_library_builder.dart';
+import '../source/source_member_builder.dart';
 import 'kernel_helper.dart';
 
 const String _tearOffNamePrefix = '_#';
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 ce46969..ec5e04c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -4492,9 +4492,8 @@
       }
     } else {
       if (isSuper) {
-        Member? getter = _helper.lookupInstanceMember(name, isSuper: isSuper);
-        Member? setter = _helper.lookupInstanceMember(name,
-            isSuper: isSuper, isSetter: true);
+        Member? getter = _helper.lookupSuperMember(name);
+        Member? setter = _helper.lookupSuperMember(name, isSetter: true);
         return new SuperPropertyAccessGenerator(
             _helper,
             // TODO(ahe): This is not the 'super' token.
@@ -4576,7 +4575,14 @@
       // The check of the arguments is done later for super initializers if the
       // 'super-parameters' language feature is enabled. In that case the
       // additional parameters can be added at a later stage.
-      if (!(isSuper && _helper.libraryBuilder.enableSuperParametersInLibrary)) {
+      bool isPotentialSuperParametersReceiver =
+          isSuper && _helper.libraryBuilder.enableSuperParametersInLibrary;
+      // Additional arguments are added to the redirecting initializer of an
+      // enum constructor, so the check is performed later.
+      bool isEnumConstructorRedirectingInitializer =
+          constructor.enclosingClass.isEnum;
+      if (!isPotentialSuperParametersReceiver &&
+          !isEnumConstructorRedirectingInitializer) {
         message = _helper.checkArgumentsForFunction(
             constructor.function, arguments, offset, <TypeParameter>[]);
       }
@@ -4652,10 +4658,8 @@
           _helper,
           token,
           index,
-          _helper.lookupInstanceMember(indexGetName, isSuper: true)
-              as Procedure?,
-          _helper.lookupInstanceMember(indexSetName, isSuper: true)
-              as Procedure?);
+          _helper.lookupSuperMember(indexGetName) as Procedure?,
+          _helper.lookupSuperMember(indexSetName) as Procedure?);
     } else {
       return new ThisIndexedAccessGenerator(_helper, token, index,
           thisOffset: fileOffset, isNullAware: isNullAware);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 42258ae..4805dac 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -55,7 +55,7 @@
 
   Expression toValue(Object? node);
 
-  Member? lookupInstanceMember(Name name, {bool isSetter, bool isSuper});
+  Member? lookupSuperMember(Name name, {bool isSetter});
 
   bool get enableExtensionTypesInLibrary;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 9ce125d..73decad 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -374,7 +374,7 @@
     for (int i = 0; i < statements.length; i++) {
       Statement statement = statements[i];
       if (statement is _VariablesDeclaration) {
-        copy ??= new List<Statement>.from(statements.getRange(0, i));
+        copy ??= new List<Statement>.of(statements.getRange(0, i));
         copy.addAll(statement.declarations);
       } else if (copy != null) {
         copy.add(statement);
@@ -592,7 +592,7 @@
   Statement wrapVariables(Statement statement) {
     if (statement is _VariablesDeclaration) {
       return new Block(
-          new List<Statement>.from(statement.declarations, growable: true))
+          new List<Statement>.of(statement.declarations, growable: true))
         ..fileOffset = statement.fileOffset;
     } else if (statement is VariableDeclaration) {
       return new Block(<Statement>[statement])
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
index a5e89b9..30bd373 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
@@ -48,9 +48,7 @@
     }
 
     List<Supertype> superclasses;
-
-    List<Supertype> interfaces;
-
+    List<Supertype> interfacesList;
     int maxInheritancePath;
 
     List<TypeBuilder>? directInterfaceBuilders;
@@ -62,7 +60,7 @@
     if (supernode == null) {
       // This should be Object.
       superclasses = new List<Supertype>.filled(0, dummySupertype);
-      interfaces = new List<Supertype>.filled(0, dummySupertype);
+      interfacesList = new List<Supertype>.filled(0, dummySupertype);
       maxInheritancePath = 0;
     } else {
       maxInheritancePath = supernode.maxInheritancePath + 1;
@@ -107,7 +105,7 @@
       }
 
       if (directInterfaceBuilders != null) {
-        interfaces = <Supertype>[];
+        Map<Class, Supertype> interfaces = {};
         // ignore: unnecessary_null_comparison
         if (superclassInterfaces != null) {
           for (int i = 0; i < superclassInterfaces.length; i++) {
@@ -145,16 +143,18 @@
             }
           }
         }
+        interfacesList = interfaces.values.toList();
         // ignore: unnecessary_null_comparison
       } else if (superclassInterfaces != null &&
           !classBuilder.library.isNonNullableByDefault &&
           supernode.classBuilder.library.isNonNullableByDefault) {
-        interfaces = <Supertype>[];
+        Map<Class, Supertype> interfaces = {};
         for (int i = 0; i < superclassInterfaces.length; i++) {
           addInterface(interfaces, superclasses, superclassInterfaces[i]);
         }
+        interfacesList = interfaces.values.toList();
       } else {
-        interfaces = superclassInterfaces;
+        interfacesList = superclassInterfaces;
       }
     }
 
@@ -162,30 +162,19 @@
       recordSupertype(superclass);
     }
     // ignore: unnecessary_null_comparison
-    if (interfaces != null) {
-      for (Supertype superinterface in interfaces) {
+    if (interfacesList != null) {
+      for (Supertype superinterface in interfacesList) {
         recordSupertype(superinterface);
       }
     }
 
-    /*ClassHierarchyMemberNode memberNode =
-    buildMemberNode(supernode, directInterfaceBuilders);*/
-
     return new ClassHierarchyNode(
-      classBuilder,
-      supernode,
-      directInterfaceBuilders,
-      /*classMemberMap,
-        classSetterMap,
-        interfaceMemberMap,
-        interfaceSetterMap,*/
-      superclasses,
-      interfaces,
-      maxInheritancePath,
-      /*hasNoSuchMethod,
-        dataForTesting,*/
-      /*memberNode*/
-    );
+        classBuilder,
+        supernode,
+        directInterfaceBuilders,
+        superclasses,
+        interfacesList,
+        maxInheritancePath);
   }
 
   Supertype recordSupertype(Supertype supertype) {
@@ -242,8 +231,8 @@
     return result ?? supertypes;
   }
 
-  void addInterface(List<Supertype> interfaces, List<Supertype> superclasses,
-      Supertype type) {
+  void addInterface(Map<Class, Supertype> interfaces,
+      List<Supertype> superclasses, Supertype type) {
     // ignore: unnecessary_null_comparison
     if (type == null) return null;
     if (!classBuilder.library.isNonNullableByDefault) {
@@ -273,31 +262,26 @@
       }
       return;
     } else {
-      for (int i = 0; i < interfaces.length; i++) {
-        // This is a quadratic algorithm, but normally, the number of
-        // interfaces is really small.
-        Supertype? interface = interfaces[i];
-        if (interface.classNode == type.classNode) {
-          // This is a potential conflict.
-          if (classBuilder.library.isNonNullableByDefault) {
-            interface = nnbdTopMergeSupertype(
-                hierarchy.coreTypes,
-                normSupertype(hierarchy.coreTypes, interface),
-                normSupertype(hierarchy.coreTypes, type));
-            if (interface == null) {
-              // This is a conflict.
-              // TODO(johnniwinther): Report errors here instead of through
-              // the computation of the [ClassHierarchy].
-              interface = interfaces[i];
-            } else {
-              interfaces[i] = interface;
-            }
+      Supertype? interface = interfaces[type.classNode];
+      if (interface != null) {
+        // This is a potential conflict.
+        if (classBuilder.library.isNonNullableByDefault) {
+          interface = nnbdTopMergeSupertype(
+              hierarchy.coreTypes,
+              normSupertype(hierarchy.coreTypes, interface),
+              normSupertype(hierarchy.coreTypes, type));
+          if (interface == null) {
+            // This is a conflict.
+            // TODO(johnniwinther): Report errors here instead of through
+            // the computation of the [ClassHierarchy].
+          } else {
+            interfaces[type.classNode] = interface;
           }
-          return;
         }
+        return;
       }
     }
-    interfaces.add(type);
+    interfaces[type.classNode] = type;
   }
 
   void inferMixinApplication() {
@@ -349,27 +333,6 @@
 
   final List<TypeBuilder>? directInterfaceBuilders;
 
-  /*/// All the members of this class including [classMembers] of its
-  /// superclasses. The members are sorted by [compareDeclarations].
-  final Map<Name, ClassMember> classMemberMap;
-
-  /// Similar to [classMembers] but for setters.
-  final Map<Name, ClassMember> classSetterMap;
-
-  /// All the interface members of this class including [interfaceMembers] of
-  /// its supertypes. The members are sorted by [compareDeclarations].
-  ///
-  /// In addition to the members of [classMembers] this also contains members
-  /// from interfaces.
-  ///
-  /// This may be null, in which case [classMembers] is the interface members.
-  final Map<Name, ClassMember>? interfaceMemberMap;
-
-  /// Similar to [interfaceMembers] but for setters.
-  ///
-  /// This may be null, in which case [classSetters] is the interface setters.
-  final Map<Name, ClassMember>? interfaceSetterMap;*/
-
   /// All superclasses of [classBuilder] excluding itself. The classes are
   /// sorted by depth from the root (Object) in ascending order.
   final List<Supertype> superclasses;
@@ -383,27 +346,13 @@
 
   int get depth => superclasses.length;
 
-  /*final bool hasNoSuchMethod;
-
-  final ClassHierarchyNodeDataForTesting? dataForTesting;*/
-
-  //final ClassHierarchyMemberNode memberNode;
-
   ClassHierarchyNode(
-    this.classBuilder,
-    this.supernode,
-    this.directInterfaceBuilders,
-    /*this.classMemberMap,
-      this.classSetterMap,
-      this.interfaceMemberMap,
-      this.interfaceSetterMap,*/
-    this.superclasses,
-    this.interfaces,
-    this.maxInheritancePath,
-    /*this.hasNoSuchMethod,
-      this.dataForTesting,*/
-    /*this.memberNode*/
-  );
+      this.classBuilder,
+      this.supernode,
+      this.directInterfaceBuilders,
+      this.superclasses,
+      this.interfaces,
+      this.maxInheritancePath);
 
   /// Returns a list of all supertypes of [classBuilder], including this node.
   List<ClassHierarchyNode> computeAllSuperNodes(
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
index f50343a..6a0c047 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
@@ -8,10 +8,10 @@
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchyMembers;
 
 import '../../builder/class_builder.dart';
-import '../../builder/field_builder.dart';
-import '../../builder/procedure_builder.dart';
 import '../../builder/type_builder.dart';
 import '../../source/source_class_builder.dart';
+import '../../source/source_field_builder.dart';
+import '../../source/source_procedure_builder.dart';
 import 'class_member.dart';
 import 'delayed.dart';
 import 'hierarchy_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
index b2fc124..f93f47e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
@@ -14,12 +14,10 @@
 import '../../../base/common.dart';
 import '../../builder/builder.dart';
 import '../../builder/class_builder.dart';
-import '../../builder/field_builder.dart';
 import '../../builder/formal_parameter_builder.dart';
 import '../../builder/library_builder.dart';
 import '../../builder/member_builder.dart';
 import '../../builder/named_type_builder.dart';
-import '../../builder/procedure_builder.dart';
 import '../../builder/type_alias_builder.dart';
 import '../../builder/type_builder.dart';
 import '../../builder/type_declaration_builder.dart';
@@ -44,6 +42,8 @@
 import '../../names.dart' show noSuchMethodName;
 import '../../scope.dart' show Scope;
 import '../../source/source_class_builder.dart';
+import '../../source/source_field_builder.dart';
+import '../../source/source_procedure_builder.dart';
 import '../combined_member_signature.dart';
 import '../member_covariance.dart';
 import 'class_member.dart';
@@ -2352,7 +2352,7 @@
       }
     }
     if (contextMap.isEmpty) return;
-    List<String> names = new List<String>.from(contextMap.keys)..sort();
+    List<String> names = new List<String>.of(contextMap.keys)..sort();
     List<LocatedMessage> context = <LocatedMessage>[];
     for (int i = 0; i < names.length; i++) {
       context.add(contextMap[names[i]]!);
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index c4f1db7..792c92f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -5,17 +5,15 @@
 library fasta.implicit_type;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
 import 'package:kernel/ast.dart';
-
 import 'package:kernel/src/assumptions.dart';
 import 'package:kernel/src/legacy_erasure.dart';
 import 'package:kernel/src/printer.dart';
 
-import '../builder/field_builder.dart';
 import '../constant_context.dart';
 import '../fasta_codes.dart';
 import '../problems.dart' show unsupported;
+import '../source/source_field_builder.dart';
 import '../type_inference/type_inferrer.dart';
 import '../type_inference/type_schema.dart';
 import 'body_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 87a0d06..2e8000f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -6655,7 +6655,7 @@
             isLowered: true)
           ..fileOffset = fileOffset;
         VariableDeclaration setterParameter =
-            new VariableDeclaration(null, type: node.type)
+            new VariableDeclaration("${node.name}#param", type: node.type)
               ..fileOffset = fileOffset;
         FunctionDeclaration setter = new FunctionDeclaration(
                 setVariable,
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 7239b43..9a8570c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -828,8 +828,19 @@
   }
 
   @override
-  String toStringInternal() {
-    return "";
+  void toTextInternal(AstPrinter printer) {
+    if (isConst) {
+      printer.write('const ');
+    } else {
+      printer.write('new ');
+    }
+    printer.writeTypedefName(typeAliasBuilder.typedef.reference);
+    printer.writeTypeArguments(arguments.types);
+    if (target.name.text.isNotEmpty) {
+      printer.write('.');
+      printer.write(target.name.text);
+    }
+    printer.writeArguments(arguments, includeTypeArguments: false);
   }
 }
 
@@ -857,8 +868,19 @@
   }
 
   @override
-  String toStringInternal() {
-    return "";
+  void toTextInternal(AstPrinter printer) {
+    if (isConst) {
+      printer.write('const ');
+    } else {
+      printer.write('new ');
+    }
+    printer.writeTypedefName(typeAliasBuilder.typedef.reference);
+    printer.writeTypeArguments(arguments.types);
+    if (target.name.text.isNotEmpty) {
+      printer.write('.');
+      printer.write(target.name.text);
+    }
+    printer.writeArguments(arguments, includeTypeArguments: false);
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
index bf49dae..635fec7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -35,9 +35,52 @@
   /// named parameters.
   final bool identicalSignatures;
 
+  final List<int>? _positionalSuperParameters;
+
+  final List<String>? _namedSuperParameters;
+
+  bool isOutlineNode;
+
   SynthesizedFunctionNode(
       this._typeSubstitution, this._original, this._synthesized,
-      {this.identicalSignatures: true});
+      {this.identicalSignatures: true,
+      List<int>? positionalSuperParameters: null,
+      List<String>? namedSuperParameters: null,
+      this.isOutlineNode: false})
+      : _positionalSuperParameters = positionalSuperParameters,
+        _namedSuperParameters = namedSuperParameters,
+        // Check that [positionalSuperParameters] and [namedSuperParameters] are
+        // provided or omitted together.
+        assert((positionalSuperParameters == null) ==
+            (namedSuperParameters == null)),
+        assert(positionalSuperParameters == null ||
+            () {
+              // Check that [positionalSuperParameters] is sorted if it's
+              // provided.
+              for (int i = 1; i < positionalSuperParameters.length; i++) {
+                if (positionalSuperParameters[i] <
+                    positionalSuperParameters[i - 1]) {
+                  return false;
+                }
+              }
+              return true;
+            }()),
+        assert(namedSuperParameters == null ||
+            () {
+              // Check that [namedSuperParameters] are the subset of and in the
+              // same order as the named parameters of [_synthesized].
+              int superParameterIndex = 0;
+              for (int namedParameterIndex = 0;
+                  namedParameterIndex < _synthesized.namedParameters.length &&
+                      superParameterIndex < namedSuperParameters.length;
+                  namedParameterIndex++) {
+                if (_synthesized.namedParameters[namedParameterIndex].name ==
+                    namedSuperParameters[superParameterIndex]) {
+                  ++superParameterIndex;
+                }
+              }
+              return superParameterIndex == namedSuperParameters.length;
+            }());
 
   void cloneDefaultValues() {
     // TODO(ahe): It is unclear if it is legal to use type variables in
@@ -63,17 +106,49 @@
     // unrelated.
 
     if (identicalSignatures) {
-      assert(_synthesized.positionalParameters.length ==
-          _original.positionalParameters.length);
-      for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
-        cloneInitializer(_original.positionalParameters[i],
-            _synthesized.positionalParameters[i]);
+      assert(_positionalSuperParameters != null ||
+          _synthesized.positionalParameters.length ==
+              _original.positionalParameters.length);
+      List<int>? positionalSuperParameters = _positionalSuperParameters;
+      for (int i = 0; i < _original.positionalParameters.length; i++) {
+        if (positionalSuperParameters == null) {
+          cloneInitializer(_original.positionalParameters[i],
+              _synthesized.positionalParameters[i]);
+        } else if (i < positionalSuperParameters.length) {
+          cloneInitializer(_original.positionalParameters[i],
+              _synthesized.positionalParameters[positionalSuperParameters[i]]);
+        }
       }
-      assert(_synthesized.namedParameters.length ==
-          _original.namedParameters.length);
+
+      assert(_namedSuperParameters != null ||
+          _synthesized.namedParameters.length ==
+              _original.namedParameters.length);
+      List<String>? namedSuperParameters = _namedSuperParameters;
+      int superParameterNameIndex = 0;
+      Map<String, int> originalNamedParameterIndices = {};
+      for (int i = 0; i < _original.namedParameters.length; i++) {
+        originalNamedParameterIndices[_original.namedParameters[i].name!] = i;
+      }
       for (int i = 0; i < _synthesized.namedParameters.length; i++) {
-        cloneInitializer(
-            _original.namedParameters[i], _synthesized.namedParameters[i]);
+        if (namedSuperParameters == null) {
+          cloneInitializer(
+              _original.namedParameters[i], _synthesized.namedParameters[i]);
+        } else if (superParameterNameIndex < namedSuperParameters.length &&
+            namedSuperParameters[superParameterNameIndex] ==
+                _synthesized.namedParameters[i].name) {
+          String superParameterName =
+              namedSuperParameters[superParameterNameIndex];
+          int? originalNamedParameterIndex =
+              originalNamedParameterIndices[superParameterName];
+          if (originalNamedParameterIndex != null) {
+            cloneInitializer(
+                _original.namedParameters[originalNamedParameterIndex],
+                _synthesized.namedParameters[i]);
+          } else {
+            // TODO(cstefantsova): Handle the erroneous case of missing names.
+          }
+          superParameterNameIndex++;
+        }
       }
     } else {
       for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
@@ -110,6 +185,12 @@
       }
     }
   }
+
+  @override
+  String toString() {
+    return "SynthesizedFunctionNode(original=${_original.parent}, "
+        "synthesized=${_synthesized.parent})";
+  }
 }
 
 class TypeDependency {
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 27f8d35..9bad9b3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -40,7 +40,6 @@
 import '../builder/void_type_declaration_builder.dart';
 import '../compiler_context.dart' show CompilerContext;
 import '../crash.dart' show withCrashReporting;
-import '../dill/dill_member_builder.dart' show DillMemberBuilder;
 import '../dill/dill_target.dart' show DillTarget;
 import '../kernel/constructor_tearoff_lowering.dart';
 import '../loader.dart' show Loader;
@@ -59,13 +58,14 @@
         templateFieldNonNullableWithoutInitializerError,
         templateFinalFieldNotInitialized,
         templateFinalFieldNotInitializedByConstructor,
-        templateInferredPackageUri,
         templateMissingImplementationCause,
         templateSuperclassHasNoDefaultConstructor;
 import '../problems.dart' show unhandled;
 import '../scope.dart' show AmbiguousBuilder;
 import '../source/name_scheme.dart';
 import '../source/source_class_builder.dart' show SourceClassBuilder;
+import '../source/source_constructor_builder.dart';
+import '../source/source_field_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 import '../source/source_loader.dart' show SourceLoader;
 import '../target_implementation.dart' show TargetImplementation;
@@ -81,6 +81,7 @@
         ConstantEvaluationData;
 import 'kernel_constants.dart' show KernelConstantErrorReporter;
 import 'kernel_helper.dart';
+import 'macro.dart';
 import 'verifier.dart' show verifyComponent, verifyGetStaticType;
 
 class KernelTarget extends TargetImplementation {
@@ -102,7 +103,7 @@
   // TODO(johnniwinther): Why isn't this using a FixedTypeBuilder?
   final TypeBuilder dynamicType = new NamedTypeBuilder(
       "dynamic",
-      const NullabilityBuilder.nullable(),
+      const NullabilityBuilder.inherent(),
       /* arguments = */ null,
       /* fileUri = */ null,
       /* charOffset = */ null,
@@ -121,7 +122,7 @@
   //  have NullType?
   final TypeBuilder nullType = new NamedTypeBuilder(
       "Null",
-      const NullabilityBuilder.nullable(),
+      const NullabilityBuilder.inherent(),
       /* arguments = */ null,
       /* fileUri = */ null,
       /* charOffset = */ null,
@@ -136,6 +137,22 @@
       /* charOffset = */ null,
       instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
 
+  final NamedTypeBuilder enumType = new NamedTypeBuilder(
+      "Enum",
+      const NullabilityBuilder.omitted(),
+      /* arguments = */ null,
+      /* fileUri = */ null,
+      /* charOffset = */ null,
+      instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+
+  final NamedTypeBuilder underscoreEnumType = new NamedTypeBuilder(
+      "_Enum",
+      const NullabilityBuilder.omitted(),
+      /* arguments = */ null,
+      /* fileUri = */ null,
+      /* charOffset = */ null,
+      instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+
   final bool excludeSource = !CompilerContext.current.options.embedSourceText;
 
   final Map<String, String>? environmentDefines =
@@ -275,6 +292,7 @@
   }
 
   Version? _currentSdkVersion;
+
   Version get currentSdkVersion {
     if (_currentSdkVersion == null) {
       _parseCurrentSdkVersion();
@@ -344,13 +362,6 @@
             Uri reversed = Uri.parse(
                 "package:$packageName/${asString.substring(prefix.length)}");
             if (entryPoint == uriTranslator.translate(reversed)) {
-              if (issueProblem) {
-                loader.addProblem(
-                    templateInferredPackageUri.withArguments(reversed),
-                    -1,
-                    1,
-                    entryPoint);
-              }
               entryPoint = reversed;
               break;
             }
@@ -380,21 +391,26 @@
     builder.mixedInTypeBuilder = null;
   }
 
-  Future<Component?> buildOutlines({CanonicalName? nameRoot}) async {
-    if (loader.first == null) return null;
-    return withCrashReporting<Component?>(() async {
+  Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
+    if (loader.first == null) return new BuildResult();
+    return withCrashReporting<BuildResult>(() async {
       await loader.buildOutlines();
       loader.coreLibrary.becomeCoreLibrary();
       loader.resolveParts();
+      loader.computeMacroDeclarations();
       loader.computeLibraryScopes();
+      MacroApplications? macroApplications =
+          await loader.computeMacroApplications();
       setupTopAndBottomTypes();
       loader.resolveTypes();
       loader.computeVariances();
       loader.computeDefaultTypes(
           dynamicType, nullType, bottomType, objectClassBuilder);
-      List<SourceClassBuilder> sourceClassBuilders =
+      if (macroApplications != null) {
+        await macroApplications.applyTypeMacros();
+      }
+      List<SourceClassBuilder>? sourceClassBuilders =
           loader.checkSemantics(objectClassBuilder);
-      loader.computeMacroDeclarations(sourceClassBuilders);
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
       loader.createTypeInferenceEngine();
       loader.buildComponent();
@@ -402,27 +418,37 @@
       installSyntheticConstructors(sourceClassBuilders);
       loader.resolveConstructors();
       component =
-          link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
+          link(new List<Library>.of(loader.libraries), nameRoot: nameRoot);
       computeCoreTypes();
       loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
+      loader.checkSupertypes(sourceClassBuilders, enumClass);
+      if (macroApplications != null) {
+        await macroApplications.applyDeclarationMacros();
+      }
+      loader.buildClassHierarchyMembers(sourceClassBuilders);
       loader.computeHierarchy();
       loader.computeShowHideElements();
       loader.installTypedefTearOffs();
       loader.performTopLevelInference(sourceClassBuilders);
-      loader.checkSupertypes(sourceClassBuilders);
       loader.checkOverrides(sourceClassBuilders);
       loader.checkAbstractMembers(sourceClassBuilders);
       loader.addNoSuchMethodForwarders(sourceClassBuilders);
       loader.checkMixins(sourceClassBuilders);
       loader.buildOutlineExpressions(
-          loader.coreTypes, synthesizedFunctionNodes);
-      loader.computeMacroApplications();
+          loader.hierarchy, synthesizedFunctionNodes);
       loader.checkTypes();
       loader.checkRedirectingFactories(sourceClassBuilders);
+      finishSynthesizedParameters(forOutline: true);
       loader.checkMainMethods();
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
-      return component;
+      // For whatever reason sourceClassBuilders is kept alive for some amount
+      // of time, meaning that all source library builders will be kept alive
+      // (for whatever amount of time) even though we convert them to dill
+      // library builders. To avoid it we null it out here.
+      sourceClassBuilders = null;
+      return new BuildResult(
+          component: component, macroApplications: macroApplications);
     }, () => loader.currentUriForCrashReporting);
   }
 
@@ -434,15 +460,23 @@
   ///
   /// If [verify], run the default kernel verification on the resulting
   /// component.
-  Future<Component?> buildComponent({bool verify: false}) async {
-    if (loader.first == null) return null;
-    return withCrashReporting<Component?>(() async {
+  Future<BuildResult> buildComponent(
+      {required MacroApplications? macroApplications,
+      bool verify: false}) async {
+    if (loader.first == null) {
+      return new BuildResult(macroApplications: macroApplications);
+    }
+    return withCrashReporting<BuildResult>(() async {
       ticker.logMs("Building component");
       await loader.buildBodies();
       finishSynthesizedParameters();
       loader.finishDeferredLoadTearoffs();
       loader.finishNoSuchMethodForwarders();
-      List<SourceClassBuilder> sourceClasses = loader.collectSourceClasses();
+      List<SourceClassBuilder>? sourceClasses = loader.collectSourceClasses();
+      if (macroApplications != null) {
+        await macroApplications.applyDefinitionMacros(
+            loader.coreTypes, loader.hierarchy);
+      }
       loader.finishNativeMethods();
       loader.finishPatchMethods();
       finishAllConstructors(sourceClasses);
@@ -450,7 +484,14 @@
 
       if (verify) this.verify();
       installAllComponentProblems(loader.allComponentProblems);
-      return component;
+
+      // For whatever reason sourceClasses is kept alive for some amount
+      // of time, meaning that all source library builders will be kept alive
+      // (for whatever amount of time) even though we convert them to dill
+      // library builders. To avoid it we null it out here.
+      sourceClasses = null;
+      return new BuildResult(
+          component: component, macroApplications: macroApplications);
     }, () => loader.currentUriForCrashReporting);
   }
 
@@ -514,11 +555,7 @@
         declaration = problem.getFirstDeclaration();
       }
       if (declaration is ProcedureBuilder) {
-        mainReference = declaration.actualProcedure.reference;
-      } else if (declaration is DillMemberBuilder) {
-        if (declaration.member is Procedure) {
-          mainReference = declaration.member.reference;
-        }
+        mainReference = declaration.procedure.reference;
       }
     }
     component.setMainMethodAndMode(mainReference, true, compiledMode);
@@ -636,6 +673,10 @@
 
   Class get objectClass => objectClassBuilder.cls;
 
+  ClassBuilder get enumClassBuilder => enumType.declaration as ClassBuilder;
+
+  Class get enumClass => enumClassBuilder.cls;
+
   /// If [builder] doesn't have a constructors, install the defaults.
   void installDefaultConstructor(SourceClassBuilder builder) {
     assert(!builder.isMixinApplication);
@@ -778,10 +819,10 @@
     }
   }
 
-  SyntheticConstructorBuilder _makeMixinApplicationConstructor(
+  SyntheticSourceConstructorBuilder _makeMixinApplicationConstructor(
       SourceClassBuilder classBuilder,
       Class mixin,
-      MemberBuilderImpl superConstructorBuilder,
+      MemberBuilder superConstructorBuilder,
       Map<TypeParameter, DartType> substitutionMap,
       Reference? constructorReference,
       Reference? tearOffReference) {
@@ -882,26 +923,32 @@
       buildConstructorTearOffProcedure(constructorTearOff, constructor,
           classBuilder.cls, classBuilder.library);
     }
-    return new SyntheticConstructorBuilder(
+    return new SyntheticSourceConstructorBuilder(
         classBuilder, constructor, constructorTearOff,
-        // If the constructor is constant, the default values must be part of
-        // the outline expressions. We pass on the original constructor and
-        // cloned function nodes to ensure that the default values are computed
-        // and cloned for the outline.
-        origin: isConst ? superConstructorBuilder : null,
-        synthesizedFunctionNode: isConst ? synthesizedFunctionNode : null);
+        // We pass on the original constructor and the cloned function nodes to
+        // ensure that the default values are computed and cloned for the
+        // outline. It is needed to make the default values a part of the
+        // outline for const constructors, and additionally it is required for
+        // a potential subclass using super initializing parameters that will
+        // required the cloning of the default values.
+        origin: superConstructorBuilder,
+        synthesizedFunctionNode: synthesizedFunctionNode);
   }
 
-  void finishSynthesizedParameters() {
+  void finishSynthesizedParameters({bool forOutline = false}) {
     for (SynthesizedFunctionNode synthesizedFunctionNode
         in synthesizedFunctionNodes) {
-      synthesizedFunctionNode.cloneDefaultValues();
+      if (!forOutline || synthesizedFunctionNode.isOutlineNode) {
+        synthesizedFunctionNode.cloneDefaultValues();
+      }
     }
-    synthesizedFunctionNodes.clear();
+    if (!forOutline) {
+      synthesizedFunctionNodes.clear();
+    }
     ticker.logMs("Cloned default values of formals");
   }
 
-  SyntheticConstructorBuilder _makeDefaultConstructor(
+  SyntheticSourceConstructorBuilder _makeDefaultConstructor(
       SourceClassBuilder classBuilder,
       Reference? constructorReference,
       Reference? tearOffReference) {
@@ -931,7 +978,7 @@
       buildConstructorTearOffProcedure(constructorTearOff, constructor,
           classBuilder.cls, classBuilder.library);
     }
-    return new SyntheticConstructorBuilder(
+    return new SyntheticSourceConstructorBuilder(
         classBuilder, constructor, constructorTearOff);
   }
 
@@ -958,6 +1005,10 @@
     nullType.bind(nullClassBuilder..isNullClass = true);
     bottomType.bind(loader.coreLibrary
         .lookupLocalMember("Never", required: true) as TypeDeclarationBuilder);
+    enumType.bind(loader.coreLibrary.lookupLocalMember("Enum", required: true)
+        as TypeDeclarationBuilder);
+    underscoreEnumType.bind(loader.coreLibrary
+        .lookupLocalMember("_Enum", required: true) as TypeDeclarationBuilder);
   }
 
   void computeCoreTypes() {
@@ -1016,11 +1067,12 @@
 
     /// Quotes below are from [Dart Programming Language Specification, 4th
     /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf):
-    List<FieldBuilder> uninitializedFields = <FieldBuilder>[];
-    List<FieldBuilder> nonFinalFields = <FieldBuilder>[];
-    List<FieldBuilder> lateFinalFields = <FieldBuilder>[];
+    List<SourceFieldBuilder> uninitializedFields = [];
+    List<SourceFieldBuilder> nonFinalFields = [];
+    List<SourceFieldBuilder> lateFinalFields = [];
 
-    builder.forEachDeclaredField((String name, FieldBuilder fieldBuilder) {
+    builder
+        .forEachDeclaredField((String name, SourceFieldBuilder fieldBuilder) {
       if (fieldBuilder.isAbstract || fieldBuilder.isExternal) {
         // Skip abstract and external fields. These are abstract/external
         // getters/setters and have no initialization.
@@ -1039,11 +1091,11 @@
         // declared towards the beginning of the file) come last in the list.
         // To report errors on the first definition of a field, we need to
         // iterate until that last element.
-        FieldBuilder earliest = fieldBuilder;
+        SourceFieldBuilder earliest = fieldBuilder;
         Builder current = fieldBuilder;
         while (current.next != null) {
           current = current.next!;
-          if (current is FieldBuilder && !fieldBuilder.hasInitializer) {
+          if (current is SourceFieldBuilder && !fieldBuilder.hasInitializer) {
             earliest = current;
           }
         }
@@ -1127,7 +1179,7 @@
               constructor.fileOffset, noLength,
               context: nonFinalFields
                   .map((field) => messageConstConstructorNonFinalFieldCause
-                      .withLocation(field.fileUri!, field.charOffset, noLength))
+                      .withLocation(field.fileUri, field.charOffset, noLength))
                   .toList());
           nonFinalFields.clear();
         }
@@ -1148,22 +1200,22 @@
       }
     }
 
-    Map<ConstructorBuilder, Set<FieldBuilder>> constructorInitializedFields =
-        new Map<ConstructorBuilder, Set<FieldBuilder>>.identity();
-    Set<FieldBuilder>? initializedFields = null;
+    Map<ConstructorBuilder, Set<SourceFieldBuilder>>
+        constructorInitializedFields = new Map.identity();
+    Set<SourceFieldBuilder>? initializedFields = null;
 
     builder.forEachDeclaredConstructor(
-        (String name, ConstructorBuilder constructorBuilder) {
+        (String name, DeclaredSourceConstructorBuilder constructorBuilder) {
       if (constructorBuilder.isExternal) return;
       // In case of duplicating constructors the earliest ones (those that
       // declared towards the beginning of the file) come last in the list.
       // To report errors on the first definition of a constructor, we need to
       // iterate until that last element.
-      ConstructorBuilder earliest = constructorBuilder;
+      DeclaredSourceConstructorBuilder earliest = constructorBuilder;
       Builder earliestBuilder = constructorBuilder;
       while (earliestBuilder.next != null) {
         earliestBuilder = earliestBuilder.next!;
-        if (earliestBuilder is ConstructorBuilder) {
+        if (earliestBuilder is DeclaredSourceConstructorBuilder) {
           earliest = earliestBuilder;
         }
       }
@@ -1175,15 +1227,17 @@
         }
       }
       if (!isRedirecting) {
-        Set<FieldBuilder> fields = earliest.takeInitializedFields() ?? const {};
+        Set<SourceFieldBuilder> fields =
+            earliest.takeInitializedFields() ?? const {};
         constructorInitializedFields[earliest] = fields;
-        (initializedFields ??= new Set<FieldBuilder>.identity()).addAll(fields);
+        (initializedFields ??= new Set<SourceFieldBuilder>.identity())
+            .addAll(fields);
       }
     });
 
     // Run through all fields that aren't initialized by any constructor, and
     // set their initializer to `null`.
-    for (FieldBuilder fieldBuilder in uninitializedFields) {
+    for (SourceFieldBuilder fieldBuilder in uninitializedFields) {
       if (initializedFields == null ||
           !initializedFields!.contains(fieldBuilder)) {
         bool uninitializedFinalOrNonNullableFieldIsError =
@@ -1193,7 +1247,7 @@
           if (fieldBuilder.isFinal &&
               uninitializedFinalOrNonNullableFieldIsError) {
             String uri = '${fieldBuilder.library.importUri}';
-            String file = fieldBuilder.fileUri!.pathSegments.last;
+            String file = fieldBuilder.fileUri.pathSegments.last;
             if (uri == 'dart:html' ||
                 uri == 'dart:svg' ||
                 uri == 'dart:_native_typed_data' ||
@@ -1231,7 +1285,7 @@
     // make sure that all other constructors also initialize them.
     constructorInitializedFields.forEach((ConstructorBuilder constructorBuilder,
         Set<FieldBuilder> fieldBuilders) {
-      for (FieldBuilder fieldBuilder
+      for (SourceFieldBuilder fieldBuilder
           in initializedFields!.difference(fieldBuilders)) {
         if (!fieldBuilder.hasInitializer && !fieldBuilder.isLate) {
           FieldInitializer initializer =
@@ -1249,7 +1303,7 @@
                 context: [
                   templateMissingImplementationCause
                       .withArguments(fieldBuilder.name)
-                      .withLocation(fieldBuilder.fileUri!,
+                      .withLocation(fieldBuilder.fileUri,
                           fieldBuilder.charOffset, fieldBuilder.name.length)
                 ]);
           } else if (fieldBuilder.field.type is! InvalidType &&
@@ -1267,7 +1321,7 @@
                   context: [
                     templateMissingImplementationCause
                         .withArguments(fieldBuilder.name)
-                        .withLocation(fieldBuilder.fileUri!,
+                        .withLocation(fieldBuilder.fileUri,
                             fieldBuilder.charOffset, fieldBuilder.name.length)
                   ]);
             }
@@ -1289,14 +1343,14 @@
     // it's so.
     assert(() {
       Set<String> patchFieldNames = {};
-      builder.forEachDeclaredField((String name, FieldBuilder fieldBuilder) {
+      builder
+          .forEachDeclaredField((String name, SourceFieldBuilder fieldBuilder) {
         patchFieldNames.add(NameScheme.createFieldName(
           FieldNameType.Field,
           name,
           isInstanceMember: fieldBuilder.isClassInstanceMember,
           className: builder.name,
-          isSynthesized:
-              fieldBuilder is SourceFieldBuilder && fieldBuilder.isLateLowered,
+          isSynthesized: fieldBuilder.isLateLowered,
         ));
       });
       builder.forEach((String name, Builder builder) {
@@ -1336,8 +1390,9 @@
 
     constants.ConstantEvaluationData constantEvaluationData =
         constants.transformLibraries(
+            component!,
             loader.libraries,
-            backendTarget.constantsBackend,
+            backendTarget,
             environmentDefines,
             environment,
             new KernelConstantErrorReporter(loader),
@@ -1393,7 +1448,8 @@
 
     constants.transformProcedure(
       procedure,
-      backendTarget.constantsBackend,
+      backendTarget,
+      component!,
       environmentDefines,
       environment,
       new KernelConstantErrorReporter(loader),
@@ -1528,3 +1584,10 @@
     loader.addProblem(message, charOffset, noLength, fileUri, context: context);
   }
 }
+
+class BuildResult {
+  final Component? component;
+  final MacroApplications? macroApplications;
+
+  BuildResult({this.component, this.macroApplications});
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index afa9dca..a637145 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -2,37 +2,535 @@
 // for details. All 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';
+// TODO: Only import `Identifier` under a prefix if/when the presubmit check
+// allows duplicate imports if they have different prefixes.
+import 'package:_fe_analyzer_shared/src/macros/api.dart' as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+import 'package:kernel/ast.dart' show DartType, DynamicType;
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../builder/class_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/type_builder.dart';
+import '../identifiers.dart';
+import '../source/source_class_builder.dart';
+import '../source/source_library_builder.dart';
+import '../source/source_procedure_builder.dart';
 
 bool enableMacros = false;
 
-final Uri macroLibraryUri = Uri.parse('package:macro_builder/src/macro.dart');
+final Uri macroLibraryUri =
+    Uri.parse('package:_fe_analyzer_shared/src/macros/api.dart');
 const String macroClassName = 'Macro';
+final IdentifierImpl dynamicIdentifier =
+    new IdentifierImpl(id: RemoteInstance.uniqueId, name: 'dynamic');
 
 class MacroDeclarationData {
   bool macrosAreAvailable = false;
   Map<Uri, List<String>> macroDeclarations = {};
   List<List<Uri>>? compilationSequence;
+  List<Map<Uri, Map<String, List<String>>>> neededPrecompilations = [];
 }
 
-class MacroApplicationData {
-  Map<Library, LibraryMacroApplicationData> libraryData = {};
+class MacroClass {
+  final Uri importUri;
+  final String className;
+
+  const MacroClass(this.importUri, this.className);
+
+  @override
+  int get hashCode => importUri.hashCode * 13 + className.hashCode * 17;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is MacroClass &&
+        importUri == other.importUri &&
+        className == other.className;
+  }
 }
 
-class MacroApplications {
-  final List<Class> macros;
+class MacroApplication {
+  final ClassBuilder classBuilder;
+  final String constructorName;
 
-  MacroApplications(this.macros);
+  // TODO(johnniwinther): Add support for arguments.
+
+  MacroApplication(this.classBuilder, this.constructorName);
+
+  late MacroInstanceIdentifier instanceIdentifier;
+}
+
+class MacroApplicationDataForTesting {
+  Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
+  Map<MemberBuilder, List<MacroExecutionResult>> memberTypesResults = {};
+  Map<MemberBuilder, List<MacroExecutionResult>> memberDeclarationsResults = {};
+  Map<MemberBuilder, List<MacroExecutionResult>> memberDefinitionsResults = {};
 }
 
 class LibraryMacroApplicationData {
-  MacroApplications? libraryApplications;
-  Map<Class, ClassMacroApplicationData> classData = {};
-  Map<Typedef, MacroApplications> typedefApplications = {};
-  Map<Member, MacroApplications> memberApplications = {};
+  Map<SourceClassBuilder, ClassMacroApplicationData> classData = {};
+  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
 }
 
 class ClassMacroApplicationData {
-  MacroApplications? classApplications;
-  Map<Member, MacroApplications> memberApplications = {};
+  List<MacroApplication>? classApplications;
+  Map<MemberBuilder, List<MacroApplication>> memberApplications = {};
+}
+
+class MacroApplications {
+  final MacroExecutor _macroExecutor;
+  final Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData;
+  final MacroApplicationDataForTesting? dataForTesting;
+
+  MacroApplications(
+      this._macroExecutor, this.libraryData, this.dataForTesting) {
+    dataForTesting?.libraryData.addAll(libraryData);
+  }
+
+  static Future<MacroApplications> loadMacroIds(
+      MacroExecutor macroExecutor,
+      Map<MacroClass, Uri> precompiledMacroUris,
+      Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData,
+      MacroApplicationDataForTesting? dataForTesting) async {
+    Map<ClassBuilder, MacroClassIdentifier> classIdCache = {};
+
+    Map<MacroApplication, MacroInstanceIdentifier> instanceIdCache = {};
+
+    Future<void> ensureMacroClassIds(
+        List<MacroApplication>? applications) async {
+      if (applications != null) {
+        for (MacroApplication application in applications) {
+          MacroClass macroClass = new MacroClass(
+              application.classBuilder.library.importUri,
+              application.classBuilder.name);
+          Uri? precompiledMacroUri = precompiledMacroUris[macroClass];
+          MacroClassIdentifier macroClassIdentifier =
+              classIdCache[application.classBuilder] ??= await macroExecutor
+                  .loadMacro(macroClass.importUri, macroClass.className,
+                      precompiledKernelUri: precompiledMacroUri);
+          application.instanceIdentifier = instanceIdCache[application] =
+              await macroExecutor.instantiateMacro(
+                  macroClassIdentifier,
+                  application.constructorName,
+                  // TODO(johnniwinther): Support macro arguments.
+                  new Arguments([], {}));
+        }
+      }
+    }
+
+    for (LibraryMacroApplicationData libraryData in libraryData.values) {
+      for (ClassMacroApplicationData classData
+          in libraryData.classData.values) {
+        await ensureMacroClassIds(classData.classApplications);
+        for (List<MacroApplication> applications
+            in classData.memberApplications.values) {
+          await ensureMacroClassIds(applications);
+        }
+      }
+      for (List<MacroApplication> applications
+          in libraryData.memberApplications.values) {
+        await ensureMacroClassIds(applications);
+      }
+    }
+    return new MacroApplications(macroExecutor, libraryData, dataForTesting);
+  }
+
+  Map<MemberBuilder, macro.Declaration?> _memberDeclarations = {};
+
+  // TODO(johnniwinther): Support all members.
+  macro.Declaration? _getMemberDeclaration(MemberBuilder memberBuilder) {
+    return _memberDeclarations[memberBuilder] ??=
+        _createMemberDeclaration(memberBuilder);
+  }
+
+  macro.Declaration? _createMemberDeclaration(MemberBuilder memberBuilder) {
+    if (memberBuilder is SourceProcedureBuilder) {
+      return createTopLevelFunctionDeclaration(memberBuilder);
+    } else {
+      // TODO(johnniwinther): Throw when all members are supported.
+      //throw new UnimplementedError('Unsupported member ${memberBuilder}');
+      return null;
+    }
+  }
+
+  Future<List<MacroExecutionResult>> _applyTypeMacros(
+      macro.Declaration declaration,
+      List<MacroApplication> macroApplications) async {
+    List<MacroExecutionResult> results = [];
+    for (MacroApplication macroApplication in macroApplications) {
+      if (macroApplication.instanceIdentifier.shouldExecute(
+          // TODO(johnniwinther): Get the declaration kind from [declaration].
+          DeclarationKind.function,
+          Phase.types)) {
+        MacroExecutionResult result = await _macroExecutor.executeTypesPhase(
+            macroApplication.instanceIdentifier, declaration);
+        results.add(result);
+      }
+    }
+    return results;
+  }
+
+  Future<void> applyTypeMacros() async {
+    for (MapEntry<SourceLibraryBuilder,
+        LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+      LibraryMacroApplicationData libraryMacroApplicationData =
+          libraryEntry.value;
+      for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+          in libraryMacroApplicationData.memberApplications.entries) {
+        MemberBuilder memberBuilder = memberEntry.key;
+        macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
+        if (declaration != null) {
+          List<MacroExecutionResult> results =
+              await _applyTypeMacros(declaration, memberEntry.value);
+          dataForTesting?.memberTypesResults[memberBuilder] = results;
+        }
+      }
+    }
+  }
+
+  Future<List<MacroExecutionResult>> _applyDeclarationMacros(
+      macro.Declaration declaration,
+      List<MacroApplication> macroApplications,
+      macro.TypeResolver typeResolver,
+      macro.ClassIntrospector classIntrospector) async {
+    List<MacroExecutionResult> results = [];
+    for (MacroApplication macroApplication in macroApplications) {
+      if (macroApplication.instanceIdentifier.shouldExecute(
+          // TODO(johnniwinther): Get the declaration kind from [declaration].
+          DeclarationKind.function,
+          Phase.declarations)) {
+        MacroExecutionResult result =
+            await _macroExecutor.executeDeclarationsPhase(
+                macroApplication.instanceIdentifier,
+                declaration,
+                typeResolver,
+                classIntrospector);
+        results.add(result);
+      }
+    }
+    return results;
+  }
+
+  Future<void> applyDeclarationMacros() async {
+    macro.TypeResolver typeResolver = new _TypeResolver(this);
+    macro.ClassIntrospector classIntrospector = new _ClassIntrospector();
+    for (MapEntry<SourceLibraryBuilder,
+        LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+      LibraryMacroApplicationData libraryMacroApplicationData =
+          libraryEntry.value;
+      for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+          in libraryMacroApplicationData.memberApplications.entries) {
+        MemberBuilder memberBuilder = memberEntry.key;
+        macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
+        if (declaration != null) {
+          List<MacroExecutionResult> results = await _applyDeclarationMacros(
+              declaration, memberEntry.value, typeResolver, classIntrospector);
+          dataForTesting?.memberDeclarationsResults[memberBuilder] = results;
+        }
+      }
+    }
+  }
+
+  Future<List<MacroExecutionResult>> _applyDefinitionMacros(
+      macro.Declaration declaration,
+      List<MacroApplication> macroApplications,
+      macro.TypeResolver typeResolver,
+      macro.ClassIntrospector classIntrospector,
+      macro.TypeDeclarationResolver typeDeclarationResolver) async {
+    List<MacroExecutionResult> results = [];
+    for (MacroApplication macroApplication in macroApplications) {
+      if (macroApplication.instanceIdentifier.shouldExecute(
+          // TODO(johnniwinther): Get the declaration kind from [declaration].
+          DeclarationKind.function,
+          Phase.definitions)) {
+        MacroExecutionResult result =
+            await _macroExecutor.executeDefinitionsPhase(
+                macroApplication.instanceIdentifier,
+                declaration,
+                typeResolver,
+                classIntrospector,
+                typeDeclarationResolver);
+        results.add(result);
+      }
+    }
+    return results;
+  }
+
+  late TypeEnvironment typeEnvironment;
+
+  Future<void> applyDefinitionMacros(
+      CoreTypes coreTypes, ClassHierarchy classHierarchy) async {
+    typeEnvironment = new TypeEnvironment(coreTypes, classHierarchy);
+    macro.TypeResolver typeResolver = new _TypeResolver(this);
+    macro.ClassIntrospector classIntrospector = new _ClassIntrospector();
+    macro.TypeDeclarationResolver typeDeclarationResolver =
+        new _TypeDeclarationResolver();
+    for (MapEntry<SourceLibraryBuilder,
+        LibraryMacroApplicationData> libraryEntry in libraryData.entries) {
+      LibraryMacroApplicationData libraryMacroApplicationData =
+          libraryEntry.value;
+      for (MapEntry<MemberBuilder, List<MacroApplication>> memberEntry
+          in libraryMacroApplicationData.memberApplications.entries) {
+        MemberBuilder memberBuilder = memberEntry.key;
+        macro.Declaration? declaration = _getMemberDeclaration(memberBuilder);
+        if (declaration != null) {
+          List<MacroExecutionResult> results = await _applyDefinitionMacros(
+              declaration,
+              memberEntry.value,
+              typeResolver,
+              classIntrospector,
+              typeDeclarationResolver);
+          dataForTesting?.memberDefinitionsResults[memberBuilder] = results;
+        }
+      }
+    }
+  }
+
+  void close() {
+    _macroExecutor.close();
+    _staticTypeCache.clear();
+    _typeAnnotationCache.clear();
+  }
+
+  macro.FunctionDeclaration createTopLevelFunctionDeclaration(
+      SourceProcedureBuilder builder) {
+    List<ParameterDeclarationImpl>? positionalParameters;
+    List<ParameterDeclarationImpl>? namedParameters;
+
+    List<FormalParameterBuilder>? formals = builder.formals;
+    if (formals == null) {
+      positionalParameters = namedParameters = const [];
+    } else {
+      positionalParameters = [];
+      namedParameters = [];
+      for (FormalParameterBuilder formal in formals) {
+        TypeAnnotationImpl type =
+            computeTypeAnnotation(builder.library, formal.type);
+        // TODO(johnniwinther): Support default values.
+        if (formal.isNamed) {
+          namedParameters.add(new ParameterDeclarationImpl(
+              id: RemoteInstance.uniqueId,
+              identifier: new IdentifierImpl(
+                  id: RemoteInstance.uniqueId, name: formal.name),
+              isRequired: formal.isNamedRequired,
+              isNamed: true,
+              type: type,
+              defaultValue: null));
+        } else {
+          positionalParameters.add(new ParameterDeclarationImpl(
+              id: RemoteInstance.uniqueId,
+              identifier: new IdentifierImpl(
+                  id: RemoteInstance.uniqueId, name: formal.name),
+              isRequired: formal.isRequired,
+              isNamed: false,
+              type: type,
+              defaultValue: null));
+        }
+      }
+    }
+
+    return new FunctionDeclarationImpl(
+        id: RemoteInstance.uniqueId,
+        identifier:
+            new IdentifierImpl(id: RemoteInstance.uniqueId, name: builder.name),
+        isAbstract: builder.isAbstract,
+        isExternal: builder.isExternal,
+        isGetter: builder.isGetter,
+        isSetter: builder.isSetter,
+        positionalParameters: positionalParameters,
+        namedParameters: namedParameters,
+        returnType: computeTypeAnnotation(builder.library, builder.returnType),
+        // TODO(johnniwinther): Support typeParameters
+        typeParameters: const []);
+  }
+
+  Map<TypeBuilder?, _NamedTypeAnnotationImpl> _typeAnnotationCache = {};
+
+  List<TypeAnnotationImpl> computeTypeAnnotations(
+      LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
+    if (typeBuilders == null) return const [];
+    return new List.generate(typeBuilders.length,
+        (int index) => computeTypeAnnotation(library, typeBuilders[index]));
+  }
+
+  _NamedTypeAnnotationImpl _computeTypeAnnotation(
+      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
+    if (typeBuilder != null) {
+      if (typeBuilder is NamedTypeBuilder) {
+        Object name = typeBuilder.name;
+        List<TypeAnnotationImpl> typeArguments =
+            computeTypeAnnotations(libraryBuilder, typeBuilder.arguments);
+        bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
+        if (name is String) {
+          return new _NamedTypeAnnotationImpl(
+              typeBuilder: typeBuilder,
+              libraryBuilder: libraryBuilder,
+              id: RemoteInstance.uniqueId,
+              identifier:
+                  new IdentifierImpl(id: RemoteInstance.uniqueId, name: name),
+              typeArguments: typeArguments,
+              isNullable: isNullable);
+        } else if (name is QualifiedName) {
+          assert(name.qualifier is String);
+          return new _NamedTypeAnnotationImpl(
+              typeBuilder: typeBuilder,
+              libraryBuilder: libraryBuilder,
+              id: RemoteInstance.uniqueId,
+              identifier: new IdentifierImpl(
+                  id: RemoteInstance.uniqueId,
+                  // TODO: We probably shouldn't be including the qualifier
+                  // here. Kernel should probably have its own implementation
+                  // of Identifier which holds on to the qualified reference
+                  // instead.
+                  name: '${name.qualifier}.${name.name}'),
+              typeArguments: typeArguments,
+              isNullable: isNullable);
+        }
+      }
+    }
+    return new _NamedTypeAnnotationImpl(
+        typeBuilder: typeBuilder,
+        libraryBuilder: libraryBuilder,
+        id: RemoteInstance.uniqueId,
+        identifier: dynamicIdentifier,
+        isNullable: false,
+        typeArguments: const []);
+  }
+
+  TypeAnnotationImpl computeTypeAnnotation(
+      LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
+    return _typeAnnotationCache[typeBuilder] ??=
+        _computeTypeAnnotation(libraryBuilder, typeBuilder);
+  }
+
+  macro.StaticType resolveTypeAnnotation(
+      _NamedTypeAnnotationImpl typeAnnotation) {
+    TypeBuilder? typeBuilder = typeAnnotation.typeBuilder;
+    LibraryBuilder libraryBuilder = typeAnnotation.libraryBuilder;
+    DartType dartType;
+    if (typeBuilder != null) {
+      dartType = typeBuilder.build(libraryBuilder);
+    } else {
+      dartType = const DynamicType();
+    }
+    return createStaticType(dartType);
+  }
+
+  Map<DartType, _StaticTypeImpl> _staticTypeCache = {};
+
+  macro.StaticType createStaticType(DartType dartType) {
+    return _staticTypeCache[dartType] ??= new _StaticTypeImpl(this, dartType);
+  }
+}
+
+class _NamedTypeAnnotationImpl extends NamedTypeAnnotationImpl {
+  final TypeBuilder? typeBuilder;
+  final LibraryBuilder libraryBuilder;
+
+  _NamedTypeAnnotationImpl({
+    required this.typeBuilder,
+    required this.libraryBuilder,
+    required int id,
+    required bool isNullable,
+    required IdentifierImpl identifier,
+    required List<TypeAnnotationImpl> typeArguments,
+  }) : super(
+            id: id,
+            isNullable: isNullable,
+            identifier: identifier,
+            typeArguments: typeArguments);
+}
+
+class _StaticTypeImpl extends macro.StaticType {
+  final MacroApplications macroApplications;
+  final DartType type;
+
+  _StaticTypeImpl(this.macroApplications, this.type);
+
+  @override
+  Future<bool> isExactly(covariant _StaticTypeImpl other) {
+    return new Future.value(type == other.type);
+  }
+
+  @override
+  Future<bool> isSubtypeOf(covariant _StaticTypeImpl other) {
+    return new Future.value(macroApplications.typeEnvironment
+        .isSubtypeOf(type, other.type, SubtypeCheckMode.withNullabilities));
+  }
+}
+
+class _TypeResolver implements macro.TypeResolver {
+  final MacroApplications macroApplications;
+
+  _TypeResolver(this.macroApplications);
+
+  @override
+  Future<macro.StaticType> instantiateCode(macro.ExpressionCode code) {
+    // TODO: implement instantiateCode
+    throw new UnimplementedError();
+  }
+
+  @override
+  Future<macro.StaticType> instantiateType(
+      covariant _NamedTypeAnnotationImpl typeAnnotation) {
+    return new Future.value(
+        macroApplications.resolveTypeAnnotation(typeAnnotation));
+  }
+}
+
+class _ClassIntrospector implements macro.ClassIntrospector {
+  @override
+  Future<List<macro.ConstructorDeclaration>> constructorsOf(
+      macro.ClassDeclaration clazz) {
+    // TODO: implement constructorsOf
+    throw new UnimplementedError('_ClassIntrospector.constructorsOf');
+  }
+
+  @override
+  Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
+    // TODO: implement fieldsOf
+    throw new UnimplementedError('_ClassIntrospector.fieldsOf');
+  }
+
+  @override
+  Future<List<macro.ClassDeclaration>> interfacesOf(
+      macro.ClassDeclaration clazz) {
+    // TODO: implement interfacesOf
+    throw new UnimplementedError('_ClassIntrospector.interfacesOf');
+  }
+
+  @override
+  Future<List<macro.MethodDeclaration>> methodsOf(
+      macro.ClassDeclaration clazz) {
+    // TODO: implement methodsOf
+    throw new UnimplementedError('_ClassIntrospector.methodsOf');
+  }
+
+  @override
+  Future<List<macro.ClassDeclaration>> mixinsOf(macro.ClassDeclaration clazz) {
+    // TODO: implement mixinsOf
+    throw new UnimplementedError('_ClassIntrospector.mixinsOf');
+  }
+
+  @override
+  Future<macro.ClassDeclaration?> superclassOf(macro.ClassDeclaration clazz) {
+    // TODO: implement superclassOf
+    throw new UnimplementedError('_ClassIntrospector.superclassOf');
+  }
+}
+
+class _TypeDeclarationResolver implements macro.TypeDeclarationResolver {
+  @override
+  Future<macro.TypeDeclaration> declarationOf(macro.Identifier identifier) {
+    // TODO: implement declarationOf
+    throw new UnimplementedError('_TypeDeclarationResolver.declarationOf');
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
new file mode 100644
index 0000000..02b0dc4
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/macro_annotation_parser.dart
@@ -0,0 +1,1927 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/messages/codes.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/prefix_builder.dart';
+import '../scope.dart';
+import '../source/diet_parser.dart';
+import '../source/source_library_builder.dart';
+
+import 'macro.dart';
+
+List<MacroApplication>? prebuildAnnotations(
+    {required SourceLibraryBuilder enclosingLibrary,
+    required List<MetadataBuilder>? metadataBuilders,
+    required Uri fileUri,
+    required Scope scope}) {
+  if (metadataBuilders == null) return null;
+  List<MacroApplication>? result;
+  for (MetadataBuilder metadataBuilder in metadataBuilders) {
+    _MacroListener listener =
+        new _MacroListener(enclosingLibrary, fileUri, scope);
+    Parser parser = new Parser(listener,
+        useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
+    parser.parseMetadata(
+        parser.syntheticPreviousToken(metadataBuilder.beginToken));
+    MacroApplication? application = listener.popMacroApplication();
+    if (application != null) {
+      result ??= [];
+      result.add(application);
+    }
+  }
+  return result;
+}
+
+class _Node {}
+
+class _UnrecognizedNode implements _Node {
+  const _UnrecognizedNode();
+}
+
+class _MacroClassNode implements _Node {
+  final Token token;
+  final ClassBuilder classBuilder;
+
+  _MacroClassNode(this.token, this.classBuilder);
+}
+
+class _MacroConstructorNode implements _Node {
+  final ClassBuilder classBuilder;
+  final String constructorName;
+
+  _MacroConstructorNode(this.classBuilder, this.constructorName);
+}
+
+class _PrefixNode implements _Node {
+  final PrefixBuilder prefixBuilder;
+
+  _PrefixNode(this.prefixBuilder);
+}
+
+class _MacroApplicationNode implements _Node {
+  final MacroApplication application;
+
+  _MacroApplicationNode(this.application);
+}
+
+class _NoArgumentsNode implements _Node {
+  const _NoArgumentsNode();
+}
+
+class _ArgumentsNode implements _Node {
+  _ArgumentsNode();
+}
+
+class _MacroListener implements Listener {
+  final SourceLibraryBuilder currentLibrary;
+
+  @override
+  final Uri uri;
+
+  final Scope scope;
+
+  final List<_Node> _stack = [];
+
+  Object? _unrecognized;
+
+  bool get unrecognized => _unrecognized != null;
+
+  void set unrecognized(bool value) {
+    if (value) {
+      // TODO(johnniwinther): Remove this when implementation is more mature.
+      _unrecognized = StackTrace.current;
+    } else {
+      _unrecognized = null;
+    }
+  }
+
+  _MacroListener(this.currentLibrary, this.uri, this.scope);
+
+  void pushUnsupported() {
+    push(const _UnrecognizedNode());
+    _unsupported();
+  }
+
+  void push(_Node node) {
+    _stack.add(node);
+  }
+
+  _Node pop() => _stack.removeLast();
+
+  MacroApplication? popMacroApplication() {
+    if (unrecognized) return null;
+    if (_stack.length != 1) return null;
+    _Node node = pop();
+    if (node is _MacroApplicationNode) {
+      return node.application;
+    }
+    return null;
+  }
+
+  @override
+  void beginMetadata(Token token) {
+    // Do nothing.
+  }
+
+  @override
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
+    _Node argumentsNode = pop();
+    _Node referenceNode = pop();
+    if (!unrecognized) {
+      ClassBuilder? macroClass;
+      String? constructorName;
+      if (referenceNode is _MacroClassNode) {
+        macroClass = referenceNode.classBuilder;
+        MemberBuilder? member = referenceNode.classBuilder
+            .findConstructorOrFactory(
+                '', referenceNode.token.charOffset, uri, currentLibrary);
+        if (member != null) {
+          constructorName = '';
+        }
+      } else if (referenceNode is _MacroConstructorNode) {
+        macroClass = referenceNode.classBuilder;
+        constructorName = referenceNode.constructorName;
+      }
+      if (macroClass != null &&
+          constructorName != null &&
+          argumentsNode is _ArgumentsNode) {
+        push(new _MacroApplicationNode(
+            new MacroApplication(macroClass, constructorName)));
+        return;
+      }
+    }
+    pushUnsupported();
+  }
+
+  @override
+  void handleIdentifier(Token token, IdentifierContext context) {
+    switch (context) {
+      case IdentifierContext.metadataReference:
+        Builder? builder = scope.lookup(token.lexeme, token.charOffset, uri);
+        if (builder is ClassBuilder && builder.isMacro) {
+          push(new _MacroClassNode(token, builder));
+        } else if (builder is PrefixBuilder) {
+          push(new _PrefixNode(builder));
+        } else {
+          pushUnsupported();
+        }
+        break;
+      case IdentifierContext.metadataContinuation:
+        _Node node = pop();
+        if (node is _PrefixNode) {
+          Builder? builder =
+              node.prefixBuilder.lookup(token.lexeme, token.charOffset, uri);
+          if (builder is ClassBuilder && builder.isMacro) {
+            push(new _MacroClassNode(token, builder));
+          } else {
+            pushUnsupported();
+          }
+        } else if (node is _MacroClassNode) {
+          MemberBuilder? member = node.classBuilder.findConstructorOrFactory(
+              token.lexeme, token.charOffset, uri, currentLibrary);
+          if (member != null) {
+            push(new _MacroConstructorNode(node.classBuilder, token.lexeme));
+          } else {
+            pushUnsupported();
+          }
+        } else {
+          pushUnsupported();
+        }
+        break;
+      case IdentifierContext.metadataContinuationAfterTypeArguments:
+        _Node node = pop();
+        if (node is _MacroClassNode) {
+          MemberBuilder? member = node.classBuilder.findConstructorOrFactory(
+              token.lexeme, token.charOffset, uri, currentLibrary);
+          if (member != null) {
+            push(new _MacroConstructorNode(node.classBuilder, token.lexeme));
+          } else {
+            pushUnsupported();
+          }
+        } else {
+          pushUnsupported();
+        }
+        break;
+      default:
+        pushUnsupported();
+        break;
+    }
+  }
+
+  @override
+  void beginArguments(Token token) {
+    // Do nothing.
+  }
+
+  @override
+  void endArguments(int count, Token beginToken, Token endToken) {
+    if (count == 0) {
+      push(new _ArgumentsNode());
+    } else {
+      // TODO(johnniwinther): Handle arguments.
+      pushUnsupported();
+    }
+  }
+
+  @override
+  void handleNoArguments(Token token) {
+    push(const _NoArgumentsNode());
+  }
+
+  @override
+  void handleNoTypeArguments(Token token) {
+    // TODO(johnniwinther): Handle type arguments. Ignore for now.
+  }
+
+  @override
+  void handleQualified(Token period) {
+    // Do nothing. Supported qualified names are handled through the identifier
+    // context.
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Stub implementation
+  //////////////////////////////////////////////////////////////////////////////
+
+  /// Called for listener events that are expected but not supported.
+  void _unsupported() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are unexpected.
+  void _unexpected() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are supported but not handled yet.
+  void _unhandled() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events whose use in unknown.
+  void _unknown() {
+    unrecognized = true;
+  }
+
+  /// Called for listener events that are ignored.
+  void _ignored() {}
+
+  @override
+  void beginAsOperatorType(Token operator) {
+    _unsupported();
+  }
+
+  @override
+  void beginAssert(Token assertKeyword, Assert kind) {
+    _unsupported();
+  }
+
+  @override
+  void beginAwaitExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginBinaryExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginBlock(Token token, BlockKind blockKind) {
+    _unsupported();
+  }
+
+  @override
+  void beginBlockFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginCascade(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginCaseExpression(Token caseKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void beginCatchClause(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginClassDeclaration(
+      Token begin, Token? abstractToken, Token? macroToken, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginClassOrMixinOrExtensionBody(DeclarationKind kind, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginClassOrMixinOrNamedMixinApplicationPrelude(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginCombinators(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginCompilationUnit(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginConditionalExpression(Token question) {
+    _unsupported();
+  }
+
+  @override
+  void beginConditionalUri(Token ifKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginConditionalUris(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginConstExpression(Token constKeyword) {
+    _unhandled();
+  }
+
+  @override
+  void beginConstLiteral(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginConstructorReference(Token start) {
+    _unknown();
+  }
+
+  @override
+  void beginDoWhileStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginDoWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginElseStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginEnum(Token enumKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginExport(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {
+    _unexpected();
+  }
+
+  @override
+  void beginExtensionDeclarationPrelude(Token extensionKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginFactoryMethod(DeclarationKind declarationKind, Token lastConsumed,
+      Token? externalToken, Token? constToken) {
+    _unexpected();
+  }
+
+  @override
+  void beginFieldInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginFields(
+      DeclarationKind declarationKind,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      Token lastConsumed) {
+    _unexpected();
+  }
+
+  @override
+  void beginForControlFlow(Token? awaitToken, Token forToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginForInBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForInExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginForStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameterDefaultValueExpression() {
+    _unsupported();
+  }
+
+  @override
+  void beginFormalParameters(Token token, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionName(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginFunctionType(Token beginToken) {
+    _unhandled();
+  }
+
+  @override
+  void beginFunctionTypedFormalParameter(Token token) {
+    _unknown();
+  }
+
+  @override
+  void beginHide(Token hideKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginIfControlFlow(Token ifToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginIfStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginImplicitCreationExpression(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginImport(Token importKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginInitializedIdentifier(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginInitializers(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginIsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void beginLabeledStatement(Token token, int labelCount) {
+    _unsupported();
+  }
+
+  @override
+  void beginLibraryName(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginLiteralString(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginLiteralSymbol(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginLocalFunctionDeclaration(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginMember() {
+    _unexpected();
+  }
+
+  @override
+  void beginMetadataStar(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginMethod(
+      DeclarationKind declarationKind,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginMixinDeclaration(Token mixinKeyword, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginNamedFunctionExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginNamedMixinApplication(
+      Token begin, Token? abstractToken, Token? macroToken, Token name) {
+    _unexpected();
+  }
+
+  @override
+  void beginNewExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginOptionalFormalParameters(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginPart(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginPartOf(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginRedirectingFactoryBody(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginRethrowStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginReturnStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginShow(Token showKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void beginSwitchBlock(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
+    _unsupported();
+  }
+
+  @override
+  void beginSwitchStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginThenStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTopLevelMember(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
+    _unexpected();
+  }
+
+  @override
+  void beginTryStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypeArguments(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void beginTypeList(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginTypeVariable(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypeVariables(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginTypedef(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginUncategorizedTopLevelDeclaration(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void beginVariableInitializer(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginVariablesDeclaration(
+      Token token, Token? lateToken, Token? varFinalOrConst) {
+    _unsupported();
+  }
+
+  @override
+  void beginWhileStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void beginYieldStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endAsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+      Token? commaToken, Token semicolonToken) {
+    _unsupported();
+  }
+
+  @override
+  void endAwaitExpression(Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endBinaryExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
+    _unsupported();
+  }
+
+  @override
+  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endCascade() {
+    _unsupported();
+  }
+
+  @override
+  void endCaseExpression(Token colon) {
+    _unsupported();
+  }
+
+  @override
+  void endCatchClause(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endClassOrMixinOrExtensionBody(
+      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endCombinators(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endCompilationUnit(int count, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endConditionalExpression(Token question, Token colon) {
+    _unhandled();
+  }
+
+  @override
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
+    _unexpected();
+  }
+
+  @override
+  void endConditionalUris(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endConstExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endConstLiteral(Token token) {
+    _unknown();
+  }
+
+  @override
+  void endConstructorReference(Token start, Token? periodBeforeName,
+      Token endToken, ConstructorReferenceContext constructorReferenceContext) {
+    _unknown();
+  }
+
+  @override
+  void endDoWhileStatement(
+      Token doKeyword, Token whileKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endDoWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endElseStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endEnum(Token enumKeyword, Token leftBrace, int memberCount) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExport(Token exportKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionDeclaration(Token extensionKeyword, Token? typeKeyword,
+      Token onKeyword, Token? showKeyword, Token? hideKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endFieldInitializer(Token assignment, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endForControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForIn(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endForInBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForInControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForInExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endForStatement(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameter(
+      Token? thisKeyword,
+      Token? superKeyword,
+      Token? periodAfterThisOrSuper,
+      Token nameToken,
+      Token? initializerStart,
+      Token? initializerEnd,
+      FormalParameterKind kind,
+      MemberKind memberKind) {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameterDefaultValueExpression() {
+    _unsupported();
+  }
+
+  @override
+  void endFormalParameters(
+      int count, Token beginToken, Token endToken, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionExpression(Token beginToken, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionName(Token beginToken, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endFunctionType(Token functionToken, Token? questionMark) {
+    _unhandled();
+  }
+
+  @override
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
+    _unknown();
+  }
+
+  @override
+  void endHide(Token hideKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void endIfControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endIfElseControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endIfStatement(Token ifToken, Token? elseToken) {
+    _unsupported();
+  }
+
+  @override
+  void endImplicitCreationExpression(Token token, Token openAngleBracket) {
+    _unhandled();
+  }
+
+  @override
+  void endImport(Token importKeyword, Token? semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endInitializedIdentifier(Token nameToken) {
+    _unsupported();
+  }
+
+  @override
+  void endInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void endInitializers(int count, Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endInvalidAwaitExpression(
+      Token beginToken, Token endToken, MessageCode errorCode) {
+    _unsupported();
+  }
+
+  @override
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
+      Token endToken, MessageCode errorCode) {
+    _unsupported();
+  }
+
+  @override
+  void endIsOperatorType(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void endLabeledStatement(int labelCount) {
+    _unsupported();
+  }
+
+  @override
+  void endLibraryName(Token libraryKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endLiteralString(int interpolationCount, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void endLiteralSymbol(Token hashToken, int identifierCount) {
+    _unhandled();
+  }
+
+  @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endMember() {
+    _unexpected();
+  }
+
+  @override
+  void endMetadataStar(int count) {
+    _unsupported();
+  }
+
+  @override
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinFields(
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endNamedFunctionExpression(Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
+      Token? implementsKeyword, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endNewExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endOptionalFormalParameters(
+      int count, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endPart(Token partKeyword, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void endPartOf(
+      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+    _unexpected();
+  }
+
+  @override
+  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endReturnStatement(
+      bool hasExpression, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endShow(Token showKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endSwitchCase(
+      int labelCount,
+      int expressionCount,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
+      int statementCount,
+      Token firstToken,
+      Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endSwitchStatement(Token switchKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endThenStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endTopLevelDeclaration(Token nextToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTopLevelFields(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void endTypeArguments(int count, Token beginToken, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void endTypeList(int count) {
+    _unexpected();
+  }
+
+  @override
+  void endTypeVariable(
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
+    _unsupported();
+  }
+
+  @override
+  void endTypeVariables(Token beginToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endTypedef(Token typedefKeyword, Token? equals, Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void endVariableInitializer(Token assignmentOperator) {
+    _unsupported();
+  }
+
+  @override
+  void endVariablesDeclaration(int count, Token? endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endWhileStatement(Token whileKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void endWhileStatementBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleAsOperator(Token operator) {
+    _unhandled();
+  }
+
+  @override
+  void handleAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleBreakStatement(
+      bool hasTarget, Token breakKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleCaseMatch(Token caseKeyword, Token colon) {
+    _unsupported();
+  }
+
+  @override
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
+    _unsupported();
+  }
+
+  @override
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleClassNoWithClause() {
+    _unexpected();
+  }
+
+  @override
+  void handleClassWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleCommentReference(
+      Token? newKeyword,
+      Token? firstToken,
+      Token? firstPeriod,
+      Token? secondToken,
+      Token? secondPeriod,
+      Token thirdToken) {
+    _ignored();
+  }
+
+  @override
+  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+    _ignored();
+  }
+
+  @override
+  void handleConditionalExpressionColon() {
+    _unhandled();
+  }
+
+  @override
+  void handleConstFactory(Token constKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleContinueStatement(
+      bool hasTarget, Token continueKeyword, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleDirectivesOnly() {
+    _unknown();
+  }
+
+  @override
+  void handleDottedName(int count, Token firstIdentifier) {
+    _unknown();
+  }
+
+  @override
+  void handleElseControlFlow(Token elseToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleEmptyFunctionBody(Token semicolon) {
+    _unsupported();
+  }
+
+  @override
+  void handleEmptyStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleEndingBinaryExpression(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleEnumElement(Token beginToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumElements(Token elementsEndToken, int elementsCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumHeader(Token enumKeyword, Token leftBrace) {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumNoWithClause() {
+    _unexpected();
+  }
+
+  @override
+  void handleEnumWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleErrorToken(ErrorToken token) {
+    _unsupported();
+  }
+
+  @override
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleExpressionStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleExtensionShowHide(Token? showKeyword, int showElementCount,
+      Token? hideKeyword, int hideElementCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleExtraneousExpression(Token token, Message message) {
+    _unknown();
+  }
+
+  @override
+  void handleFinallyBlock(Token finallyKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
+      Token leftParenthesis, Token inKeyword) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerEmptyStatement(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
+    _unsupported();
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
+    _unsupported();
+  }
+
+  @override
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {
+    _unsupported();
+  }
+
+  @override
+  void handleFormalParameterWithoutValue(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+    _unsupported();
+  }
+
+  @override
+  void handleIdentifierList(int count) {
+    _unknown();
+  }
+
+  @override
+  void handleImplements(Token? implementsKeyword, int interfacesCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleIndexedExpression(
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
+    _unsupported();
+  }
+
+  @override
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleInvalidExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidMember(Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidStatement(Token token, Message message) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidTopLevelBlock(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidTopLevelDeclaration(Token endToken) {
+    _unexpected();
+  }
+
+  @override
+  void handleInvalidTypeArguments(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleIsOperator(Token isOperator, Token? not) {
+    _unhandled();
+  }
+
+  @override
+  void handleLabel(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleLiteralBool(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralDouble(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralInt(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralList(
+      int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralNull(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleLiteralSetOrMap(int count, Token leftBrace, Token? constKeyword,
+      Token rightBrace, bool hasSetEntry) {
+    _unhandled();
+  }
+
+  @override
+  void handleMixinHeader(Token mixinKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleMixinOn(Token? onKeyword, int typeCount) {
+    _unexpected();
+  }
+
+  @override
+  void handleNamedArgument(Token colon) {
+    _unhandled();
+  }
+
+  @override
+  void handleNamedMixinApplicationWithClause(Token withKeyword) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeClause(Token nativeToken, bool hasName) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleNewAsIdentifier(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleNoCommentReference() {
+    _ignored();
+  }
+
+  @override
+  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoFieldInitializer(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleNoFormalParameters(Token token, MemberKind kind) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoFunctionBody(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoInitializers() {
+    _unexpected();
+  }
+
+  @override
+  void handleNoName(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoType(Token lastConsumed) {
+    _unknown();
+  }
+
+  @override
+  void handleNoTypeNameInConstructorReference(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleNoTypeVariables(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNoVariableInitializer(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleNonNullAssertExpression(Token bang) {
+    _unsupported();
+  }
+
+  @override
+  void handleOperator(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleOperatorName(Token operatorKeyword, Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleParenthesizedCondition(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleParenthesizedExpression(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleRecoverClassHeader() {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverImport(Token? semicolon) {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    _unexpected();
+  }
+
+  @override
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleScript(Token token) {
+    _unexpected();
+  }
+
+  @override
+  void handleSend(Token beginToken, Token endToken) {
+    _unhandled();
+  }
+
+  @override
+  void handleShowHideIdentifier(Token? modifier, Token identifier) {
+    _unexpected();
+  }
+
+  @override
+  void handleSpreadExpression(Token spreadToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleStringJuxtaposition(Token startToken, int literalCount) {
+    _unhandled();
+  }
+
+  @override
+  void handleStringPart(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleSuperExpression(Token token, IdentifierContext context) {
+    _unsupported();
+  }
+
+  @override
+  void handleSymbolVoid(Token token) {
+    _unhandled();
+  }
+
+  @override
+  void handleThenControlFlow(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleThisExpression(Token token, IdentifierContext context) {
+    _unsupported();
+  }
+
+  @override
+  void handleThrowExpression(Token throwToken, Token endToken) {
+    _unsupported();
+  }
+
+  @override
+  void handleType(Token beginToken, Token? questionMark) {
+    _unknown();
+  }
+
+  @override
+  void handleTypeArgumentApplication(Token openAngleBracket) {
+    _unhandled();
+  }
+
+  @override
+  void handleTypeVariablesDefined(Token token, int count) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPostfixAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPrefixAssignmentExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnaryPrefixExpression(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleUnescapeError(
+      Message message, covariant Token location, int stringOffset, int length) {
+    _unsupported();
+  }
+
+  @override
+  void handleValuedFormalParameter(Token equals, Token token) {
+    _unsupported();
+  }
+
+  @override
+  void handleVoidKeyword(Token token) {
+    _unknown();
+  }
+
+  @override
+  void handleVoidKeywordWithTypeArguments(Token token) {
+    _unsupported();
+  }
+
+  @override
+  void logEvent(String name) {}
+
+  @override
+  void reportVarianceModifierNotEnabled(Token? variance) {
+    _unsupported();
+  }
+}
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 a0fef49..55c1e0b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -158,14 +158,16 @@
 NullabilityBuilder combineNullabilityBuildersForSubstitution(
     NullabilityBuilder a, NullabilityBuilder b) {
   assert(
-      (identical(a, const NullabilityBuilder.nullable()) ||
-              identical(a, const NullabilityBuilder.omitted())) &&
-          (identical(b, const NullabilityBuilder.nullable()) ||
-              identical(b, const NullabilityBuilder.omitted())),
+      // ignore: unnecessary_null_comparison
+      a != null && b != null,
       "Both arguments to combineNullabilityBuildersForSubstitution "
       "should be identical to either 'const NullabilityBuilder.nullable()' or "
       "'const NullabilityBuilder.omitted()'.");
 
+  if (identical(a, const NullabilityBuilder.inherent()) &&
+      identical(b, const NullabilityBuilder.inherent())) {
+    return const NullabilityBuilder.inherent();
+  }
   if (identical(a, const NullabilityBuilder.nullable()) ||
       identical(b, const NullabilityBuilder.nullable())) {
     return const NullabilityBuilder.nullable();
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index f69cc83..2ccd860 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -5,7 +5,7 @@
 library fasta.scope;
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 
 import 'builder/builder.dart';
 import 'builder/extension_builder.dart';
@@ -13,11 +13,6 @@
 import 'builder/member_builder.dart';
 import 'builder/name_iterator.dart';
 import 'builder/type_variable_builder.dart';
-import 'kernel/body_builder.dart' show JumpTarget;
-import 'kernel/hierarchy/class_member.dart' show ClassMember;
-import 'kernel/kernel_helper.dart';
-import 'util/helpers.dart' show DelayedActionPerformer;
-
 import 'fasta_codes.dart'
     show
         LocatedMessage,
@@ -26,8 +21,13 @@
         templateAccessError,
         templateDuplicatedDeclarationUse,
         templateDuplicatedNamePreviouslyUsedCause;
-
+import 'kernel/body_builder.dart' show JumpTarget;
+import 'kernel/hierarchy/class_member.dart' show ClassMember;
+import 'kernel/kernel_helper.dart';
 import 'problems.dart' show internalProblem, unsupported;
+import 'source/source_library_builder.dart';
+import 'source/source_member_builder.dart';
+import 'util/helpers.dart' show DelayedActionPerformer;
 
 class MutableScope {
   /// Names declared in this scope.
@@ -424,6 +424,10 @@
     _setters.forEach(f);
   }
 
+  void forEachLocalExtension(void Function(ExtensionBuilder member) f) {
+    _extensions?.forEach(f);
+  }
+
   Iterable<Builder> get localMembers => _local.values;
 
   Iterable<MemberBuilder> get localSetters => _setters.values;
@@ -768,7 +772,10 @@
   }
 }
 
-mixin ErroneousMemberBuilderMixin implements MemberBuilder {
+mixin ErroneousMemberBuilderMixin implements SourceMemberBuilder {
+  @override
+  MemberDataForTesting? get dataForTesting => null;
+
   @override
   Member get member => throw new UnsupportedError('$runtimeType.member');
 
@@ -815,8 +822,8 @@
 
   @override
   void buildOutlineExpressions(
-      LibraryBuilder library,
-      CoreTypes coreTypes,
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     throw new UnsupportedError(
@@ -824,6 +831,12 @@
   }
 
   @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    assert(false, "Unexpected call to $runtimeType.buildMembers.");
+  }
+
+  @override
   List<ClassMember> get localMembers => const <ClassMember>[];
 
   @override
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 ae3196c..143fcb8 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -12,40 +12,26 @@
         MemberKind,
         Parser,
         optional;
-
 import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
-
 import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
     show FixedNullableList, NullValue, ParserRecovery;
-
 import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
 import 'package:kernel/ast.dart';
-
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
 import 'package:kernel/core_types.dart' show CoreTypes;
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/declaration_builder.dart';
-import '../builder/field_builder.dart';
 import '../builder/formal_parameter_builder.dart';
-import '../builder/function_builder.dart';
 import '../builder/function_type_builder.dart';
 import '../builder/metadata_builder.dart';
 import '../builder/modifier_builder.dart';
 import '../builder/type_alias_builder.dart';
 import '../builder/type_builder.dart';
-
-import '../identifiers.dart' show QualifiedName;
-
 import '../constant_context.dart' show ConstantContext;
-
 import '../crash.dart' show Crash;
-
 import '../fasta_codes.dart'
     show
         Code,
@@ -53,27 +39,22 @@
         Message,
         messageExpectedBlockToSkip,
         templateInternalProblemNotFound;
-
+import '../identifiers.dart' show QualifiedName;
 import '../ignored_parser_errors.dart' show isIgnoredParserError;
-
 import '../kernel/body_builder.dart' show BodyBuilder, FormalParameters;
-
 import '../problems.dart'
     show DebugAbort, internalProblem, unexpected, unhandled;
-
 import '../scope.dart';
-
 import '../source/value_kinds.dart';
-
 import '../type_inference/type_inference_engine.dart'
     show InferenceDataForTesting, TypeInferenceEngine;
-
 import '../type_inference/type_inferrer.dart' show TypeInferrer;
-
 import 'diet_parser.dart';
-
+import 'source_constructor_builder.dart';
+import 'source_enum_builder.dart';
+import 'source_field_builder.dart';
+import 'source_function_builder.dart';
 import 'source_library_builder.dart' show SourceLibraryBuilder;
-
 import 'stack_listener_impl.dart';
 
 class DietListener extends StackListenerImpl {
@@ -207,6 +188,12 @@
   }
 
   @override
+  void handleNamedArgument(Token colon) {
+    debugEvent("NamedArgument");
+    pop(); // Named argument name.
+  }
+
+  @override
   void handleClassWithClause(Token withKeyword) {
     debugEvent("ClassWithClause");
   }
@@ -373,7 +360,7 @@
 
     final BodyBuilder listener = createFunctionListener(
         lookupBuilder(beginToken, getOrSet, name as String)
-            as FunctionBuilderImpl);
+            as SourceFunctionBuilderImpl);
     buildFunctionBody(listener, bodyToken, metadata, MemberKind.TopLevelMethod);
   }
 
@@ -620,8 +607,8 @@
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || currentClassIsParserRecovery) return;
 
-    FunctionBuilderImpl builder =
-        lookupConstructor(beginToken, name!) as FunctionBuilderImpl;
+    SourceFunctionBuilderImpl builder =
+        lookupConstructor(beginToken, name!) as SourceFunctionBuilderImpl;
     if (_inRedirectingFactory) {
       buildRedirectingFactoryMethod(
           bodyToken, builder, MemberKind.Factory, metadata);
@@ -730,12 +717,13 @@
     Token? metadata = pop() as Token?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || currentClassIsParserRecovery) return;
-    FunctionBuilderImpl builder;
+    SourceFunctionBuilderImpl builder;
     if (isConstructor) {
-      builder = lookupConstructor(beginToken, name!) as FunctionBuilderImpl;
+      builder =
+          lookupConstructor(beginToken, name!) as SourceFunctionBuilderImpl;
     } else {
       builder = lookupBuilder(beginToken, getOrSet, name as String)
-          as FunctionBuilderImpl;
+          as SourceFunctionBuilderImpl;
     }
     buildFunctionBody(
         createFunctionListener(builder),
@@ -799,7 +787,7 @@
       ..constantContext = constantContext;
   }
 
-  BodyBuilder createFunctionListener(FunctionBuilderImpl builder) {
+  BodyBuilder createFunctionListener(SourceFunctionBuilderImpl builder) {
     final Scope typeParameterScope =
         builder.computeTypeParameterScope(memberScope);
     final Scope formalParameterScope =
@@ -816,8 +804,8 @@
         inferenceDataForTesting: builder.dataForTesting?.inferenceData);
   }
 
-  void buildRedirectingFactoryMethod(Token token, FunctionBuilderImpl builder,
-      MemberKind kind, Token? metadata) {
+  void buildRedirectingFactoryMethod(Token token,
+      SourceFunctionBuilderImpl builder, MemberKind kind, Token? metadata) {
     final BodyBuilder listener = createFunctionListener(builder);
     try {
       Parser parser = new Parser(listener,
@@ -982,6 +970,19 @@
   void endEnum(Token enumKeyword, Token leftBrace, int memberCount) {
     debugEvent("Enum");
     checkEmpty(enumKeyword.charOffset);
+
+    SourceEnumBuilder? enumBuilder = currentClass as SourceEnumBuilder?;
+    if (enumBuilder != null) {
+      DeclaredSourceConstructorBuilder? defaultConstructorBuilder =
+          enumBuilder.synthesizedDefaultConstructorBuilder;
+      if (defaultConstructorBuilder != null) {
+        BodyBuilder bodyBuilder =
+            createFunctionListener(defaultConstructorBuilder);
+        bodyBuilder.finishConstructor(
+            defaultConstructorBuilder, AsyncMarker.Sync, new EmptyStatement());
+      }
+    }
+
     currentDeclaration = null;
     memberScope = libraryBuilder.scope;
   }
@@ -1007,37 +1008,15 @@
   @override
   void endEnumConstructor(Token? getOrSet, Token beginToken, Token beginParam,
       Token? beginInitializers, Token endToken) {
-    // TODO(chloestefantsova): Call endClassConstructor instead.
-    debugEvent("EnumConstructor");
-    pop(); // bodyToken
-    pop(); // name
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    // Skip the declaration. An error as already been produced by the parser.
-  }
-
-  @override
-  void endEnumFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    // TODO(chloestefantsova): Call endClassFactoryMethod instead.
-    debugEvent("EnumFactoryMethod");
-    pop(); // bodyToken
-    pop(); // name
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    // Skip the declaration. An error as already been produced by the parser.
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, true);
   }
 
   @override
   void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
       Token? beginInitializers, Token endToken) {
-    // TODO(chloestefantsova): Call endClassMethod instead.
-    debugEvent("EnumMethod");
-    pop(); // bodyToken
-    pop(); // name
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    // Skip the declaration. An error as already been produced by the parser.
+    _endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken, false);
   }
 
   @override
@@ -1051,12 +1030,8 @@
       int count,
       Token beginToken,
       Token endToken) {
-    // TODO(chloestefantsova): Call endClassFields instead.
-    debugEvent("EnumFields");
-    const FixedNullableList<String>().pop(stack, count); // names
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    // Skip the declaration. An error as already been produced by the parser.
+    debugEvent("Fields");
+    buildFields(count, beginToken, false);
   }
 
   @override
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 82bbe12..47620d5 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -14,23 +14,16 @@
         lengthOfSpan,
         MemberKind,
         optional;
-
 import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
-
 import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
     show FixedNullableList, NullValue, ParserRecovery;
-
 import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
 import 'package:_fe_analyzer_shared/src/util/link.dart';
-
 import 'package:kernel/ast.dart'
     show AsyncMarker, InvalidType, Nullability, ProcedureKind, Variance;
 
 import '../builder/constructor_reference_builder.dart';
-import '../builder/enum_builder.dart';
 import '../builder/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_type_builder.dart';
@@ -41,20 +34,13 @@
 import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
-
 import '../combinator.dart' show CombinatorBuilder;
-
 import '../configuration.dart' show Configuration;
-
 import '../fasta_codes.dart';
-
 import '../identifiers.dart' show QualifiedName, flattenName;
-
 import '../ignored_parser_errors.dart' show isIgnoredParserError;
-
 import '../kernel/type_algorithms.dart';
 import '../kernel/utils.dart';
-
 import '../modifier.dart'
     show
         Const,
@@ -73,27 +59,22 @@
         mixinDeclarationMask,
         requiredMask,
         staticMask;
-
 import '../operator.dart'
     show
         Operator,
         operatorFromString,
         operatorToString,
         operatorRequiredArgumentCount;
-
 import '../problems.dart' show unhandled;
-
+import 'source_enum_builder.dart';
 import 'source_extension_builder.dart';
-
 import 'source_library_builder.dart'
     show
         TypeParameterScopeBuilder,
         TypeParameterScopeKind,
         FieldInfo,
         SourceLibraryBuilder;
-
 import 'stack_listener_impl.dart';
-
 import 'value_kinds.dart';
 
 enum MethodBody {
@@ -1775,6 +1756,7 @@
         case _MethodKind.classConstructor:
         case _MethodKind.mixinConstructor:
         case _MethodKind.extensionConstructor:
+        case _MethodKind.enumConstructor:
           constructorName = libraryBuilder.computeAndValidateConstructorName(
                   name, charOffset) ??
               name as String?;
@@ -1782,6 +1764,7 @@
         case _MethodKind.classMethod:
         case _MethodKind.mixinMethod:
         case _MethodKind.extensionMethod:
+        case _MethodKind.enumMethod:
           break;
       }
       bool isStatic = (modifiers & staticMask) != 0;
@@ -1916,6 +1899,13 @@
   }
 
   @override
+  void handleNamedArgument(Token colon) {
+    debugEvent("NamedArgument");
+    pop(); // Named argument offset.
+    pop(); // Named argument name.
+  }
+
+  @override
   void endNamedMixinApplication(Token beginToken, Token classKeyword,
       Token equals, Token? implementsKeyword, Token endToken) {
     debugEvent("endNamedMixinApplication");
@@ -2022,7 +2012,7 @@
   @override
   void endArguments(int count, Token beginToken, Token endToken) {
     debugEvent("Arguments");
-    push(NullValue.Arguments);
+    push(beginToken);
   }
 
   @override
@@ -2317,6 +2307,7 @@
     } else {
       declarationName = '#enum';
     }
+    libraryBuilder.setCurrentClassName(declarationName);
     pushDeclarationContext(DeclarationContext.Enum);
     libraryBuilder.beginNestedDeclaration(
         TypeParameterScopeKind.enumDeclaration, declarationName);
@@ -2325,14 +2316,42 @@
   @override
   void handleEnumElement(Token beginToken) {
     debugEvent("EnumElements");
-    pop(); // arguments.
-    pop(); // constructor reference.
-    // Keep on the stack the EnumConstantInfo created in handleIdentifier.
+    Token? argumentsBeginToken = pop() as Token?;
+
+    ConstructorReferenceBuilder? constructorReferenceBuilder =
+        pop() as ConstructorReferenceBuilder?;
+    Object? enumConstantInfo = pop();
+    if (enumConstantInfo is EnumConstantInfo) {
+      push(enumConstantInfo
+        ..constructorReferenceBuilder = constructorReferenceBuilder
+        ..argumentsBeginToken = argumentsBeginToken);
+    } else {
+      assert(enumConstantInfo is ParserRecovery);
+      push(enumConstantInfo);
+    }
   }
 
   @override
   void handleEnumHeader(Token enumKeyword, Token leftBrace) {
     debugEvent("EnumHeader");
+
+    // We pop more values than needed to reach typeVariables, offset and name.
+    List<TypeBuilder>? interfaces = pop() as List<TypeBuilder>?;
+    Object? mixins = pop();
+    List<TypeVariableBuilder>? typeVariables =
+        pop() as List<TypeVariableBuilder>?;
+    int charOffset = popCharOffset(); // identifier char offset.
+    Object? name = pop();
+
+    libraryBuilder.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
+        name is String ? name : "<syntax-error>", charOffset, typeVariables);
+
+    push(name ?? NullValue.Name);
+    push(charOffset);
+    push(typeVariables ?? NullValue.TypeVariables);
+    push(mixins ?? NullValue.TypeBuilder);
+    push(interfaces ?? NullValue.TypeBuilderList);
+
     push(enumKeyword.charOffset); // start char offset.
     push(leftBrace.endGroup!.charOffset); // end char offset.
   }
@@ -2340,12 +2359,20 @@
   @override
   void handleEnumElements(Token elementsEndToken, int elementsCount) {
     debugEvent("EnumElements");
+    push(elementsCount);
+  }
+
+  @override
+  void endEnum(Token enumKeyword, Token leftBrace, int memberCount) {
+    debugEvent("Enum");
+
+    int elementsCount = pop() as int;
     List<EnumConstantInfo?>? enumConstantInfos =
         const FixedNullableList<EnumConstantInfo>().pop(stack, elementsCount);
     int endCharOffset = popCharOffset();
     int startCharOffset = popCharOffset();
-    pop() as List<TypeBuilder>?; // interfaces.
-    pop() as List<TypeBuilder>?; // mixins.
+    List<TypeBuilder>? interfaces = pop() as List<TypeBuilder>?;
+    MixinApplicationBuilder? mixinBuilder = pop() as MixinApplicationBuilder?;
     List<TypeVariableBuilder>? typeVariables =
         pop() as List<TypeVariableBuilder>?;
     int charOffset = popCharOffset(); // identifier char offset.
@@ -2354,19 +2381,38 @@
     checkEmpty(startCharOffset);
 
     if (name is! ParserRecovery) {
-      libraryBuilder.addEnum(metadata, name as String, enumConstantInfos,
-          startCharOffset, charOffset, endCharOffset);
+      if (interfaces != null) {
+        for (TypeBuilder interface in interfaces) {
+          if (interface.nullabilityBuilder.build(libraryBuilder) ==
+              Nullability.nullable) {
+            libraryBuilder.addProblem(
+                templateNullableInterfaceError
+                    .withArguments(interface.fullNameForErrors),
+                interface.charOffset ?? startCharOffset,
+                (name as String).length,
+                uri);
+          }
+        }
+      }
+
+      libraryBuilder.addEnum(
+          metadata,
+          name as String,
+          typeVariables,
+          mixinBuilder,
+          interfaces,
+          enumConstantInfos,
+          startCharOffset,
+          charOffset,
+          endCharOffset);
     } else {
       libraryBuilder
           .endNestedDeclaration(
               TypeParameterScopeKind.enumDeclaration, "<syntax-error>")
           .resolveNamedTypes(typeVariables, libraryBuilder);
     }
-  }
 
-  @override
-  void endEnum(Token enumKeyword, Token leftBrace, int memberCount) {
-    debugEvent("Enum");
+    libraryBuilder.setCurrentClassName(null);
     checkEmpty(enumKeyword.charOffset);
     popDeclarationContext(DeclarationContext.Enum);
   }
@@ -3015,73 +3061,7 @@
   @override
   void endEnumFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
-    // TODO(cstefantsova): Call endClassFactoryMethod instead.
     debugEvent("EnumFactoryMethod");
-    MethodBody bodyKind = pop() as MethodBody;
-    if (bodyKind == MethodBody.RedirectingFactoryBody) {
-      pop(); // reference
-    }
-    pop(); // async marker
-    pop(); // formals
-    popCharOffset(); // formals char offset
-    pop(); // type variables
-    popCharOffset(); // char offset
-    pop(); // name
-    pop(); // modifiers
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    popDeclarationContext();
-    // TODO(cstefantsova): Use actual type parameters.
-    libraryBuilder
-        .endNestedDeclaration(
-            TypeParameterScopeKind.factoryMethod, "#factory_method")
-        .resolveNamedTypes([], libraryBuilder);
-    // Skip the declaration. An error as already been produced by the parser.
-
-    if (libraryBuilder.enableEnhancedEnumsInLibrary) {
-      addProblem(messageEnumDeclaresFactory, beginToken.charOffset, -1);
-    } else {
-      addProblem(
-          templateExperimentNotEnabled.withArguments('enhanced-enums',
-              libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
-          beginToken.charOffset,
-          -1);
-    }
-  }
-
-  @override
-  void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
-      Token? beginInitializers, Token endToken) {
-    // TODO(cstefantsova): Call endClassMethod instead.
-    debugEvent("EnumMethod");
-    MethodBody bodyKind = pop() as MethodBody;
-    if (bodyKind == MethodBody.RedirectingFactoryBody) {
-      pop(); // reference
-    }
-    pop(); // async marker
-    pop(); // formals
-    popCharOffset(); // formals char offset
-    pop(); // type variables
-    popCharOffset(); // char offset
-    pop(); // name
-    pop(); // return type
-    int modifiers = Modifier.toMask(pop() as List<Modifier>?);
-    popCharOffset(); // final or const offset
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    popDeclarationContext();
-    TypeParameterScopeKind scopeKind;
-    if ((modifiers & staticMask) != 0) {
-      scopeKind = TypeParameterScopeKind.staticMethod;
-    } else {
-      scopeKind = TypeParameterScopeKind.instanceMethod;
-    }
-    // TODO(cstefantsova): Use actual type parameters.
-    libraryBuilder
-        .endNestedDeclaration(scopeKind, "#method")
-        .resolveNamedTypes([], libraryBuilder);
-    // Skip the declaration. An error as already been produced by the parser.
-
     if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
       addProblem(
           templateExperimentNotEnabled.withArguments('enhanced-enums',
@@ -3089,6 +3069,23 @@
           beginToken.charOffset,
           -1);
     }
+
+    _endFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  @override
+  void endEnumMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
+    if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
+      addProblem(
+          templateExperimentNotEnabled.withArguments('enhanced-enums',
+              libraryBuilder.enableEnhancedEnumsVersionInLibrary.toText()),
+          beginToken.charOffset,
+          -1);
+    }
+
+    _endClassMethod(getOrSet, beginToken, beginParam, beginInitializers,
+        endToken, _MethodKind.enumMethod);
   }
 
   @override
@@ -3102,15 +3099,6 @@
       int count,
       Token beginToken,
       Token endToken) {
-    // TODO(cstefantsova): Call endClassFields instead.
-    debugEvent("EnumFields");
-    popFieldInfos(count); // field infos
-    pop(); // type
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    popDeclarationContext();
-    // Skip the declaration. An error as already been produced by the parser.
-
     if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
       addProblem(
           templateExperimentNotEnabled.withArguments('enhanced-enums',
@@ -3118,35 +3106,13 @@
           beginToken.charOffset,
           -1);
     }
+    endClassFields(abstractToken, externalToken, staticToken, covariantToken,
+        lateToken, varFinalOrConst, count, beginToken, endToken);
   }
 
   @override
   void endEnumConstructor(Token? getOrSet, Token beginToken, Token beginParam,
       Token? beginInitializers, Token endToken) {
-    // TODO(cstefantsova): Call endClassConstructor instead.
-    debugEvent("EnumMethod");
-    MethodBody bodyKind = pop() as MethodBody;
-    if (bodyKind == MethodBody.RedirectingFactoryBody) {
-      pop(); // reference
-    }
-    pop(); // async marker
-    pop(); // formals
-    popCharOffset(); // formals char offset
-    pop(); // type variables
-    popCharOffset(); // char offset
-    pop(); // name
-    pop(); // return type
-    pop(); // modifiers
-    popCharOffset(); // final or const offset
-    pop(); // metadata
-    checkEmpty(beginToken.charOffset);
-    popDeclarationContext();
-    // TODO(cstefantsova): Use actual type parameters.
-    libraryBuilder
-        .endNestedDeclaration(TypeParameterScopeKind.instanceMethod, "#method")
-        .resolveNamedTypes([], libraryBuilder);
-    // Skip the declaration. An error as already been produced by the parser.
-
     if (!libraryBuilder.enableEnhancedEnumsInLibrary) {
       addProblem(
           templateExperimentNotEnabled.withArguments('enhanced-enums',
@@ -3154,6 +3120,9 @@
           beginToken.charOffset,
           -1);
     }
+
+    _endClassMethod(getOrSet, beginToken, beginParam, beginInitializers,
+        endToken, _MethodKind.enumConstructor);
   }
 
   @override
@@ -3261,15 +3230,17 @@
     if (mixins is ParserRecovery) {
       push(new ParserRecovery(withKeyword.charOffset));
     } else {
-      // TODO(cstefantsova): Handle enum mixins here.
-      push(mixins);
+      push(libraryBuilder.addMixinApplication(
+          libraryBuilder.loader.target.underscoreEnumType,
+          mixins as List<TypeBuilder>,
+          withKeyword.charOffset));
     }
   }
 
   @override
   void handleEnumNoWithClause() {
     debugEvent("EnumNoWithClause");
-    push(NullValue.TypeBuilderList);
+    push(NullValue.TypeBuilder);
   }
 
   @override
@@ -3337,4 +3308,6 @@
   mixinMethod,
   extensionConstructor,
   extensionMethod,
+  enumConstructor,
+  enumMethod,
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 6c5157d..50fad75 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -7,6 +7,7 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart'
     show ClassHierarchy, ClassHierarchyMembers;
+import 'package:kernel/core_types.dart';
 import 'package:kernel/reference_from_index.dart' show IndexedClass;
 import 'package:kernel/src/bounds_checks.dart';
 import 'package:kernel/src/legacy_erasure.dart';
@@ -16,47 +17,47 @@
         FreshTypeParameters,
         Substitution,
         getFreshTypeParameters,
+        substitute,
         updateBoundNullabilities;
 import 'package:kernel/type_environment.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
 import '../builder/constructor_reference_builder.dart';
-import '../builder/factory_builder.dart';
-import '../builder/field_builder.dart';
 import '../builder/function_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/metadata_builder.dart';
 import '../builder/named_type_builder.dart';
+import '../builder/never_type_declaration_builder.dart';
 import '../builder/nullability_builder.dart';
-import '../builder/procedure_builder.dart';
 import '../builder/type_alias_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
-
+import '../builder/void_type_declaration_builder.dart';
 import '../dill/dill_member_builder.dart';
-
 import '../fasta_codes.dart';
-
 import '../kernel/combined_member_signature.dart';
+import '../kernel/hierarchy/hierarchy_builder.dart';
+import '../kernel/kernel_helper.dart';
 import '../kernel/kernel_target.dart' show KernelTarget;
-import '../kernel/redirecting_factory_body.dart' show redirectingName;
+import '../kernel/redirecting_factory_body.dart'
+    show RedirectingFactoryBody, redirectingName;
 import '../kernel/type_algorithms.dart' show computeTypeVariableBuilderVariance;
 import '../kernel/utils.dart' show compareProcedures;
-
 import '../names.dart' show equalsName, noSuchMethodName;
-
 import '../problems.dart' show unexpected, unhandled, unimplemented;
-
 import '../scope.dart';
-
 import '../type_inference/type_schema.dart';
-
+import '../util/helpers.dart';
+import 'source_constructor_builder.dart';
+import 'source_factory_builder.dart';
+import 'source_field_builder.dart';
 import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
 
 Class initializeClass(
     Class? cls,
@@ -88,7 +89,6 @@
 
 class SourceClassBuilder extends ClassBuilderImpl
     implements Comparable<SourceClassBuilder> {
-  @override
   final Class actualCls;
 
   final List<ConstructorReferenceBuilder>? constructorReferences;
@@ -103,6 +103,8 @@
   @override
   final bool isMacro;
 
+  SourceClassBuilder? _patchBuilder;
+
   SourceClassBuilder(
       List<MetadataBuilder>? metadata,
       int modifiers,
@@ -130,6 +132,13 @@
     actualCls.hasConstConstructor = declaresConstConstructor;
   }
 
+  SourceClassBuilder? get patchForTesting => _patchBuilder;
+
+  SourceClassBuilder? actualOrigin;
+
+  @override
+  SourceClassBuilder get origin => actualOrigin ?? this;
+
   @override
   Class get cls => origin.actualCls;
 
@@ -156,8 +165,8 @@
                 charOffset,
                 fileUri);
           }
-        } else if (declaration is MemberBuilderImpl) {
-          MemberBuilderImpl memberBuilder = declaration;
+        } else if (declaration is SourceMemberBuilder) {
+          SourceMemberBuilder memberBuilder = declaration;
           memberBuilder.buildMembers(library,
               (Member member, BuiltMemberKind memberKind) {
             member.parent = cls;
@@ -189,7 +198,7 @@
     scope.forEach(buildBuilders);
     constructors.forEach(buildBuilders);
     if (supertypeBuilder != null) {
-      supertypeBuilder = checkSupertype(supertypeBuilder!);
+      supertypeBuilder = _checkSupertype(supertypeBuilder!);
     }
     Supertype? supertype =
         supertypeBuilder?.buildSupertype(library, charOffset, fileUri);
@@ -223,7 +232,7 @@
     actualCls.supertype = supertype;
 
     if (mixedInTypeBuilder != null) {
-      mixedInTypeBuilder = checkSupertype(mixedInTypeBuilder!);
+      mixedInTypeBuilder = _checkSupertype(mixedInTypeBuilder!);
     }
     Supertype? mixedInType =
         mixedInTypeBuilder?.buildMixedInType(library, charOffset, fileUri);
@@ -246,7 +255,7 @@
     cls.isMacro = isMacro;
     if (interfaceBuilders != null) {
       for (int i = 0; i < interfaceBuilders!.length; ++i) {
-        interfaceBuilders![i] = checkSupertype(interfaceBuilders![i]);
+        interfaceBuilders![i] = _checkSupertype(interfaceBuilders![i]);
         Supertype? supertype =
             interfaceBuilders![i].buildSupertype(library, charOffset, fileUri);
         if (supertype != null) {
@@ -315,7 +324,688 @@
     return false;
   }
 
-  TypeBuilder checkSupertype(TypeBuilder supertype) {
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    void build(String ignore, Builder declaration) {
+      SourceMemberBuilder member = declaration as SourceMemberBuilder;
+      member.buildOutlineExpressions(library, classHierarchy,
+          delayedActionPerformers, synthesizedFunctionNodes);
+    }
+
+    MetadataBuilder.buildAnnotations(isPatch ? origin.cls : cls, metadata,
+        library, this, null, fileUri, library.scope);
+    if (typeVariables != null) {
+      for (int i = 0; i < typeVariables!.length; i++) {
+        typeVariables![i].buildOutlineExpressions(library, this, null,
+            classHierarchy, delayedActionPerformers, scope.parent!);
+      }
+    }
+
+    constructors.forEach(build);
+    scope.forEach(build);
+  }
+
+  @override
+  void forEachConstructor(void Function(String, MemberBuilder) f,
+      {bool includeInjectedConstructors: false}) {
+    if (isPatch) {
+      actualOrigin!.forEachConstructor(f,
+          includeInjectedConstructors: includeInjectedConstructors);
+    } else {
+      constructors.forEach(f);
+      if (includeInjectedConstructors) {
+        _patchBuilder?.constructors
+            .forEach((String name, MemberBuilder builder) {
+          if (!builder.isPatch) {
+            f(name, builder);
+          }
+        });
+      }
+    }
+  }
+
+  void forEachDeclaredField(
+      void Function(String name, SourceFieldBuilder fieldBuilder) callback) {
+    void callbackFilteringFieldBuilders(String name, Builder builder) {
+      if (builder is SourceFieldBuilder) {
+        callback(name, builder);
+      }
+    }
+
+    // Currently, fields can't be patched, but can be injected.  When the fields
+    // will be made available for patching, the following code should iterate
+    // first over the fields from the patch and then -- over the fields in the
+    // original declaration, filtering out the patched fields.  For now, the
+    // assert checks that the names of the fields from the original declaration
+    // and from the patch don't intersect.
+    assert(
+        _patchBuilder == null ||
+            _patchBuilder!.scope.localMembers
+                .where((b) => b is SourceFieldBuilder)
+                .map((b) => (b as SourceFieldBuilder).name)
+                .toSet()
+                .intersection(scope.localMembers
+                    .where((b) => b is SourceFieldBuilder)
+                    .map((b) => (b as SourceFieldBuilder).name)
+                    .toSet())
+                .isEmpty,
+        "Detected an attempt to patch a field.");
+    _patchBuilder?.scope.forEach(callbackFilteringFieldBuilders);
+    scope.forEach(callbackFilteringFieldBuilders);
+  }
+
+  void forEachDeclaredConstructor(
+      void Function(
+              String name, DeclaredSourceConstructorBuilder constructorBuilder)
+          callback) {
+    Set<String> visitedConstructorNames = {};
+    void callbackFilteringFieldBuilders(String name, Builder builder) {
+      if (builder is DeclaredSourceConstructorBuilder &&
+          visitedConstructorNames.add(builder.name)) {
+        callback(name, builder);
+      }
+    }
+
+    // Constructors can be patched, so iterate first over constructors in the
+    // patch, and then over constructors in the original declaration skipping
+    // those with the names that are in the patch.
+    _patchBuilder?.constructors.forEach(callbackFilteringFieldBuilders);
+    constructors.forEach(callbackFilteringFieldBuilders);
+  }
+
+  /// Looks up the constructor by [name] on the class built by this class
+  /// builder.
+  ///
+  /// If [isSuper] is `true`, constructors in the superclass are searched.
+  Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
+    if (name.text == "new") {
+      name = new Name("", name.library);
+    }
+
+    Class? instanceClass = cls;
+    if (isSuper) {
+      instanceClass = instanceClass.superclass;
+    }
+    if (instanceClass != null) {
+      for (Constructor constructor in instanceClass.constructors) {
+        if (constructor.name == name) {
+          return constructor;
+        }
+      }
+    }
+
+    /// Performs a similar lookup to [lookupConstructor], but using a slower
+    /// implementation.
+    Constructor? lookupConstructorWithPatches(Name name, bool isSuper) {
+      ClassBuilder? builder = this.origin;
+
+      ClassBuilder? getSuperclass(ClassBuilder builder) {
+        // This way of computing the superclass is slower than using the kernel
+        // objects directly.
+        TypeBuilder? supertype = builder.supertypeBuilder;
+        if (supertype is NamedTypeBuilder) {
+          TypeDeclarationBuilder? builder = supertype.declaration;
+          if (builder is ClassBuilder) return builder;
+          if (builder is TypeAliasBuilder) {
+            TypeDeclarationBuilder? declarationBuilder =
+                builder.unaliasDeclaration(supertype.arguments,
+                    isUsedAsClass: true,
+                    usedAsClassCharOffset: supertype.charOffset,
+                    usedAsClassFileUri: supertype.fileUri);
+            if (declarationBuilder is ClassBuilder) return declarationBuilder;
+          }
+        }
+        return null;
+      }
+
+      if (isSuper) {
+        builder = getSuperclass(builder)?.origin;
+      }
+      if (builder != null) {
+        Class cls = builder.cls;
+        for (Constructor constructor in cls.constructors) {
+          if (constructor.name == name) return constructor;
+        }
+      }
+      return null;
+    }
+
+    return lookupConstructorWithPatches(name, isSuper);
+  }
+
+  @override
+  int get typeVariablesCount => typeVariables?.length ?? 0;
+
+  @override
+  List<DartType> buildTypeArguments(
+      LibraryBuilder library, List<TypeBuilder>? arguments) {
+    if (arguments == null && typeVariables == null) {
+      return <DartType>[];
+    }
+
+    if (arguments == null && typeVariables != null) {
+      List<DartType> result = new List<DartType>.generate(typeVariables!.length,
+          (int i) => typeVariables![i].defaultType!.build(library),
+          growable: true);
+      if (library is SourceLibraryBuilder) {
+        library.inferredTypes.addAll(result);
+      }
+      return result;
+    }
+
+    if (arguments != null && arguments.length != typeVariablesCount) {
+      // That should be caught and reported as a compile-time error earlier.
+      return unhandled(
+          templateTypeArgumentMismatch
+              .withArguments(typeVariablesCount)
+              .problemMessage,
+          "buildTypeArguments",
+          -1,
+          null);
+    }
+
+    assert(arguments!.length == typeVariablesCount);
+    List<DartType> result = new List<DartType>.generate(
+        arguments!.length, (int i) => arguments[i].build(library),
+        growable: true);
+    return result;
+  }
+
+  /// Returns a map which maps the type variables of [superclass] to their
+  /// respective values as defined by the superclass clause of this class (and
+  /// its superclasses).
+  ///
+  /// It's assumed that [superclass] is a superclass of this class.
+  ///
+  /// For example, given:
+  ///
+  ///     class Box<T> {}
+  ///     class BeatBox extends Box<Beat> {}
+  ///     class Beat {}
+  ///
+  /// We have:
+  ///
+  ///     [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
+  ///
+  /// It's an error if [superclass] isn't a superclass.
+  Map<TypeParameter, DartType> getSubstitutionMap(Class superclass) {
+    Supertype? supertype = cls.supertype;
+    Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
+    List<DartType> arguments;
+    List<TypeParameter> variables;
+    Class? classNode;
+
+    while (classNode != superclass) {
+      classNode = supertype!.classNode;
+      arguments = supertype.typeArguments;
+      variables = classNode.typeParameters;
+      supertype = classNode.supertype;
+      if (variables.isNotEmpty) {
+        Map<TypeParameter, DartType> directSubstitutionMap =
+            <TypeParameter, DartType>{};
+        for (int i = 0; i < variables.length; i++) {
+          DartType argument =
+              i < arguments.length ? arguments[i] : const DynamicType();
+          // ignore: unnecessary_null_comparison
+          if (substitutionMap != null) {
+            // TODO(ahe): Investigate if requiring the caller to use
+            // `substituteDeep` from `package:kernel/type_algebra.dart` instead
+            // of `substitute` is faster. If so, we can simply this code.
+            argument = substitute(argument, substitutionMap);
+          }
+          directSubstitutionMap[variables[i]] = argument;
+        }
+        substitutionMap = directSubstitutionMap;
+      }
+    }
+
+    return substitutionMap;
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is SourceClassBuilder) {
+      patch.actualOrigin = this;
+      _patchBuilder = patch;
+      // TODO(ahe): Complain if `patch.supertype` isn't null.
+      scope.forEachLocalMember((String name, Builder member) {
+        Builder? memberPatch =
+            patch.scope.lookupLocalMember(name, setter: false);
+        if (memberPatch != null) {
+          member.applyPatch(memberPatch);
+        }
+      });
+      scope.forEachLocalSetter((String name, Builder member) {
+        Builder? memberPatch =
+            patch.scope.lookupLocalMember(name, setter: true);
+        if (memberPatch != null) {
+          member.applyPatch(memberPatch);
+        }
+      });
+      constructors.local.forEach((String name, Builder member) {
+        Builder? memberPatch = patch.constructors.local[name];
+        if (memberPatch != null) {
+          member.applyPatch(memberPatch);
+        }
+      });
+
+      int originLength = typeVariables?.length ?? 0;
+      int patchLength = patch.typeVariables?.length ?? 0;
+      if (originLength != patchLength) {
+        patch.addProblem(messagePatchClassTypeVariablesMismatch,
+            patch.charOffset, noLength, context: [
+          messagePatchClassOrigin.withLocation(fileUri, charOffset, noLength)
+        ]);
+      } else if (typeVariables != null) {
+        int count = 0;
+        for (TypeVariableBuilder t in patch.typeVariables!) {
+          typeVariables![count++].applyPatch(t);
+        }
+      }
+    } else {
+      library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
+          noLength, patch.fileUri, context: [
+        messagePatchDeclarationOrigin.withLocation(
+            fileUri, charOffset, noLength)
+      ]);
+    }
+  }
+
+  void checkSupertypes(CoreTypes coreTypes,
+      ClassHierarchyBuilder hierarchyBuilder, Class enumClass) {
+    // This method determines whether the class (that's being built) its super
+    // class appears both in 'extends' and 'implements' clauses and whether any
+    // interface appears multiple times in the 'implements' clause.
+    // Moreover, it checks that `FutureOr` and `void` are not among the
+    // supertypes and that `Enum` is not implemented by non-abstract classes.
+
+    if (!cls.isAbstract && !cls.isEnum) {
+      bool isEnumFound = false;
+      List<Supertype> interfaces =
+          hierarchyBuilder.getNodeFromClass(cls).superclasses;
+      for (int i = 0; !isEnumFound && i < interfaces.length; i++) {
+        if (interfaces[i].classNode == enumClass) {
+          isEnumFound = true;
+        }
+      }
+      interfaces = hierarchyBuilder.getNodeFromClass(cls).interfaces;
+      for (int i = 0; !isEnumFound && i < interfaces.length; i++) {
+        if (interfaces[i].classNode == enumClass) {
+          isEnumFound = true;
+        }
+      }
+      if (isEnumFound) {
+        addProblem(templateEnumSupertypeOfNonAbstractClass.withArguments(name),
+            charOffset, noLength);
+      }
+    }
+
+    void fail(NamedTypeBuilder target, Message message,
+        TypeAliasBuilder? aliasBuilder) {
+      int nameOffset = target.nameOffset;
+      int nameLength = target.nameLength;
+      // TODO(eernst): nameOffset not fully implemented; use backup.
+      if (nameOffset == -1) {
+        nameOffset = this.charOffset;
+        nameLength = noLength;
+      }
+      if (aliasBuilder != null) {
+        addProblem(message, nameOffset, nameLength, context: [
+          messageTypedefCause.withLocation(
+              aliasBuilder.fileUri, aliasBuilder.charOffset, noLength),
+        ]);
+      } else {
+        addProblem(message, nameOffset, nameLength);
+      }
+    }
+
+    // Extract and check superclass (if it exists).
+    ClassBuilder? superClass;
+    TypeBuilder? superClassType = supertypeBuilder;
+    if (superClassType is NamedTypeBuilder) {
+      TypeDeclarationBuilder? decl = superClassType.declaration;
+      TypeAliasBuilder? aliasBuilder; // Non-null if a type alias is use.
+      if (decl is TypeAliasBuilder) {
+        aliasBuilder = decl;
+        decl = aliasBuilder.unaliasDeclaration(superClassType.arguments,
+            isUsedAsClass: true,
+            usedAsClassCharOffset: superClassType.charOffset,
+            usedAsClassFileUri: superClassType.fileUri);
+      }
+      // TODO(eernst): Should gather 'restricted supertype' checks in one place,
+      // e.g., dynamic/int/String/Null and more are checked elsewhere.
+      if (decl is VoidTypeDeclarationBuilder) {
+        fail(superClassType, messageExtendsVoid, aliasBuilder);
+      } else if (decl is NeverTypeDeclarationBuilder) {
+        fail(superClassType, messageExtendsNever, aliasBuilder);
+      } else if (decl is ClassBuilder) {
+        superClass = decl;
+      }
+    }
+    if (interfaceBuilders == null) return;
+
+    // Validate interfaces.
+    Map<ClassBuilder, int>? problems;
+    Map<ClassBuilder, int>? problemsOffsets;
+    Set<ClassBuilder> implemented = new Set<ClassBuilder>();
+    for (TypeBuilder type in interfaceBuilders!) {
+      if (type is NamedTypeBuilder) {
+        int? charOffset = type.charOffset;
+        TypeDeclarationBuilder? typeDeclaration = type.declaration;
+        TypeDeclarationBuilder? decl;
+        TypeAliasBuilder? aliasBuilder; // Non-null if a type alias is used.
+        if (typeDeclaration is TypeAliasBuilder) {
+          aliasBuilder = typeDeclaration;
+          decl = aliasBuilder.unaliasDeclaration(type.arguments,
+              isUsedAsClass: true,
+              usedAsClassCharOffset: type.charOffset,
+              usedAsClassFileUri: type.fileUri);
+        } else {
+          decl = typeDeclaration;
+        }
+        if (decl is ClassBuilder) {
+          ClassBuilder interface = decl;
+          if (superClass == interface) {
+            addProblem(
+                templateImplementsSuperClass.withArguments(interface.name),
+                this.charOffset,
+                noLength);
+          } else if (interface.cls.name == "FutureOr" &&
+              interface.cls.enclosingLibrary.importUri.scheme == "dart" &&
+              interface.cls.enclosingLibrary.importUri.path == "async") {
+            addProblem(messageImplementsFutureOr, this.charOffset, noLength);
+          } else if (implemented.contains(interface)) {
+            // Aggregate repetitions.
+            problems ??= <ClassBuilder, int>{};
+            problems[interface] ??= 0;
+            problems[interface] = problems[interface]! + 1;
+            problemsOffsets ??= <ClassBuilder, int>{};
+            problemsOffsets[interface] ??= charOffset ?? TreeNode.noOffset;
+          } else {
+            implemented.add(interface);
+          }
+        }
+        if (decl != superClass) {
+          // TODO(eernst): Have all 'restricted supertype' checks in one place.
+          if (decl is VoidTypeDeclarationBuilder) {
+            fail(type, messageImplementsVoid, aliasBuilder);
+          } else if (decl is NeverTypeDeclarationBuilder) {
+            fail(type, messageImplementsNever, aliasBuilder);
+          }
+        }
+      }
+    }
+    if (problems != null) {
+      problems.forEach((ClassBuilder interface, int repetitions) {
+        addProblem(
+            templateImplementsRepeated.withArguments(
+                interface.name, repetitions),
+            problemsOffsets![interface]!,
+            noLength);
+      });
+    }
+  }
+
+  void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes) {
+    TypeEnvironment typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
+    // A mixin declaration can only be applied to a class that implements all
+    // the declaration's superclass constraints.
+    InterfaceType supertype = cls.supertype!.asInterfaceType;
+    Substitution substitution = Substitution.fromSupertype(cls.mixedInType!);
+    for (Supertype constraint in cls.mixedInClass!.superclassConstraints()) {
+      InterfaceType requiredInterface =
+          substitution.substituteSupertype(constraint).asInterfaceType;
+      InterfaceType? implementedInterface = hierarchy.getTypeAsInstanceOf(
+          supertype, requiredInterface.classNode, library.library);
+      if (implementedInterface == null ||
+          !typeEnvironment.areMutualSubtypes(
+              implementedInterface,
+              requiredInterface,
+              library.isNonNullableByDefault
+                  ? SubtypeCheckMode.withNullabilities
+                  : SubtypeCheckMode.ignoringNullabilities)) {
+        library.addProblem(
+            templateMixinApplicationIncompatibleSupertype.withArguments(
+                supertype,
+                requiredInterface,
+                cls.mixedInType!.asInterfaceType,
+                library.isNonNullableByDefault),
+            cls.fileOffset,
+            noLength,
+            cls.fileUri);
+      }
+    }
+  }
+
+  // Computes the function type of a given redirection target. Returns [null] if
+  // the type of the target could not be computed.
+  FunctionType? _computeRedirecteeType(
+      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment) {
+    ConstructorReferenceBuilder redirectionTarget = factory.redirectionTarget;
+    Builder? targetBuilder = redirectionTarget.target;
+    FunctionNode targetNode;
+    if (targetBuilder == null) return null;
+    if (targetBuilder is FunctionBuilder) {
+      targetNode = targetBuilder.function;
+    } else if (targetBuilder is AmbiguousBuilder) {
+      // Multiple definitions with the same name: An error has already been
+      // issued.
+      // TODO(http://dartbug.com/35294): Unfortunate error; see also
+      // https://dart-review.googlesource.com/c/sdk/+/85390/.
+      return null;
+    } else {
+      unhandled("${redirectionTarget.target}", "computeRedirecteeType",
+          charOffset, fileUri);
+    }
+
+    List<DartType>? typeArguments = factory.getTypeArguments();
+    FunctionType targetFunctionType =
+        targetNode.computeFunctionType(library.nonNullable);
+    if (typeArguments != null &&
+        targetFunctionType.typeParameters.length != typeArguments.length) {
+      _addProblemForRedirectingFactory(
+          factory,
+          templateTypeArgumentMismatch
+              .withArguments(targetFunctionType.typeParameters.length),
+          redirectionTarget.charOffset,
+          noLength);
+      return null;
+    }
+
+    // Compute the substitution of the target class type parameters if
+    // [redirectionTarget] has any type arguments.
+    Substitution? substitution;
+    bool hasProblem = false;
+    if (typeArguments != null && typeArguments.length > 0) {
+      substitution = Substitution.fromPairs(
+          targetFunctionType.typeParameters, typeArguments);
+      for (int i = 0; i < targetFunctionType.typeParameters.length; i++) {
+        TypeParameter typeParameter = targetFunctionType.typeParameters[i];
+        DartType typeParameterBound =
+            substitution.substituteType(typeParameter.bound);
+        DartType typeArgument = typeArguments[i];
+        // Check whether the [typeArgument] respects the bounds of
+        // [typeParameter].
+        if (!typeEnvironment.isSubtypeOf(typeArgument, typeParameterBound,
+            SubtypeCheckMode.ignoringNullabilities)) {
+          _addProblemForRedirectingFactory(
+              factory,
+              templateRedirectingFactoryIncompatibleTypeArgument.withArguments(
+                  typeArgument,
+                  typeParameterBound,
+                  library.isNonNullableByDefault),
+              redirectionTarget.charOffset,
+              noLength);
+          hasProblem = true;
+        } else if (library.isNonNullableByDefault) {
+          if (!typeEnvironment.isSubtypeOf(typeArgument, typeParameterBound,
+              SubtypeCheckMode.withNullabilities)) {
+            _addProblemForRedirectingFactory(
+                factory,
+                templateRedirectingFactoryIncompatibleTypeArgument
+                    .withArguments(typeArgument, typeParameterBound,
+                        library.isNonNullableByDefault),
+                redirectionTarget.charOffset,
+                noLength);
+            hasProblem = true;
+          }
+        }
+      }
+    } else if (typeArguments == null &&
+        targetFunctionType.typeParameters.length > 0) {
+      // TODO(hillerstrom): In this case, we need to perform type inference on
+      // the redirectee to obtain actual type arguments which would allow the
+      // following program to type check:
+      //
+      //    class A<T> {
+      //       factory A() = B;
+      //    }
+      //    class B<T> implements A<T> {
+      //       B();
+      //    }
+      //
+      return null;
+    }
+
+    // Substitute if necessary.
+    targetFunctionType = substitution == null
+        ? targetFunctionType
+        : (substitution.substituteType(targetFunctionType.withoutTypeParameters)
+            as FunctionType);
+
+    return hasProblem ? null : targetFunctionType;
+  }
+
+  bool _isCyclicRedirectingFactory(RedirectingFactoryBuilder factory) {
+    // We use the [tortoise and hare algorithm]
+    // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
+    // handle cycles.
+    Builder? tortoise = factory;
+    Builder? hare = factory.redirectionTarget.target;
+    if (hare == factory) {
+      return true;
+    }
+    while (tortoise != hare) {
+      // Hare moves 2 steps forward.
+      if (hare is! RedirectingFactoryBuilder) {
+        return false;
+      }
+      hare = hare.redirectionTarget.target;
+      if (hare == factory) {
+        return true;
+      }
+      if (hare is! RedirectingFactoryBuilder) {
+        return false;
+      }
+      hare = hare.redirectionTarget.target;
+      if (hare == factory) {
+        return true;
+      }
+      // Tortoise moves one step forward. No need to test type of tortoise
+      // as it follows hare which already checked types.
+      tortoise =
+          (tortoise as RedirectingFactoryBuilder).redirectionTarget.target;
+    }
+    // Cycle found, but original factory doesn't belong to a cycle.
+    return false;
+  }
+
+  void _addProblemForRedirectingFactory(RedirectingFactoryBuilder factory,
+      Message message, int charOffset, int length) {
+    addProblem(message, charOffset, length);
+    String text = library.loader.target.context
+        .format(
+            message.withLocation(fileUri, charOffset, length), Severity.error)
+        .plain;
+    factory.body = new RedirectingFactoryBody.error(text);
+  }
+
+  void _checkRedirectingFactory(
+      RedirectingFactoryBuilder factory, TypeEnvironment typeEnvironment) {
+    // Check that factory declaration is not cyclic.
+    if (_isCyclicRedirectingFactory(factory)) {
+      _addProblemForRedirectingFactory(
+          factory,
+          templateCyclicRedirectingFactoryConstructors
+              .withArguments("${factory.member.enclosingClass!.name}"
+                  "${factory.name == '' ? '' : '.${factory.name}'}"),
+          factory.charOffset,
+          noLength);
+      return;
+    }
+
+    // The factory type cannot contain any type parameters other than those of
+    // its enclosing class, because constructors cannot specify type parameters
+    // of their own.
+    FunctionType factoryType = factory.function
+        .computeThisFunctionType(library.nonNullable)
+        .withoutTypeParameters;
+    FunctionType? redirecteeType =
+        _computeRedirecteeType(factory, typeEnvironment);
+
+    // TODO(hillerstrom): It would be preferable to know whether a failure
+    // happened during [_computeRedirecteeType].
+    if (redirecteeType == null) {
+      return;
+    }
+
+    // Check whether [redirecteeType] <: [factoryType].
+    if (!typeEnvironment.isSubtypeOf(
+        redirecteeType, factoryType, SubtypeCheckMode.ignoringNullabilities)) {
+      _addProblemForRedirectingFactory(
+          factory,
+          templateIncompatibleRedirecteeFunctionType.withArguments(
+              redirecteeType, factoryType, library.isNonNullableByDefault),
+          factory.redirectionTarget.charOffset,
+          noLength);
+    } else if (library.isNonNullableByDefault) {
+      if (!typeEnvironment.isSubtypeOf(
+          redirecteeType, factoryType, SubtypeCheckMode.withNullabilities)) {
+        _addProblemForRedirectingFactory(
+            factory,
+            templateIncompatibleRedirecteeFunctionType.withArguments(
+                redirecteeType, factoryType, library.isNonNullableByDefault),
+            factory.redirectionTarget.charOffset,
+            noLength);
+      }
+    }
+  }
+
+  void checkRedirectingFactories(TypeEnvironment typeEnvironment) {
+    Map<String, MemberBuilder> constructors = this.constructors.local;
+    for (Builder? constructor in constructors.values) {
+      do {
+        if (constructor is RedirectingFactoryBuilder) {
+          _checkRedirectingFactory(constructor, typeEnvironment);
+        }
+        constructor = constructor!.next;
+      } while (constructor != null);
+    }
+  }
+
+  Map<String, ConstructorRedirection>? _redirectingConstructors;
+
+  /// Registers a constructor redirection for this class and returns true if
+  /// this redirection gives rise to a cycle that has not been reported before.
+  bool checkConstructorCyclic(String source, String target) {
+    ConstructorRedirection? redirect = new ConstructorRedirection(target);
+    _redirectingConstructors ??= <String, ConstructorRedirection>{};
+    _redirectingConstructors![source] = redirect;
+    while (redirect != null) {
+      if (redirect.cycleReported) return false;
+      if (redirect.target == source) {
+        redirect.cycleReported = true;
+        return true;
+      }
+      redirect = _redirectingConstructors![redirect.target];
+    }
+    return false;
+  }
+
+  TypeBuilder _checkSupertype(TypeBuilder supertype) {
     if (typeVariables == null) return supertype;
     Message? message;
     for (int i = 0; i < typeVariables!.length; ++i) {
@@ -550,19 +1240,21 @@
         // Check fields.
         checkVarianceInField(builder, typeEnvironment, cls.typeParameters);
         library.checkTypesInField(builder, typeEnvironment);
-      } else if (builder is ProcedureBuilder) {
+      } else if (builder is SourceProcedureBuilder) {
         // Check procedures
         checkVarianceInFunction(
             builder.procedure, typeEnvironment, cls.typeParameters);
         library.checkTypesInFunctionBuilder(builder, typeEnvironment);
       } else {
-        assert(builder is DillFieldBuilder && builder.name == redirectingName,
+        assert(
+            builder is _RedirectingConstructorsFieldBuilder &&
+                builder.name == redirectingName,
             "Unexpected member: $builder.");
       }
     });
 
     forEachConstructor((String name, MemberBuilder builder) {
-      if (builder is ConstructorBuilder) {
+      if (builder is DeclaredSourceConstructorBuilder) {
         library.checkTypesInConstructorBuilder(builder, typeEnvironment);
       } else if (builder is RedirectingFactoryBuilder) {
         library.checkTypesInRedirectingFactoryBuilder(builder, typeEnvironment);
@@ -572,13 +1264,14 @@
       } else {
         assert(
             // This is a synthesized constructor.
-            builder is DillConstructorBuilder,
+            builder is SyntheticSourceConstructorBuilder,
             "Unexpected constructor: $builder.");
       }
     }, includeInjectedConstructors: true);
   }
 
-  void addSyntheticConstructor(SyntheticConstructorBuilder constructorBuilder) {
+  void addSyntheticConstructor(
+      SyntheticSourceConstructorBuilder constructorBuilder) {
     String name = constructorBuilder.name;
     constructorBuilder.next = constructorScopeBuilder[name];
     constructorScopeBuilder.addMember(name, constructorBuilder);
@@ -683,6 +1376,12 @@
     return charOffset.compareTo(other.charOffset);
   }
 
+  bool _hasUserDefinedNoSuchMethod(
+      Class klass, ClassHierarchy hierarchy, Class objectClass) {
+    Member? noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
+    return noSuchMethod != null && noSuchMethod.enclosingClass != objectClass;
+  }
+
   bool _addMissingNoSuchMethodForwarders(
       KernelTarget target, Set<Member> existingForwarders,
       {required bool forSetters}) {
@@ -701,7 +1400,7 @@
     Procedure noSuchMethod = ClassHierarchy.findMemberByName(
         hierarchy.getInterfaceMembers(cls), noSuchMethodName) as Procedure;
     bool clsHasUserDefinedNoSuchMethod =
-        hasUserDefinedNoSuchMethod(cls, hierarchy, target.objectClass);
+        _hasUserDefinedNoSuchMethod(cls, hierarchy, target.objectClass);
 
     bool changed = false;
 
@@ -771,7 +1470,7 @@
         nearestConcreteSuperclass = nearestConcreteSuperclass.superclass;
       }
       if (nearestConcreteSuperclass != null) {
-        bool superHasUserDefinedNoSuchMethod = hasUserDefinedNoSuchMethod(
+        bool superHasUserDefinedNoSuchMethod = _hasUserDefinedNoSuchMethod(
             nearestConcreteSuperclass, hierarchy, target.objectClass);
         {
           List<Member> concrete =
@@ -894,8 +1593,9 @@
     // [constructor.target].
     //
     // TODO(ahe): Add a kernel node to represent redirecting factory bodies.
-    DillFieldBuilder? constructorsField = origin.scope
-        .lookupLocalMember(redirectingName, setter: false) as DillFieldBuilder?;
+    _RedirectingConstructorsFieldBuilder? constructorsField =
+        origin.scope.lookupLocalMember(redirectingName, setter: false)
+            as _RedirectingConstructorsFieldBuilder?;
     if (constructorsField == null) {
       ListLiteral literal = new ListLiteral(<Expression>[]);
       Name name = new Name(redirectingName, library.library);
@@ -908,7 +1608,7 @@
           getterReference: getterReference)
         ..fileOffset = cls.fileOffset;
       cls.addField(field);
-      constructorsField = new DillFieldBuilder(field, this);
+      constructorsField = new _RedirectingConstructorsFieldBuilder(field, this);
       origin.scope
           .addLocalMember(redirectingName, constructorsField, setter: false);
     }
@@ -965,14 +1665,14 @@
               } else if (targetBuilder is DillMemberBuilder) {
                 targetNode = targetBuilder.member;
               } else if (targetBuilder is AmbiguousBuilder) {
-                addProblemForRedirectingFactory(
+                _addProblemForRedirectingFactory(
                     declaration,
                     templateDuplicatedDeclarationUse
                         .withArguments(redirectionTarget.fullNameForErrors),
                     redirectionTarget.charOffset,
                     noLength);
               } else {
-                addProblemForRedirectingFactory(
+                _addProblemForRedirectingFactory(
                     declaration,
                     templateRedirectionTargetNotFound
                         .withArguments(redirectionTarget.fullNameForErrors),
@@ -982,7 +1682,7 @@
               if (targetNode != null &&
                   targetNode is Constructor &&
                   targetNode.enclosingClass.isAbstract) {
-                addProblemForRedirectingFactory(
+                _addProblemForRedirectingFactory(
                     declaration,
                     templateAbstractRedirectedClassInstantiation
                         .withArguments(redirectionTarget.fullNameForErrors),
@@ -1007,6 +1707,23 @@
     return count;
   }
 
+  void _handleSeenCovariant(
+      ClassHierarchyMembers memberHierarchy,
+      Member interfaceMember,
+      bool isSetter,
+      callback(Member interfaceMember, bool isSetter)) {
+    // When a parameter is covariant we have to check that we also
+    // override the same member in all parents.
+    for (Supertype supertype in interfaceMember.enclosingClass!.supers) {
+      Member? member = memberHierarchy.getInterfaceMember(
+          supertype.classNode, interfaceMember.name,
+          setter: isSetter);
+      if (member != null) {
+        callback(member, isSetter);
+      }
+    }
+  }
+
   void checkOverride(
       Types types,
       ClassHierarchyMembers memberHierarchy,
@@ -1041,7 +1758,7 @@
               isInterfaceCheck,
               declaredNeedsLegacyErasure);
           if (seenCovariant) {
-            handleSeenCovariant(
+            _handleSeenCovariant(
                 memberHierarchy, interfaceMember, isSetter, callback);
           }
         } else if (declaredMember.kind == ProcedureKind.Getter) {
@@ -1061,7 +1778,7 @@
               isInterfaceCheck,
               declaredNeedsLegacyErasure);
           if (seenCovariant) {
-            handleSeenCovariant(
+            _handleSeenCovariant(
                 memberHierarchy, interfaceMember, isSetter, callback);
           }
         } else {
@@ -1102,7 +1819,7 @@
             isInterfaceCheck,
             declaredNeedsLegacyErasure);
         if (seenCovariant) {
-          handleSeenCovariant(
+          _handleSeenCovariant(
               memberHierarchy, interfaceMember, isSetter, callback);
         }
       }
@@ -1657,10 +2374,10 @@
     }
 
     List<VariableDeclaration> sortedFromDeclared =
-        new List.from(declaredFunction.namedParameters)
+        new List.of(declaredFunction.namedParameters)
           ..sort(compareNamedParameters);
     List<VariableDeclaration> sortedFromInterface =
-        new List.from(interfaceFunction.namedParameters)
+        new List.of(interfaceFunction.namedParameters)
           ..sort(compareNamedParameters);
     Iterator<VariableDeclaration> declaredNamedParameters =
         sortedFromDeclared.iterator;
@@ -1911,3 +2628,18 @@
   }
   return null;
 }
+
+class _RedirectingConstructorsFieldBuilder extends DillFieldBuilder
+    with SourceMemberBuilderMixin {
+  _RedirectingConstructorsFieldBuilder(Field field, SourceClassBuilder parent)
+      : super(field, parent);
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    // Do nothing.
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
new file mode 100644
index 0000000..8f7cfc8
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -0,0 +1,763 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/constructor_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/type_alias_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_declaration_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../constant_context.dart' show ConstantContext;
+import '../dill/dill_member_builder.dart';
+import '../kernel/body_builder.dart' show BodyBuilder;
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/expression_generator_helper.dart'
+    show ExpressionGeneratorHelper;
+import '../kernel/hierarchy/class_member.dart' show ClassMember;
+import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
+import '../kernel/utils.dart'
+    show isRedirectingGenerativeConstructorImplementation;
+import '../messages.dart'
+    show
+        Message,
+        messageMoreThanOneSuperInitializer,
+        messageRedirectingConstructorWithAnotherInitializer,
+        messageRedirectingConstructorWithMultipleRedirectInitializers,
+        messageRedirectingConstructorWithSuperInitializer,
+        messageSuperInitializerNotLast,
+        noLength;
+import '../scope.dart';
+import '../source/source_class_builder.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import '../source/source_member_builder.dart';
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_field_builder.dart';
+import 'source_function_builder.dart';
+
+abstract class SourceConstructorBuilder
+    implements ConstructorBuilder, SourceMemberBuilder {}
+
+class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
+    implements SourceConstructorBuilder {
+  final Constructor _constructor;
+  final Procedure? _constructorTearOff;
+
+  Set<SourceFieldBuilder>? _initializedFields;
+
+  final int charOpenParenOffset;
+
+  bool hasMovedSuperInitializer = false;
+
+  SuperInitializer? superInitializer;
+
+  RedirectingInitializer? redirectingInitializer;
+
+  Token? beginInitializers;
+
+  DeclaredSourceConstructorBuilder? actualOrigin;
+
+  Constructor get actualConstructor => _constructor;
+
+  bool _hasFormalsInferred = false;
+
+  final bool _hasSuperInitializingFormals;
+
+  final List<SynthesizedFunctionNode> _superParameterDefaultValueCloners =
+      <SynthesizedFunctionNode>[];
+
+  @override
+  List<FormalParameterBuilder>? formals;
+
+  DeclaredSourceConstructorBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder? returnType,
+      String name,
+      List<TypeVariableBuilder>? typeVariables,
+      this.formals,
+      SourceLibraryBuilder compilationUnit,
+      int startCharOffset,
+      int charOffset,
+      this.charOpenParenOffset,
+      int charEndOffset,
+      Reference? constructorReference,
+      Reference? tearOffReference,
+      {String? nativeMethodName,
+      required bool forAbstractClassOrEnum})
+      : _constructor = new Constructor(new FunctionNode(null),
+            name: new Name(name, compilationUnit.library),
+            fileUri: compilationUnit.fileUri,
+            reference: constructorReference)
+          ..startFileOffset = startCharOffset
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
+        _constructorTearOff = createConstructorTearOffProcedure(
+            name,
+            compilationUnit,
+            compilationUnit.fileUri,
+            charOffset,
+            tearOffReference,
+            forAbstractClassOrEnum: forAbstractClassOrEnum),
+        _hasSuperInitializingFormals =
+            formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
+        super(metadata, modifiers, returnType, name, typeVariables, formals,
+            compilationUnit, charOffset, nativeMethodName);
+
+  @override
+  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+  @override
+  SourceClassBuilder get classBuilder =>
+      super.classBuilder as SourceClassBuilder;
+
+  @override
+  Member? get readTarget => _constructorTearOff ?? _constructor;
+
+  @override
+  Member? get writeTarget => null;
+
+  @override
+  Member get invokeTarget => constructor;
+
+  @override
+  FunctionNode get function => _constructor.function;
+
+  @override
+  Iterable<Member> get exportedMembers => [constructor];
+
+  @override
+  DeclaredSourceConstructorBuilder get origin => actualOrigin ?? this;
+
+  ConstructorBuilder? get patchForTesting =>
+      dataForTesting?.patchForTesting as ConstructorBuilder?;
+
+  @override
+  bool get isDeclarationInstanceMember => false;
+
+  @override
+  bool get isClassInstanceMember => false;
+
+  @override
+  bool get isConstructor => true;
+
+  @override
+  AsyncMarker get asyncModifier => AsyncMarker.Sync;
+
+  @override
+  ProcedureKind? get kind => null;
+
+  @override
+  bool get isRedirectingGenerativeConstructor {
+    return isRedirectingGenerativeConstructorImplementation(_constructor);
+  }
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.Constructor);
+    if (_constructorTearOff != null) {
+      f(_constructorTearOff!, BuiltMemberKind.Method);
+    }
+  }
+
+  bool _hasBeenBuilt = false;
+
+  @override
+  Constructor build(SourceLibraryBuilder libraryBuilder) {
+    if (!_hasBeenBuilt) {
+      buildFunction(libraryBuilder);
+      _constructor.function.fileOffset = charOpenParenOffset;
+      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+      _constructor.function.typeParameters = const <TypeParameter>[];
+      _constructor.isConst = isConst;
+      _constructor.isExternal = isExternal;
+      updatePrivateMemberName(_constructor, libraryBuilder);
+
+      if (_constructorTearOff != null) {
+        buildConstructorTearOffProcedure(_constructorTearOff!, _constructor,
+            classBuilder.cls, libraryBuilder);
+      }
+
+      _hasBeenBuilt = true;
+    }
+    if (formals != null) {
+      bool needsInference = false;
+      for (FormalParameterBuilder formal in formals!) {
+        if (formal.type == null &&
+            (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+          formal.variable!.type = const UnknownType();
+          needsInference = true;
+        }
+      }
+      if (needsInference) {
+        assert(
+            library == libraryBuilder,
+            "Unexpected library builder ${libraryBuilder} for"
+            " constructor $this in ${library}.");
+        libraryBuilder.loader
+            .registerConstructorToBeInferred(_constructor, this);
+      }
+    }
+    return _constructor;
+  }
+
+  /// Infers the types of any untyped initializing formals.
+  void inferFormalTypes(ClassHierarchy classHierarchy) {
+    if (_hasFormalsInferred) return;
+    if (formals != null) {
+      for (FormalParameterBuilder formal in formals!) {
+        if (formal.type == null) {
+          if (formal.isInitializingFormal) {
+            formal.finalizeInitializingFormal(classBuilder);
+          }
+        }
+      }
+
+      if (_hasSuperInitializingFormals) {
+        if (beginInitializers != null) {
+          BodyBuilder bodyBuilder = library.loader
+              .createBodyBuilderForOutlineExpression(
+                  library, classBuilder, this, classBuilder.scope, fileUri);
+          bodyBuilder.constantContext = ConstantContext.required;
+          bodyBuilder.parseInitializers(beginInitializers!,
+              doFinishConstructor: false);
+        }
+        finalizeSuperInitializingFormals(
+            classHierarchy, _superParameterDefaultValueCloners);
+      }
+    }
+    _hasFormalsInferred = true;
+  }
+
+  ConstructorBuilder? _computeSuperTargetBuilder() {
+    Constructor superTarget;
+    ClassBuilder superclassBuilder;
+
+    TypeBuilder? supertype = classBuilder.supertypeBuilder;
+    if (supertype is NamedTypeBuilder) {
+      TypeDeclarationBuilder? declaration = supertype.declaration;
+      if (declaration is ClassBuilder) {
+        superclassBuilder = declaration;
+      } else if (declaration is TypeAliasBuilder) {
+        declaration = declaration.unaliasDeclaration(supertype.arguments);
+        if (declaration is ClassBuilder) {
+          superclassBuilder = declaration;
+        } else {
+          // The error in this case should be reported elsewhere.
+          return null;
+        }
+      } else {
+        // The error in this case should be reported elsewhere.
+        return null;
+      }
+    } else {
+      // The error in this case should be reported elsewhere.
+      return null;
+    }
+
+    if (constructor.initializers.isNotEmpty &&
+        constructor.initializers.last is SuperInitializer) {
+      superTarget = (constructor.initializers.last as SuperInitializer).target;
+    } else {
+      MemberBuilder? memberBuilder = superclassBuilder.constructors
+          .lookup("", charOffset, library.fileUri);
+      if (memberBuilder is ConstructorBuilder) {
+        superTarget = memberBuilder.constructor;
+      } else {
+        // The error in this case should be reported elsewhere.
+        return null;
+      }
+    }
+
+    MemberBuilder? constructorBuilder =
+        superclassBuilder.findConstructorOrFactory(
+            superTarget.name.text, charOffset, library.fileUri, library);
+    return constructorBuilder is ConstructorBuilder ? constructorBuilder : null;
+  }
+
+  void finalizeSuperInitializingFormals(ClassHierarchy classHierarchy,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (formals == null) return;
+    if (!_hasSuperInitializingFormals) return;
+
+    void performRecoveryForErroneousCase() {
+      for (FormalParameterBuilder formal in formals!) {
+        if (formal.isSuperInitializingFormal) {
+          formal.variable!.type = const DynamicType();
+        }
+      }
+    }
+
+    ConstructorBuilder? superTargetBuilder = _computeSuperTargetBuilder();
+    Constructor superTarget;
+    List<FormalParameterBuilder>? superFormals;
+    if (superTargetBuilder is DeclaredSourceConstructorBuilder) {
+      superTarget = superTargetBuilder.constructor;
+      superFormals = superTargetBuilder.formals!;
+    } else if (superTargetBuilder is DillConstructorBuilder) {
+      superTarget = superTargetBuilder.constructor;
+      if (superTargetBuilder is SyntheticSourceConstructorBuilder) {
+        superFormals = superTargetBuilder.formals;
+      } else {
+        // The error in this case should be reported elsewhere. Here we perform
+        // a simple recovery.
+        return performRecoveryForErroneousCase();
+      }
+    } else {
+      // The error in this case should be reported elsewhere. Here we perform a
+      // simple recovery.
+      return performRecoveryForErroneousCase();
+    }
+
+    if (superFormals == null) {
+      // The error in this case should be reported elsewhere. Here we perform a
+      // simple recovery.
+      return performRecoveryForErroneousCase();
+    }
+
+    if (superTargetBuilder is DeclaredSourceConstructorBuilder) {
+      superTargetBuilder.inferFormalTypes(classHierarchy);
+    } else if (superTargetBuilder is SyntheticSourceConstructorBuilder) {
+      MemberBuilder? superTargetOriginBuilder = superTargetBuilder.actualOrigin;
+      if (superTargetOriginBuilder is DeclaredSourceConstructorBuilder) {
+        superTargetOriginBuilder.inferFormalTypes(classHierarchy);
+      }
+    }
+
+    int superInitializingFormalIndex = -1;
+    List<int>? positionalSuperParameters;
+    List<String>? namedSuperParameters;
+
+    Supertype? supertype = classHierarchy.getClassAsInstanceOf(
+        classBuilder.cls, superTarget.enclosingClass);
+    assert(supertype != null);
+    Map<TypeParameter, DartType> substitution =
+        new Map<TypeParameter, DartType>.fromIterables(
+            supertype!.classNode.typeParameters, supertype.typeArguments);
+
+    for (int formalIndex = 0; formalIndex < formals!.length; formalIndex++) {
+      FormalParameterBuilder formal = formals![formalIndex];
+      if (formal.isSuperInitializingFormal) {
+        superInitializingFormalIndex++;
+        bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
+
+        FormalParameterBuilder? correspondingSuperFormal;
+
+        if (formal.isPositional) {
+          if (superInitializingFormalIndex < superFormals.length) {
+            correspondingSuperFormal =
+                superFormals[superInitializingFormalIndex];
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (positionalSuperParameters ??= <int>[]).add(formalIndex);
+            }
+          } else {
+            // TODO(cstefantsova): Report an error.
+          }
+        } else {
+          for (FormalParameterBuilder superFormal in superFormals) {
+            if (superFormal.isNamed && superFormal.name == formal.name) {
+              correspondingSuperFormal = superFormal;
+              break;
+            }
+          }
+
+          if (correspondingSuperFormal != null) {
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (namedSuperParameters ??= <String>[]).add(formal.name);
+            }
+          } else {
+            // TODO(cstefantsova): Report an error.
+          }
+        }
+
+        if (formal.type == null) {
+          DartType? type = correspondingSuperFormal?.variable?.type;
+          if (substitution.isNotEmpty && type != null) {
+            type = substitute(type, substitution);
+          }
+          formal.variable!.type = type ?? const DynamicType();
+        } else {
+          formal.variable!.type = const DynamicType();
+        }
+      }
+    }
+
+    if (positionalSuperParameters != null || namedSuperParameters != null) {
+      synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
+          substitution, superTarget.function, constructor.function,
+          positionalSuperParameters: positionalSuperParameters ?? const <int>[],
+          namedSuperParameters: namedSuperParameters ?? const <String>[],
+          isOutlineNode: true));
+    }
+  }
+
+  bool _hasBuiltOutlines = false;
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (_hasBuiltOutlines) return;
+    if (isConst && isPatch) {
+      origin.buildOutlineExpressions(library, classHierarchy,
+          delayedActionPerformers, synthesizedFunctionNodes);
+    }
+    super.buildOutlineExpressions(library, classHierarchy,
+        delayedActionPerformers, synthesizedFunctionNodes);
+
+    // For modular compilation purposes we need to include initializers
+    // for const constructors into the outline. We also need to parse
+    // initializers to infer types of the super-initializing parameters.
+    if ((isConst || _hasSuperInitializingFormals) &&
+        beginInitializers != null) {
+      final Scope? formalParameterScope;
+      if (isConst) {
+        // We're going to fully build the constructor so we need scopes.
+        formalParameterScope = computeFormalParameterInitializerScope(
+            computeFormalParameterScope(
+                computeTypeParameterScope(declarationBuilder!.scope)));
+      } else {
+        formalParameterScope = null;
+      }
+      BodyBuilder bodyBuilder = library.loader
+          .createBodyBuilderForOutlineExpression(
+              library, classBuilder, this, classBuilder.scope, fileUri,
+              formalParameterScope: formalParameterScope);
+      bodyBuilder.constantContext = ConstantContext.required;
+      bodyBuilder.parseInitializers(beginInitializers!,
+          doFinishConstructor: isConst);
+      bodyBuilder.performBacklogComputations(delayedActionPerformers);
+    }
+    beginInitializers = null;
+    addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+    if (isConst && isPatch) {
+      _finishPatch();
+    }
+    _hasBuiltOutlines = true;
+  }
+
+  void addSuperParameterDefaultValueCloners(
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    ConstructorBuilder? superTargetBuilder = _computeSuperTargetBuilder();
+    if (superTargetBuilder is DeclaredSourceConstructorBuilder) {
+      superTargetBuilder
+          .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+    } else if (superTargetBuilder is SyntheticSourceConstructorBuilder) {
+      superTargetBuilder
+          .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+    }
+    synthesizedFunctionNodes.addAll(_superParameterDefaultValueCloners);
+    _superParameterDefaultValueCloners.clear();
+  }
+
+  @override
+  void buildFunction(SourceLibraryBuilder library) {
+    // According to the specification §9.3 the return type of a constructor
+    // function is its enclosing class.
+    super.buildFunction(library);
+    Class enclosingClass = classBuilder.cls;
+    List<DartType> typeParameterTypes = <DartType>[];
+    for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
+      TypeParameter typeParameter = enclosingClass.typeParameters[i];
+      typeParameterTypes.add(
+          new TypeParameterType.withDefaultNullabilityForLibrary(
+              typeParameter, library.library));
+    }
+    function.returnType = new InterfaceType(
+        enclosingClass, library.nonNullable, typeParameterTypes);
+  }
+
+  @override
+  Constructor get constructor => isPatch ? origin.constructor : _constructor;
+
+  @override
+  Member get member => constructor;
+
+  void injectInvalidInitializer(Message message, int charOffset, int length,
+      ExpressionGeneratorHelper helper) {
+    List<Initializer> initializers = _constructor.initializers;
+    Initializer lastInitializer = initializers.removeLast();
+    assert(lastInitializer == superInitializer ||
+        lastInitializer == redirectingInitializer);
+    Initializer error = helper.buildInvalidInitializer(
+        helper.buildProblem(message, charOffset, length));
+    initializers.add(error..parent = _constructor);
+    initializers.add(lastInitializer);
+  }
+
+  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
+      {required InitializerInferenceResult? inferenceResult}) {
+    List<Initializer> initializers = _constructor.initializers;
+    if (initializer is SuperInitializer) {
+      if (superInitializer != null) {
+        injectInvalidInitializer(messageMoreThanOneSuperInitializer,
+            initializer.fileOffset, "super".length, helper);
+      } else if (redirectingInitializer != null) {
+        injectInvalidInitializer(
+            messageRedirectingConstructorWithSuperInitializer,
+            initializer.fileOffset,
+            "super".length,
+            helper);
+      } else {
+        inferenceResult?.applyResult(initializers, _constructor);
+        initializers.add(initializer..parent = _constructor);
+        superInitializer = initializer;
+      }
+    } else if (initializer is RedirectingInitializer) {
+      if (superInitializer != null) {
+        // Point to the existing super initializer.
+        injectInvalidInitializer(
+            messageRedirectingConstructorWithSuperInitializer,
+            superInitializer!.fileOffset,
+            "super".length,
+            helper);
+      } else if (redirectingInitializer != null) {
+        injectInvalidInitializer(
+            messageRedirectingConstructorWithMultipleRedirectInitializers,
+            initializer.fileOffset,
+            noLength,
+            helper);
+      } else if (initializers.isNotEmpty) {
+        // Error on all previous ones.
+        for (int i = 0; i < initializers.length; i++) {
+          Initializer initializer = initializers[i];
+          int length = noLength;
+          if (initializer is AssertInitializer) length = "assert".length;
+          Initializer error = helper.buildInvalidInitializer(
+              helper.buildProblem(
+                  messageRedirectingConstructorWithAnotherInitializer,
+                  initializer.fileOffset,
+                  length));
+          error.parent = _constructor;
+          initializers[i] = error;
+        }
+        inferenceResult?.applyResult(initializers, _constructor);
+        initializers.add(initializer..parent = _constructor);
+        redirectingInitializer = initializer;
+      } else {
+        inferenceResult?.applyResult(initializers, _constructor);
+        initializers.add(initializer..parent = _constructor);
+        redirectingInitializer = initializer;
+      }
+    } else if (redirectingInitializer != null) {
+      int length = noLength;
+      if (initializer is AssertInitializer) length = "assert".length;
+      injectInvalidInitializer(
+          messageRedirectingConstructorWithAnotherInitializer,
+          initializer.fileOffset,
+          length,
+          helper);
+    } else if (superInitializer != null) {
+      injectInvalidInitializer(messageSuperInitializerNotLast,
+          initializer.fileOffset, noLength, helper);
+    } else {
+      inferenceResult?.applyResult(initializers, _constructor);
+      initializers.add(initializer..parent = _constructor);
+    }
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    if (_constructorTearOff != null) {
+      if (index < _constructorTearOff!.function.positionalParameters.length) {
+        return _constructorTearOff!.function.positionalParameters[index];
+      } else {
+        index -= _constructorTearOff!.function.positionalParameters.length;
+        if (index < _constructorTearOff!.function.namedParameters.length) {
+          return _constructorTearOff!.function.namedParameters[index];
+        }
+      }
+    }
+    return null;
+  }
+
+  void _finishPatch() {
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin.constructor.fileUri = fileUri;
+    origin.constructor.startFileOffset = _constructor.startFileOffset;
+    origin.constructor.fileOffset = _constructor.fileOffset;
+    origin.constructor.fileEndOffset = _constructor.fileEndOffset;
+    origin.constructor.annotations
+        .forEach((m) => m.fileOffset = _constructor.fileOffset);
+
+    origin.constructor.isExternal = _constructor.isExternal;
+    origin.constructor.function = _constructor.function;
+    origin.constructor.function.parent = origin.constructor;
+    origin.constructor.initializers = _constructor.initializers;
+    setParents(origin.constructor.initializers, origin.constructor);
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+    _finishPatch();
+    return 1;
+  }
+
+  @override
+  void becomeNative(SourceLoader loader) {
+    _constructor.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is DeclaredSourceConstructorBuilder) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  void prepareInitializers() {
+    // For const constructors we parse initializers already at the outlining
+    // stage, there is no easy way to make body building stage skip initializer
+    // parsing, so we simply clear parsed initializers and rebuild them
+    // again.
+    // For when doing an experimental incremental compilation they are also
+    // potentially done more than once (because it rebuilds the bodies of an old
+    // compile), and so we also clear them.
+    // Note: this method clears both initializers from the target Kernel node
+    // and internal state associated with parsing initializers.
+    _constructor.initializers = [];
+    redirectingInitializer = null;
+    superInitializer = null;
+    hasMovedSuperInitializer = false;
+  }
+
+  @override
+  List<ClassMember> get localMembers =>
+      throw new UnsupportedError('${runtimeType}.localMembers');
+
+  @override
+  List<ClassMember> get localSetters =>
+      throw new UnsupportedError('${runtimeType}.localSetters');
+
+  /// Registers field as being initialized by this constructor.
+  ///
+  /// The field can be initialized either via an initializing formal or via an
+  /// entry in the constructor initializer list.
+  void registerInitializedField(SourceFieldBuilder fieldBuilder) {
+    (_initializedFields ??= {}).add(fieldBuilder);
+  }
+
+  /// Returns the fields registered as initialized by this constructor.
+  ///
+  /// Returns the set of fields previously registered via
+  /// [registerInitializedField] and passes on the ownership of the collection
+  /// to the caller.
+  Set<SourceFieldBuilder>? takeInitializedFields() {
+    Set<SourceFieldBuilder>? result = _initializedFields;
+    _initializedFields = null;
+    return result;
+  }
+
+  void ensureGrowableFormals() {
+    if (formals != null) {
+      formals = new List<FormalParameterBuilder>.of(formals!, growable: true);
+    } else {
+      formals = <FormalParameterBuilder>[];
+    }
+  }
+}
+
+class SyntheticSourceConstructorBuilder extends DillConstructorBuilder
+    with SourceMemberBuilderMixin {
+  // TODO(johnniwinther,cstefantsova): Rename [_origin] to avoid the confusion
+  // with patches.
+  // TODO(johnniwinther): Change the type of [_origin] to SourceMemberBuilder
+  // when it's the supertype for both old SourceMemberBuilder and
+  // SyntheticConstructorBuilder.
+  MemberBuilder? _origin;
+  SynthesizedFunctionNode? _synthesizedFunctionNode;
+
+  SyntheticSourceConstructorBuilder(SourceClassBuilder parent,
+      Constructor constructor, Procedure? constructorTearOff,
+      {MemberBuilder? origin, SynthesizedFunctionNode? synthesizedFunctionNode})
+      : _origin = origin,
+        _synthesizedFunctionNode = synthesizedFunctionNode,
+        super(constructor, constructorTearOff, parent);
+
+  // TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
+  //  confusion with patches.
+  MemberBuilder? get actualOrigin {
+    MemberBuilder? origin = _origin;
+    while (origin is SyntheticSourceConstructorBuilder) {
+      origin = origin._origin;
+    }
+    return origin;
+  }
+
+  List<FormalParameterBuilder>? get formals {
+    MemberBuilder? origin = actualOrigin;
+    return origin is DeclaredSourceConstructorBuilder ? origin.formals : null;
+  }
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder libraryBuilder,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (_origin != null) {
+      // Ensure that default value expressions have been created for [_origin].
+      LibraryBuilder originLibraryBuilder = _origin!.library;
+      if (originLibraryBuilder is SourceLibraryBuilder) {
+        // If [_origin] is from a source library, we need to build the default
+        // values and initializers first.
+        MemberBuilder origin = _origin!;
+        if (origin is DeclaredSourceConstructorBuilder) {
+          origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
+              delayedActionPerformers, synthesizedFunctionNodes);
+        } else if (origin is SyntheticSourceConstructorBuilder) {
+          origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
+              delayedActionPerformers, synthesizedFunctionNodes);
+        }
+      }
+      addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+      _origin = null;
+    }
+  }
+
+  void addSuperParameterDefaultValueCloners(
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    MemberBuilder? origin = _origin;
+    if (origin is DeclaredSourceConstructorBuilder) {
+      origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+    } else if (origin is SyntheticSourceConstructorBuilder) {
+      origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+    }
+    if (_synthesizedFunctionNode != null) {
+      synthesizedFunctionNodes
+          .add(_synthesizedFunctionNode!..isOutlineNode = true);
+      _synthesizedFunctionNode = null;
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
new file mode 100644
index 0000000..093c77c
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -0,0 +1,690 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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.enum_builder;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/reference_from_index.dart' show IndexedClass;
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/constructor_reference_builder.dart';
+import '../builder/field_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/nullability_builder.dart';
+import '../builder/procedure_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_declaration_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../fasta_codes.dart'
+    show
+        LocatedMessage,
+        messageEnumEntryWithTypeArgumentsWithoutArguments,
+        messageNoUnnamedConstructorInObject,
+        noLength,
+        templateDuplicatedDeclaration,
+        templateDuplicatedDeclarationCause,
+        templateDuplicatedDeclarationSyntheticCause,
+        templateEnumConstantSameNameAsEnclosing;
+
+import '../kernel/body_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/expression_generator_helper.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/internal_ast.dart';
+
+import '../modifier.dart' show constMask, hasInitializerMask, staticMask;
+
+import '../constant_context.dart';
+import '../scope.dart';
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+import '../util/helpers.dart';
+import 'name_scheme.dart';
+import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_field_builder.dart';
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_procedure_builder.dart';
+
+class SourceEnumBuilder extends SourceClassBuilder {
+  final List<EnumConstantInfo?>? enumConstantInfos;
+
+  final NamedTypeBuilder intType;
+
+  final NamedTypeBuilder stringType;
+
+  final NamedTypeBuilder objectType;
+
+  final NamedTypeBuilder listType;
+
+  DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
+
+  SourceEnumBuilder.internal(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<TypeVariableBuilder>? typeVariables,
+      TypeBuilder supertypeBuilder,
+      List<TypeBuilder>? interfaceBuilders,
+      Scope scope,
+      ConstructorScope constructors,
+      Class cls,
+      this.enumConstantInfos,
+      this.intType,
+      this.listType,
+      this.objectType,
+      this.stringType,
+      SourceLibraryBuilder parent,
+      int startCharOffset,
+      int charOffset,
+      int charEndOffset,
+      IndexedClass? referencesFromIndexed)
+      : super(
+            metadata,
+            0,
+            name,
+            typeVariables,
+            supertypeBuilder,
+            interfaceBuilders,
+            /* onTypes = */ null,
+            scope,
+            constructors,
+            parent,
+            /* constructorReferences = */ null,
+            startCharOffset,
+            charOffset,
+            charEndOffset,
+            referencesFromIndexed,
+            cls: cls);
+
+  factory SourceEnumBuilder(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<TypeVariableBuilder>? typeVariables,
+      TypeBuilder? supertypeBuilder,
+      List<TypeBuilder>? interfaceBuilders,
+      List<EnumConstantInfo?>? enumConstantInfos,
+      SourceLibraryBuilder parent,
+      int startCharOffset,
+      int charOffset,
+      int charEndOffset,
+      IndexedClass? referencesFromIndexed,
+      Scope scope,
+      ConstructorScope constructorScope) {
+    assert(enumConstantInfos == null || enumConstantInfos.isNotEmpty);
+
+    Uri fileUri = parent.fileUri;
+
+    // TODO(ahe): These types shouldn't be looked up in scope, they come
+    // directly from dart:core.
+    NamedTypeBuilder intType = new NamedTypeBuilder(
+        "int",
+        const NullabilityBuilder.omitted(),
+        /* arguments = */ null,
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess:
+            // If "int" resolves to an instance type variable then that we would
+            // allowed (the types that we are adding are in instance context
+            // after all) but it would be unexpected and we would like an
+            // assertion failure, since "int" was meant to be `int` from
+            // `dart:core`.
+            // TODO(johnniwinther): Add a more robust way of creating named
+            // typed builders for dart:core types. This might be needed for the
+            // enhanced enums feature where enums can actually declare type
+            // variables.
+            InstanceTypeVariableAccessState.Unexpected);
+    NamedTypeBuilder stringType = new NamedTypeBuilder(
+        "String",
+        const NullabilityBuilder.omitted(),
+        /* arguments = */ null,
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+    NamedTypeBuilder objectType = new NamedTypeBuilder(
+        "Object",
+        const NullabilityBuilder.omitted(),
+        /* arguments = */ null,
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+    supertypeBuilder ??= new NamedTypeBuilder(
+        "_Enum",
+        const NullabilityBuilder.omitted(),
+        /* arguments = */ null,
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+    Class cls = new Class(
+        name: name,
+        typeParameters:
+            TypeVariableBuilder.typeParametersFromBuilders(typeVariables),
+        reference: referencesFromIndexed?.cls.reference,
+        fileUri: fileUri);
+    Map<String, MemberBuilder> members = <String, MemberBuilder>{};
+    Map<String, MemberBuilder> setters = <String, MemberBuilder>{};
+    Map<String, MemberBuilder> constructors = <String, MemberBuilder>{};
+    NamedTypeBuilder selfType = new NamedTypeBuilder(
+        name,
+        const NullabilityBuilder.omitted(),
+        /* arguments = */ null,
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+    NamedTypeBuilder listType = new NamedTypeBuilder(
+        "List",
+        const NullabilityBuilder.omitted(),
+        <TypeBuilder>[selfType],
+        /* fileUri = */ null,
+        /* charOffset = */ null,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+
+    // metadata class E extends _Enum {
+    //   const E(int index, String name) : super(index, name);
+    //   static const E id0 = const E(0, 'id0');
+    //   ...
+    //   static const E id${n-1} = const E(n - 1, 'idn-1');
+    //   static const List<E> values = const <E>[id0, ..., id${n-1}];
+    //   String toString() {
+    //     return "E.${_Enum::_name}";
+    //   }
+    // }
+
+    NameScheme staticFieldNameScheme = new NameScheme(
+        isInstanceMember: false,
+        className: name,
+        isExtensionMember: false,
+        extensionName: null,
+        libraryReference: referencesFromIndexed != null
+            ? referencesFromIndexed.library.reference
+            : parent.library.reference);
+
+    NameScheme procedureNameScheme = new NameScheme(
+        isInstanceMember: true,
+        className: name,
+        isExtensionMember: false,
+        extensionName: null,
+        libraryReference: referencesFromIndexed != null
+            ? referencesFromIndexed.library.reference
+            : parent.library.reference);
+
+    Reference? constructorReference;
+    Reference? tearOffReference;
+    Reference? toStringReference;
+    Reference? valuesFieldReference;
+    Reference? valuesGetterReference;
+    Reference? valuesSetterReference;
+    if (referencesFromIndexed != null) {
+      constructorReference =
+          referencesFromIndexed.lookupConstructorReference(new Name(""));
+      tearOffReference = referencesFromIndexed.lookupGetterReference(
+          constructorTearOffName("", referencesFromIndexed.library));
+      toStringReference =
+          referencesFromIndexed.lookupGetterReference(new Name("toString"));
+      Name valuesName = new Name("values");
+      valuesFieldReference =
+          referencesFromIndexed.lookupFieldReference(valuesName);
+      valuesGetterReference =
+          referencesFromIndexed.lookupGetterReference(valuesName);
+      valuesSetterReference =
+          referencesFromIndexed.lookupSetterReference(valuesName);
+    }
+
+    SourceFieldBuilder valuesBuilder = new SourceFieldBuilder(
+        /* metadata = */ null,
+        listType,
+        "values",
+        constMask | staticMask | hasInitializerMask,
+        /* isTopLevel = */ false,
+        parent,
+        charOffset,
+        charOffset,
+        staticFieldNameScheme,
+        fieldReference: valuesFieldReference,
+        fieldGetterReference: valuesGetterReference,
+        fieldSetterReference: valuesSetterReference);
+    members["values"] = valuesBuilder;
+
+    DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
+
+    // The default constructor is added if no generative or unnamed factory
+    // constructors are declared.
+    bool needsSynthesizedDefaultConstructor = true;
+    if (constructorScope.local.isNotEmpty) {
+      for (MemberBuilder constructorBuilder in constructorScope.local.values) {
+        if (!constructorBuilder.isFactory || constructorBuilder.name == "") {
+          needsSynthesizedDefaultConstructor = false;
+          break;
+        }
+      }
+    }
+
+    if (needsSynthesizedDefaultConstructor) {
+      synthesizedDefaultConstructorBuilder =
+          new DeclaredSourceConstructorBuilder(
+              /* metadata = */ null,
+              constMask,
+              /* returnType = */ null,
+              "",
+              /* typeParameters = */ null,
+              <FormalParameterBuilder>[
+                new FormalParameterBuilder(
+                    null, 0, intType, "index", parent, charOffset),
+                new FormalParameterBuilder(
+                    null, 0, stringType, "name", parent, charOffset)
+              ],
+              parent,
+              charOffset,
+              charOffset,
+              charOffset,
+              charEndOffset,
+              constructorReference,
+              tearOffReference,
+              forAbstractClassOrEnum: true);
+      synthesizedDefaultConstructorBuilder
+          .registerInitializedField(valuesBuilder);
+      constructors[""] = synthesizedDefaultConstructorBuilder;
+    } else {
+      constructorScope.forEach((name, member) {
+        if (member is DeclaredSourceConstructorBuilder) {
+          member.ensureGrowableFormals();
+          member.formals!.insert(
+              0,
+              new FormalParameterBuilder(
+                  null, 0, stringType, "name", parent, charOffset));
+          member.formals!.insert(
+              0,
+              new FormalParameterBuilder(
+                  null, 0, intType, "index", parent, charOffset));
+        }
+      });
+    }
+
+    if (scope.lookupLocalMember("toString", setter: false) == null) {
+      ProcedureBuilder toStringBuilder = new SourceProcedureBuilder(
+          /* metadata = */ null,
+          0,
+          stringType,
+          "toString",
+          /* typeVariables = */ null,
+          /* formals = */ null,
+          ProcedureKind.Method,
+          parent,
+          charOffset,
+          charOffset,
+          charOffset,
+          charEndOffset,
+          toStringReference,
+          /* tearOffReference = */ null,
+          AsyncMarker.Sync,
+          procedureNameScheme,
+          isExtensionMember: false,
+          isInstanceMember: true);
+      members["toString"] = toStringBuilder;
+    }
+    String className = name;
+    if (enumConstantInfos != null) {
+      for (int i = 0; i < enumConstantInfos.length; i++) {
+        EnumConstantInfo enumConstantInfo = enumConstantInfos[i]!;
+        List<MetadataBuilder>? metadata = enumConstantInfo.metadata;
+        String name = enumConstantInfo.name;
+        MemberBuilder? existing = members[name];
+        if (existing != null) {
+          // The existing declaration is synthetic if it has the same
+          // charOffset as the enclosing enum.
+          bool isSynthetic = existing.charOffset == charOffset;
+          List<LocatedMessage> context = isSynthetic
+              ? <LocatedMessage>[
+                  templateDuplicatedDeclarationSyntheticCause
+                      .withArguments(name)
+                      .withLocation(
+                          parent.fileUri, charOffset, className.length)
+                ]
+              : <LocatedMessage>[
+                  templateDuplicatedDeclarationCause
+                      .withArguments(name)
+                      .withLocation(
+                          parent.fileUri, existing.charOffset, name.length)
+                ];
+          parent.addProblem(templateDuplicatedDeclaration.withArguments(name),
+              enumConstantInfo.charOffset, name.length, parent.fileUri,
+              context: context);
+          enumConstantInfos[i] = null;
+        } else if (name == className) {
+          parent.addProblem(
+              templateEnumConstantSameNameAsEnclosing.withArguments(name),
+              enumConstantInfo.charOffset,
+              name.length,
+              parent.fileUri);
+        }
+        Reference? fieldReference;
+        Reference? getterReference;
+        Reference? setterReference;
+        if (referencesFromIndexed != null) {
+          Name nameName = new Name(name, referencesFromIndexed.library);
+          fieldReference = referencesFromIndexed.lookupFieldReference(nameName);
+          getterReference =
+              referencesFromIndexed.lookupGetterReference(nameName);
+          setterReference =
+              referencesFromIndexed.lookupSetterReference(nameName);
+        }
+        FieldBuilder fieldBuilder = new SourceFieldBuilder(
+            metadata,
+            selfType,
+            name,
+            constMask | staticMask | hasInitializerMask,
+            /* isTopLevel = */ false,
+            parent,
+            enumConstantInfo.charOffset,
+            enumConstantInfo.charOffset,
+            staticFieldNameScheme,
+            fieldReference: fieldReference,
+            fieldGetterReference: getterReference,
+            fieldSetterReference: setterReference);
+        members[name] = fieldBuilder..next = existing;
+      }
+    }
+    final int startCharOffsetComputed =
+        metadata == null ? startCharOffset : metadata.first.charOffset;
+    scope.forEachLocalMember((name, member) {
+      members[name] = member as MemberBuilder;
+    });
+    scope.forEachLocalSetter((name, member) {
+      setters[name] = member;
+    });
+    SourceEnumBuilder enumBuilder = new SourceEnumBuilder.internal(
+        metadata,
+        name,
+        typeVariables,
+        supertypeBuilder,
+        interfaceBuilders,
+        new Scope(
+            local: members,
+            setters: setters,
+            parent: scope.parent,
+            debugName: "enum $name",
+            isModifiable: false),
+        constructorScope..local.addAll(constructors),
+        cls,
+        enumConstantInfos,
+        intType,
+        listType,
+        objectType,
+        stringType,
+        parent,
+        startCharOffsetComputed,
+        charOffset,
+        charEndOffset,
+        referencesFromIndexed)
+      ..synthesizedDefaultConstructorBuilder =
+          synthesizedDefaultConstructorBuilder;
+
+    void setParent(String name, MemberBuilder? builder) {
+      while (builder != null) {
+        builder.parent = enumBuilder;
+        builder = builder.next as MemberBuilder?;
+      }
+    }
+
+    members.forEach(setParent);
+    constructors.forEach(setParent);
+    selfType.bind(enumBuilder);
+    return enumBuilder;
+  }
+
+  @override
+  TypeBuilder? get mixedInTypeBuilder => null;
+
+  @override
+  Class build(SourceLibraryBuilder libraryBuilder, LibraryBuilder coreLibrary) {
+    cls.isEnum = true;
+    intType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+    stringType.resolveIn(
+        coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+    objectType.resolveIn(
+        coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+    TypeBuilder? supertypeBuilder = this.supertypeBuilder;
+    NamedTypeBuilder? enumType;
+
+    while (enumType == null && supertypeBuilder is NamedTypeBuilder) {
+      TypeDeclarationBuilder? superclassBuilder = supertypeBuilder.declaration;
+      if (superclassBuilder is ClassBuilder &&
+          superclassBuilder.isMixinApplication) {
+        supertypeBuilder = superclassBuilder.supertypeBuilder;
+      } else {
+        enumType = supertypeBuilder;
+      }
+    }
+    assert(enumType is NamedTypeBuilder && enumType.name == "_Enum");
+    enumType!.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+
+    listType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
+
+    List<Expression> values = <Expression>[];
+    if (enumConstantInfos != null) {
+      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
+        if (enumConstantInfo != null) {
+          Builder declaration = firstMemberNamed(enumConstantInfo.name)!;
+          if (declaration.isField) {
+            SourceFieldBuilder fieldBuilder = declaration as SourceFieldBuilder;
+            fieldBuilder.build(libraryBuilder);
+            values.add(new StaticGet(fieldBuilder.field));
+          }
+        }
+      }
+    }
+    SourceFieldBuilder valuesBuilder =
+        firstMemberNamed("values") as SourceFieldBuilder;
+    valuesBuilder.build(libraryBuilder);
+
+    // The super initializer for the synthesized default constructor is
+    // inserted here if the enum's supertype is _Enum to preserve the legacy
+    // behavior or having the old-style enum constants built in the outlines.
+    // Other constructors are handled in [BodyBuilder.finishConstructor] as
+    // they are processed via the pipeline for constructor parsing and
+    // building.
+    if (identical(this.supertypeBuilder, enumType)) {
+      if (synthesizedDefaultConstructorBuilder != null) {
+        Constructor constructor =
+            synthesizedDefaultConstructorBuilder!.build(libraryBuilder);
+        ClassBuilder objectClass = objectType.declaration as ClassBuilder;
+        ClassBuilder enumClass = enumType.declaration as ClassBuilder;
+        MemberBuilder? superConstructor = enumClass.findConstructorOrFactory(
+            "", charOffset, fileUri, libraryBuilder);
+        if (superConstructor == null || !superConstructor.isConstructor) {
+          // TODO(ahe): Ideally, we would also want to check that [Object]'s
+          // unnamed constructor requires no arguments. But that information
+          // isn't always available at this point, and it's not really a
+          // situation that can happen unless you start modifying the SDK
+          // sources. (We should add a correct message. We no longer depend on
+          // Object here.)
+          library.addProblem(
+              messageNoUnnamedConstructorInObject,
+              objectClass.charOffset,
+              objectClass.name.length,
+              objectClass.fileUri);
+        } else {
+          constructor.initializers.add(new SuperInitializer(
+              superConstructor.member as Constructor,
+              new Arguments.forwarded(
+                  constructor.function, libraryBuilder.library))
+            ..parent = constructor);
+        }
+        synthesizedDefaultConstructorBuilder = null;
+      }
+    }
+
+    return super.build(libraryBuilder, coreLibrary);
+  }
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder libraryBuilder,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    List<Expression> values = <Expression>[];
+    if (enumConstantInfos != null) {
+      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
+        if (enumConstantInfo != null) {
+          Builder declaration = firstMemberNamed(enumConstantInfo.name)!;
+          if (declaration.isField) {
+            SourceFieldBuilder fieldBuilder = declaration as SourceFieldBuilder;
+            fieldBuilder.build(libraryBuilder);
+            values.add(new StaticGet(fieldBuilder.field));
+          }
+        }
+      }
+    }
+    SourceFieldBuilder valuesBuilder =
+        firstMemberNamed("values") as SourceFieldBuilder;
+    valuesBuilder.buildBody(
+        classHierarchy.coreTypes,
+        new ListLiteral(values,
+            typeArgument: rawType(library.nonNullable), isConst: true));
+    int index = 0;
+    if (enumConstantInfos != null) {
+      for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
+        if (enumConstantInfo != null) {
+          if (enumConstantInfo.argumentsBeginToken == null &&
+              enumConstantInfo.constructorReferenceBuilder?.typeArguments !=
+                  null) {
+            addProblem(messageEnumEntryWithTypeArgumentsWithoutArguments,
+                enumConstantInfo.charOffset, noLength);
+          }
+
+          String constant = enumConstantInfo.name;
+          Builder declaration = firstMemberNamed(constant)!;
+          SourceFieldBuilder field;
+          if (declaration.isField) {
+            field = declaration as SourceFieldBuilder;
+          } else {
+            continue;
+          }
+
+          String constructorName =
+              enumConstantInfo.constructorReferenceBuilder?.suffix ?? "";
+          MemberBuilder? constructorBuilder =
+              constructorScopeBuilder[constructorName];
+
+          Arguments arguments;
+          List<Expression> enumSyntheticArguments = <Expression>[
+            new IntLiteral(index++),
+            new StringLiteral(constant),
+          ];
+          List<DartType>? typeArguments;
+          List<TypeBuilder>? typeArgumentBuilders =
+              enumConstantInfo.constructorReferenceBuilder?.typeArguments;
+          if (typeArgumentBuilders != null) {
+            typeArguments = <DartType>[];
+            for (TypeBuilder typeBuilder in typeArgumentBuilders) {
+              typeArguments.add(typeBuilder.build(library));
+            }
+          }
+          BodyBuilder? bodyBuilder;
+          if (enumConstantInfo.argumentsBeginToken != null ||
+              typeArgumentBuilders == null && cls.typeParameters.isNotEmpty) {
+            // We need to create a BodyBuilder in two cases: 1) if the
+            // arguments token is provided, we'll use the BodyBuilder to
+            // parse them and perform inference, 2) if the type arguments
+            // aren't provided, but required, we'll use it to infer them.
+            bodyBuilder = library.loader.createBodyBuilderForOutlineExpression(
+                library, this, this, scope, fileUri);
+            bodyBuilder.constantContext = ConstantContext.required;
+          }
+
+          if (enumConstantInfo.argumentsBeginToken != null) {
+            arguments = bodyBuilder!
+                .parseArguments(enumConstantInfo.argumentsBeginToken!);
+            bodyBuilder.performBacklogComputations(delayedActionPerformers);
+
+            arguments.positional.insertAll(0, enumSyntheticArguments);
+          } else {
+            arguments = new ArgumentsImpl(enumSyntheticArguments);
+          }
+
+          if (typeArguments != null && arguments is ArgumentsImpl) {
+            ArgumentsImpl.setNonInferrableArgumentTypes(
+                arguments, typeArguments);
+          } else if (cls.typeParameters.isNotEmpty) {
+            arguments.types.addAll(new List<DartType>.filled(
+                cls.typeParameters.length, const UnknownType()));
+          }
+          setParents(enumSyntheticArguments, arguments);
+
+          if (constructorBuilder == null ||
+              constructorBuilder is! SourceConstructorBuilder) {
+            bodyBuilder ??= library.loader
+                .createBodyBuilderForOutlineExpression(
+                    library, this, this, scope, fileUri)
+              ..constantContext = ConstantContext.required;
+            field.buildBody(
+                classHierarchy.coreTypes,
+                bodyBuilder.buildUnresolvedError(
+                    new NullLiteral(),
+                    enumConstantInfo
+                            .constructorReferenceBuilder?.fullNameForErrors ??
+                        constructorName,
+                    arguments,
+                    enumConstantInfo.constructorReferenceBuilder?.charOffset ??
+                        enumConstantInfo.charOffset,
+                    kind: UnresolvedKind.Constructor));
+          } else {
+            Expression initializer = new ConstructorInvocation(
+                constructorBuilder.constructor, arguments,
+                isConst: true)
+              ..fileOffset = field.charOffset;
+            if (bodyBuilder != null) {
+              ExpressionInferenceResult inferenceResult =
+                  bodyBuilder.typeInferrer.inferFieldInitializer(
+                      bodyBuilder, const UnknownType(), initializer);
+              initializer = inferenceResult.expression;
+              field.fieldType = inferenceResult.inferredType;
+            }
+            field.buildBody(classHierarchy.coreTypes, initializer);
+          }
+        }
+      }
+    }
+
+    SourceProcedureBuilder toStringBuilder =
+        firstMemberNamed("toString") as SourceProcedureBuilder;
+
+    TypeBuilder supertypeBuilder = this.supertypeBuilder!;
+    ClassBuilder enumClass = supertypeBuilder.declaration as ClassBuilder;
+    MemberBuilder? nameFieldBuilder =
+        enumClass.lookupLocalMember("_name") as MemberBuilder?;
+    if (nameFieldBuilder != null) {
+      Field nameField = nameFieldBuilder.member as Field;
+
+      toStringBuilder.body = new ReturnStatement(new StringConcatenation([
+        new StringLiteral("${cls.demangledName}."),
+        new InstanceGet.byReference(
+            InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
+            interfaceTargetReference: nameField.getterReference,
+            resultType: nameField.getterType),
+      ]));
+    }
+
+    super.buildOutlineExpressions(library, classHierarchy,
+        delayedActionPerformers, synthesizedFunctionNodes);
+  }
+}
+
+class EnumConstantInfo {
+  final List<MetadataBuilder>? metadata;
+  final String name;
+  final int charOffset;
+  ConstructorReferenceBuilder? constructorReferenceBuilder;
+  Token? argumentsBeginToken;
+
+  EnumConstantInfo(this.metadata, this.name, this.charOffset);
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 4760e58..6a8924b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -3,40 +3,33 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/type_environment.dart';
 
 import '../../base/common.dart';
-
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/extension_builder.dart';
-import '../builder/field_builder.dart';
 import '../builder/library_builder.dart';
-import '../builder/member_builder.dart';
 import '../builder/metadata_builder.dart';
 import '../builder/procedure_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
-
 import '../fasta_codes.dart'
     show
         messagePatchDeclarationMismatch,
         messagePatchDeclarationOrigin,
         noLength,
         templateExtensionMemberConflictsWithObjectMember;
-
 import '../kernel/kernel_helper.dart';
-
 import '../operator.dart';
-
 import '../problems.dart';
-
 import '../scope.dart';
-
 import '../util/helpers.dart';
-
+import 'source_field_builder.dart';
 import 'source_library_builder.dart';
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
 
 const String extensionThisName = '#this';
 
@@ -128,8 +121,8 @@
             unexpected(fullNameForErrors, declaration.parent!.fullNameForErrors,
                 charOffset, fileUri);
           }
-        } else if (declaration is MemberBuilderImpl) {
-          MemberBuilderImpl memberBuilder = declaration;
+        } else if (declaration is SourceMemberBuilder) {
+          SourceMemberBuilder memberBuilder = declaration;
           memberBuilder.buildMembers(libraryBuilder,
               (Member member, BuiltMemberKind memberKind) {
             if (addMembersToLibrary &&
@@ -262,7 +255,7 @@
       if (builder is SourceFieldBuilder) {
         // Check fields.
         library.checkTypesInField(builder, typeEnvironment);
-      } else if (builder is ProcedureBuilder) {
+      } else if (builder is SourceProcedureBuilder) {
         // Check procedures
         library.checkTypesInFunctionBuilder(builder, typeEnvironment);
         if (builder.isGetter) {
@@ -282,7 +275,7 @@
   @override
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     MetadataBuilder.buildAnnotations(isPatch ? origin.extension : extension,
@@ -290,13 +283,13 @@
     if (typeParameters != null) {
       for (int i = 0; i < typeParameters!.length; i++) {
         typeParameters![i].buildOutlineExpressions(library, this, null,
-            coreTypes, delayedActionPerformers, scope.parent!);
+            classHierarchy, delayedActionPerformers, scope.parent!);
       }
     }
 
     void build(String ignore, Builder declaration) {
-      MemberBuilder member = declaration as MemberBuilder;
-      member.buildOutlineExpressions(library, coreTypes,
+      SourceMemberBuilder member = declaration as SourceMemberBuilder;
+      member.buildOutlineExpressions(library, classHierarchy,
           delayedActionPerformers, synthesizedFunctionNodes);
     }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
new file mode 100644
index 0000000..5d02635
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
@@ -0,0 +1,469 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All 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/type_algebra.dart';
+
+import '../builder/builder.dart';
+import '../builder/constructor_reference_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/function_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../dill/dill_member_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/forest.dart';
+import '../kernel/hierarchy/class_member.dart';
+import '../kernel/internal_ast.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/redirecting_factory_body.dart'
+    show getRedirectingFactoryBody, RedirectingFactoryBody;
+import '../messages.dart'
+    show messageConstFactoryRedirectionToNonConst, noLength;
+import '../problems.dart' show unexpected, unhandled;
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+import '../util/helpers.dart';
+import 'name_scheme.dart';
+import 'source_function_builder.dart';
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_loader.dart' show SourceLoader;
+import 'source_member_builder.dart';
+
+class SourceFactoryBuilder extends SourceFunctionBuilderImpl {
+  final int charOpenParenOffset;
+
+  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+  @override
+  final bool isExtensionInstanceMember = false;
+
+  final Procedure _procedureInternal;
+  final Procedure? _factoryTearOff;
+
+  SourceFactoryBuilder? actualOrigin;
+
+  SourceFactoryBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder returnType,
+      String name,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder>? formals,
+      SourceLibraryBuilder libraryBuilder,
+      int startCharOffset,
+      int charOffset,
+      this.charOpenParenOffset,
+      int charEndOffset,
+      Reference? procedureReference,
+      Reference? tearOffReference,
+      AsyncMarker asyncModifier,
+      NameScheme nameScheme,
+      {String? nativeMethodName})
+      : _procedureInternal = new Procedure(
+            nameScheme.getProcedureName(ProcedureKind.Factory, name),
+            ProcedureKind.Factory,
+            new FunctionNode(null),
+            fileUri: libraryBuilder.fileUri,
+            reference: procedureReference)
+          ..startFileOffset = startCharOffset
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault,
+        _factoryTearOff = createFactoryTearOffProcedure(name, libraryBuilder,
+            libraryBuilder.fileUri, charOffset, tearOffReference),
+        super(metadata, modifiers, returnType, name, typeVariables, formals,
+            libraryBuilder, charOffset, nativeMethodName) {
+    this.asyncModifier = asyncModifier;
+  }
+
+  SourceFactoryBuilder? get patchForTesting =>
+      dataForTesting?.patchForTesting as SourceFactoryBuilder?;
+
+  @override
+  AsyncMarker get asyncModifier => actualAsyncModifier;
+
+  @override
+  Statement? get body {
+    if (bodyInternal == null && !isAbstract && !isExternal) {
+      bodyInternal = new EmptyStatement();
+    }
+    return bodyInternal;
+  }
+
+  void set asyncModifier(AsyncMarker newModifier) {
+    actualAsyncModifier = newModifier;
+    function.asyncMarker = actualAsyncModifier;
+    function.dartAsyncMarker = actualAsyncModifier;
+  }
+
+  @override
+  Member get member => _procedure;
+
+  @override
+  SourceFactoryBuilder get origin => actualOrigin ?? this;
+
+  @override
+  ProcedureKind get kind => ProcedureKind.Factory;
+
+  Procedure get _procedure => isPatch ? origin._procedure : _procedureInternal;
+
+  @override
+  FunctionNode get function => _procedureInternal.function;
+
+  @override
+  Member? get readTarget => origin._factoryTearOff ?? _procedure;
+
+  @override
+  Member? get writeTarget => null;
+
+  @override
+  Member? get invokeTarget => _procedure;
+
+  @override
+  Iterable<Member> get exportedMembers => [_procedure];
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.Method);
+    if (_factoryTearOff != null) {
+      f(_factoryTearOff!, BuiltMemberKind.Method);
+    }
+  }
+
+  @override
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    buildFunction(libraryBuilder);
+    _procedureInternal.function.fileOffset = charOpenParenOffset;
+    _procedureInternal.function.fileEndOffset =
+        _procedureInternal.fileEndOffset;
+    _procedureInternal.isAbstract = isAbstract;
+    _procedureInternal.isExternal = isExternal;
+    _procedureInternal.isConst = isConst;
+    updatePrivateMemberName(_procedureInternal, libraryBuilder);
+    _procedureInternal.isStatic = isStatic;
+
+    if (_factoryTearOff != null) {
+      buildConstructorTearOffProcedure(_factoryTearOff!, _procedureInternal,
+          classBuilder!.cls, libraryBuilder);
+    }
+    return _procedureInternal;
+  }
+
+  bool _hasBuiltOutlines = false;
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (_hasBuiltOutlines) return;
+    super.buildOutlineExpressions(library, classHierarchy,
+        delayedActionPerformers, synthesizedFunctionNodes);
+    _hasBuiltOutlines = true;
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    if (_factoryTearOff != null) {
+      if (index < _factoryTearOff!.function.positionalParameters.length) {
+        return _factoryTearOff!.function.positionalParameters[index];
+      } else {
+        index -= _factoryTearOff!.function.positionalParameters.length;
+        if (index < _factoryTearOff!.function.namedParameters.length) {
+          return _factoryTearOff!.function.namedParameters[index];
+        }
+      }
+    }
+    return null;
+  }
+
+  @override
+  List<ClassMember> get localMembers =>
+      throw new UnsupportedError('${runtimeType}.localMembers');
+
+  @override
+  List<ClassMember> get localSetters =>
+      throw new UnsupportedError('${runtimeType}.localSetters');
+
+  @override
+  void becomeNative(SourceLoader loader) {
+    _procedureInternal.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+    if (bodyInternal != null) {
+      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+    }
+    bodyInternal = new RedirectingFactoryBody(target, typeArguments, function);
+    function.body = bodyInternal;
+    bodyInternal?.parent = function;
+    if (isPatch) {
+      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+    }
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is SourceFactoryBuilder) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  void _finishPatch() {
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin._procedure.fileUri = fileUri;
+    origin._procedure.startFileOffset = _procedureInternal.startFileOffset;
+    origin._procedure.fileOffset = _procedureInternal.fileOffset;
+    origin._procedure.fileEndOffset = _procedureInternal.fileEndOffset;
+    origin._procedure.annotations
+        .forEach((m) => m.fileOffset = _procedureInternal.fileOffset);
+
+    origin._procedure.isAbstract = _procedureInternal.isAbstract;
+    origin._procedure.isExternal = _procedureInternal.isExternal;
+    origin._procedure.function = _procedureInternal.function;
+    origin._procedure.function.parent = origin._procedure;
+    origin._procedure.isRedirectingFactory =
+        _procedureInternal.isRedirectingFactory;
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+    _finishPatch();
+    return 1;
+  }
+}
+
+class RedirectingFactoryBuilder extends SourceFactoryBuilder {
+  final ConstructorReferenceBuilder redirectionTarget;
+  List<DartType>? typeArguments;
+
+  FreshTypeParameters? _tearOffTypeParameters;
+
+  RedirectingFactoryBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder returnType,
+      String name,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder>? formals,
+      SourceLibraryBuilder libraryBuilder,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      Reference? procedureReference,
+      Reference? tearOffReference,
+      NameScheme nameScheme,
+      String? nativeMethodName,
+      this.redirectionTarget)
+      : super(
+            metadata,
+            modifiers,
+            returnType,
+            name,
+            typeVariables,
+            formals,
+            libraryBuilder,
+            startCharOffset,
+            charOffset,
+            charOpenParenOffset,
+            charEndOffset,
+            procedureReference,
+            tearOffReference,
+            AsyncMarker.Sync,
+            nameScheme,
+            nativeMethodName: nativeMethodName);
+
+  @override
+  Statement? get body => bodyInternal;
+
+  @override
+  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+    if (bodyInternal != null) {
+      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+    }
+
+    // Ensure that constant factories only have constant targets/bodies.
+    if (isConst && !target.isConst) {
+      library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
+          noLength, fileUri);
+    }
+
+    bodyInternal = new RedirectingFactoryBody(target, typeArguments, function);
+    function.body = bodyInternal;
+    bodyInternal?.parent = function;
+    _procedure.isRedirectingFactory = true;
+    if (isPatch) {
+      // ignore: unnecessary_null_comparison
+      if (function.typeParameters != null) {
+        Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
+        for (int i = 0; i < function.typeParameters.length; i++) {
+          substitution[function.typeParameters[i]] =
+              new TypeParameterType.withDefaultNullabilityForLibrary(
+                  actualOrigin!.function.typeParameters[i], library.library);
+        }
+        typeArguments = new List<DartType>.generate(typeArguments.length,
+            (int i) => substitute(typeArguments[i], substitution),
+            growable: false);
+      }
+      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+    }
+  }
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.RedirectingFactory);
+    if (_factoryTearOff != null) {
+      f(_factoryTearOff!, BuiltMemberKind.Method);
+    }
+  }
+
+  @override
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    buildFunction(libraryBuilder);
+    _procedureInternal.function.fileOffset = charOpenParenOffset;
+    _procedureInternal.function.fileEndOffset =
+        _procedureInternal.fileEndOffset;
+    _procedureInternal.isAbstract = isAbstract;
+    _procedureInternal.isExternal = isExternal;
+    _procedureInternal.isConst = isConst;
+    _procedureInternal.isStatic = isStatic;
+    _procedureInternal.isRedirectingFactory = true;
+    if (redirectionTarget.typeArguments != null) {
+      typeArguments = new List<DartType>.generate(
+          redirectionTarget.typeArguments!.length,
+          (int i) => redirectionTarget.typeArguments![i].build(library),
+          growable: false);
+    }
+    updatePrivateMemberName(_procedureInternal, libraryBuilder);
+    if (_factoryTearOff != null) {
+      _tearOffTypeParameters =
+          buildRedirectingFactoryTearOffProcedureParameters(
+              _factoryTearOff!, _procedureInternal, libraryBuilder);
+    }
+    return _procedureInternal;
+  }
+
+  @override
+  bool _hasBuiltOutlines = false;
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (_hasBuiltOutlines) return;
+    if (isConst && isPatch) {
+      origin.buildOutlineExpressions(library, classHierarchy,
+          delayedActionPerformers, synthesizedFunctionNodes);
+    }
+    super.buildOutlineExpressions(library, classHierarchy,
+        delayedActionPerformers, synthesizedFunctionNodes);
+    RedirectingFactoryBody redirectingFactoryBody =
+        _procedureInternal.function.body as RedirectingFactoryBody;
+    List<DartType>? typeArguments = redirectingFactoryBody.typeArguments;
+    Member? target = redirectingFactoryBody.target;
+    if (typeArguments != null && typeArguments.any((t) => t is UnknownType)) {
+      TypeInferrerImpl inferrer = library.loader.typeInferenceEngine
+              .createLocalTypeInferrer(
+                  fileUri, classBuilder!.thisType, library, null)
+          as TypeInferrerImpl;
+      inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
+          library, classBuilder, this, classBuilder!.scope, fileUri);
+      Builder? targetBuilder = redirectionTarget.target;
+      if (targetBuilder is FunctionBuilder) {
+        target = targetBuilder.member;
+      } else if (targetBuilder is DillMemberBuilder) {
+        target = targetBuilder.member;
+      } else {
+        unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
+            charOffset, fileUri);
+      }
+      ArgumentsImpl targetInvocationArguments;
+      {
+        List<Expression> positionalArguments = <Expression>[];
+        for (VariableDeclaration parameter
+            in _procedure.function.positionalParameters) {
+          inferrer.flowAnalysis.declare(parameter, true);
+          positionalArguments
+              .add(new VariableGetImpl(parameter, forNullGuardedAccess: false));
+        }
+        List<NamedExpression> namedArguments = <NamedExpression>[];
+        for (VariableDeclaration parameter
+            in _procedure.function.namedParameters) {
+          inferrer.flowAnalysis.declare(parameter, true);
+          namedArguments.add(new NamedExpression(parameter.name!,
+              new VariableGetImpl(parameter, forNullGuardedAccess: false)));
+        }
+        // If arguments are created using [Forest.createArguments], and the
+        // type arguments are omitted, they are to be inferred.
+        targetInvocationArguments = const Forest().createArguments(
+            _procedure.fileOffset, positionalArguments,
+            named: namedArguments);
+      }
+      InvocationInferenceResult result = inferrer.inferInvocation(
+          function.returnType,
+          charOffset,
+          target.function!.computeFunctionType(Nullability.nonNullable),
+          targetInvocationArguments,
+          staticTarget: target);
+      if (result.inferredType is InterfaceType) {
+        typeArguments = (result.inferredType as InterfaceType).typeArguments;
+      } else {
+        // Assume that the error is reported elsewhere, use 'dynamic' for
+        // recovery.
+        typeArguments = new List<DartType>.filled(
+            target.enclosingClass!.typeParameters.length, const DynamicType(),
+            growable: true);
+      }
+
+      function.body =
+          new RedirectingFactoryBody(target, typeArguments, function);
+      function.body!.parent = function;
+    }
+    if (_factoryTearOff != null &&
+        (target is Constructor || target is Procedure && target.isFactory)) {
+      synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
+          _factoryTearOff!,
+          target!,
+          typeArguments ?? [],
+          _tearOffTypeParameters!));
+    }
+    if (isConst && isPatch) {
+      _finishPatch();
+    }
+    _hasBuiltOutlines = true;
+  }
+
+  @override
+  void _finishPatch() {
+    super._finishPatch();
+
+    SourceFactoryBuilder redirectingOrigin = origin;
+    if (redirectingOrigin is RedirectingFactoryBuilder) {
+      redirectingOrigin.typeArguments = typeArguments;
+    }
+  }
+
+  List<DartType>? getTypeArguments() {
+    return getRedirectingFactoryBody(_procedure)!.typeArguments;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
new file mode 100644
index 0000000..5a71d1b
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -0,0 +1,1809 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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.field_builder;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../builder/class_builder.dart';
+import '../builder/field_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../constant_context.dart' show ConstantContext;
+import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
+import '../kernel/body_builder.dart' show BodyBuilder;
+import '../kernel/hierarchy/class_member.dart';
+import '../kernel/hierarchy/members_builder.dart';
+import '../kernel/implicit_field_type.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/late_lowering.dart' as late_lowering;
+import '../kernel/member_covariance.dart';
+import '../modifier.dart' show covariantMask, hasInitializerMask, lateMask;
+import '../problems.dart' show internalProblem;
+import '../scope.dart' show Scope;
+import '../source/name_scheme.dart';
+import '../source/source_extension_builder.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import '../type_inference/type_inference_engine.dart'
+    show IncludesTypeParametersNonCovariantly;
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_member_builder.dart';
+
+class SourceFieldBuilder extends SourceMemberBuilderImpl
+    implements FieldBuilder {
+  @override
+  final String name;
+
+  @override
+  final int modifiers;
+
+  late FieldEncoding _fieldEncoding;
+
+  final List<MetadataBuilder>? metadata;
+
+  final TypeBuilder? type;
+
+  Token? _constInitializerToken;
+
+  bool hadTypesInferred = false;
+
+  /// Whether the body of this field has been built.
+  ///
+  /// Constant fields have their initializer built in the outline so we avoid
+  /// building them twice as part of the non-outline build.
+  bool hasBodyBeenBuilt = false;
+
+  // TODO(johnniwinther): [parent] is not trust-worthy for determining
+  //  properties since it is changed after the creation of the builder. For now
+  //  we require it has an argument here. A follow-up should clean up the
+  //  misuse of parent.
+  @override
+  final bool isTopLevel;
+
+  SourceFieldBuilder(
+      this.metadata,
+      this.type,
+      this.name,
+      this.modifiers,
+      this.isTopLevel,
+      SourceLibraryBuilder libraryBuilder,
+      int charOffset,
+      int charEndOffset,
+      NameScheme fieldNameScheme,
+      {Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      Token? constInitializerToken})
+      : _constInitializerToken = constInitializerToken,
+        super(libraryBuilder, charOffset) {
+    bool isInstanceMember = fieldNameScheme.isInstanceMember;
+
+    Uri fileUri = libraryBuilder.fileUri;
+    // If in mixed mode, late lowerings cannot use `null` as a sentinel on
+    // non-nullable fields since they can be assigned from legacy code.
+    late_lowering.IsSetStrategy isSetStrategy =
+        late_lowering.computeIsSetStrategy(libraryBuilder);
+
+    if (isAbstract || isExternal) {
+      assert(fieldReference == null);
+      assert(lateIsSetFieldReference == null);
+      assert(lateIsSetGetterReference == null);
+      assert(lateIsSetSetterReference == null);
+      assert(lateGetterReference == null);
+      assert(lateSetterReference == null);
+      _fieldEncoding = new AbstractOrExternalFieldEncoding(
+          this,
+          name,
+          fieldNameScheme,
+          fileUri,
+          charOffset,
+          charEndOffset,
+          fieldGetterReference,
+          fieldSetterReference,
+          isAbstract: isAbstract,
+          isExternal: isExternal,
+          isFinal: isFinal,
+          isCovariantByDeclaration: isCovariantByDeclaration,
+          isNonNullableByDefault: library.isNonNullableByDefault);
+    } else if (isLate &&
+        libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
+            hasInitializer: hasInitializer,
+            isFinal: isFinal,
+            isStatic: !isInstanceMember)) {
+      if (hasInitializer) {
+        if (isFinal) {
+          _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
+              name,
+              fieldNameScheme,
+              fileUri,
+              charOffset,
+              charEndOffset,
+              fieldReference,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetFieldReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              lateGetterReference,
+              lateSetterReference,
+              isCovariantByDeclaration,
+              isSetStrategy);
+        } else {
+          _fieldEncoding = new LateFieldWithInitializerEncoding(
+              name,
+              fieldNameScheme,
+              fileUri,
+              charOffset,
+              charEndOffset,
+              fieldReference,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetFieldReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              lateGetterReference,
+              lateSetterReference,
+              isCovariantByDeclaration,
+              isSetStrategy);
+        }
+      } else {
+        if (isFinal) {
+          _fieldEncoding = new LateFinalFieldWithoutInitializerEncoding(
+              name,
+              fieldNameScheme,
+              fileUri,
+              charOffset,
+              charEndOffset,
+              fieldReference,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetFieldReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              lateGetterReference,
+              lateSetterReference,
+              isCovariantByDeclaration,
+              isSetStrategy);
+        } else {
+          _fieldEncoding = new LateFieldWithoutInitializerEncoding(
+              name,
+              fieldNameScheme,
+              fileUri,
+              charOffset,
+              charEndOffset,
+              fieldReference,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetFieldReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              lateGetterReference,
+              lateSetterReference,
+              isCovariantByDeclaration,
+              isSetStrategy);
+        }
+      }
+    } else if (libraryBuilder.isNonNullableByDefault &&
+        libraryBuilder.loader.target.backendTarget.useStaticFieldLowering &&
+        !isInstanceMember &&
+        !isConst &&
+        hasInitializer) {
+      if (isFinal) {
+        _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
+            name,
+            fieldNameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+      } else {
+        _fieldEncoding = new LateFieldWithInitializerEncoding(
+            name,
+            fieldNameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+      }
+    } else {
+      assert(lateIsSetFieldReference == null);
+      assert(lateIsSetGetterReference == null);
+      assert(lateIsSetSetterReference == null);
+      assert(lateGetterReference == null);
+      assert(lateSetterReference == null);
+      _fieldEncoding = new RegularFieldEncoding(
+          name, fieldNameScheme, fileUri, charOffset, charEndOffset,
+          isFinal: isFinal,
+          isConst: isConst,
+          isLate: isLate,
+          hasInitializer: hasInitializer,
+          isNonNullableByDefault: library.isNonNullableByDefault,
+          fieldReference: fieldReference,
+          getterReference: fieldGetterReference,
+          setterReference: fieldSetterReference);
+    }
+  }
+
+  bool get isLateLowered => _fieldEncoding.isLateLowering;
+
+  bool _typeEnsured = false;
+  Set<ClassMember>? _overrideDependencies;
+
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    assert(
+        overriddenMembers.every((overriddenMember) =>
+            overriddenMember.classBuilder != classBuilder),
+        "Unexpected override dependencies for $this: $overriddenMembers");
+    _overrideDependencies ??= {};
+    _overrideDependencies!.addAll(overriddenMembers);
+  }
+
+  void _ensureType(ClassMembersBuilder membersBuilder) {
+    if (_typeEnsured) return;
+    if (_overrideDependencies != null) {
+      membersBuilder.inferFieldType(this, _overrideDependencies!);
+      _overrideDependencies = null;
+    } else {
+      inferType();
+    }
+    _typeEnsured = true;
+  }
+
+  @override
+  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+  @override
+  Member get member => _fieldEncoding.field;
+
+  @override
+  String get debugName => "FieldBuilder";
+
+  @override
+  bool get isField => true;
+
+  bool get isLate => (modifiers & lateMask) != 0;
+
+  bool get isCovariantByDeclaration => (modifiers & covariantMask) != 0;
+
+  bool get hasInitializer => (modifiers & hasInitializerMask) != 0;
+
+  /// Builds the body of this field using [initializer] as the initializer
+  /// expression.
+  void buildBody(CoreTypes coreTypes, Expression? initializer) {
+    assert(!hasBodyBeenBuilt);
+    hasBodyBeenBuilt = true;
+    if (!hasInitializer &&
+        initializer != null &&
+        initializer is! NullLiteral &&
+        !isConst &&
+        !isFinal) {
+      internalProblem(
+          messageInternalProblemAlreadyInitialized, charOffset, fileUri);
+    }
+    _fieldEncoding.createBodies(coreTypes, initializer);
+  }
+
+  /// Builds the field initializers for each field used to encode this field
+  /// using the [fileOffset] for the created nodes and [value] as the initial
+  /// field value.
+  List<Initializer> buildInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic}) {
+    return _fieldEncoding.createInitializer(fileOffset, value,
+        isSynthetic: isSynthetic);
+  }
+
+  bool get isEligibleForInference {
+    return type == null && (hasInitializer || isClassInstanceMember);
+  }
+
+  @override
+  bool get isAssignable {
+    if (isConst) return false;
+    if (isFinal) {
+      if (isLate) {
+        return !hasInitializer;
+      }
+      return false;
+    }
+    return true;
+  }
+
+  @override
+  Field get field => _fieldEncoding.field;
+
+  @override
+  Member get readTarget => _fieldEncoding.readTarget;
+
+  @override
+  Member? get writeTarget {
+    return isAssignable ? _fieldEncoding.writeTarget : null;
+  }
+
+  @override
+  Member get invokeTarget => readTarget;
+
+  @override
+  Iterable<Member> get exportedMembers => _fieldEncoding.exportedMembers;
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    build(library);
+    _fieldEncoding.registerMembers(library, this, f);
+  }
+
+  /// Builds the core AST structures for this field as needed for the outline.
+  void build(SourceLibraryBuilder libraryBuilder) {
+    if (type != null) {
+      fieldType = type!.build(libraryBuilder);
+    }
+    _fieldEncoding.build(libraryBuilder, this);
+  }
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    _fieldEncoding.completeSignature(classHierarchy.coreTypes);
+
+    for (Annotatable annotatable in _fieldEncoding.annotatables) {
+      MetadataBuilder.buildAnnotations(
+          annotatable,
+          metadata,
+          library,
+          declarationBuilder,
+          this,
+          fileUri,
+          declarationBuilder?.scope ?? library.scope);
+    }
+
+    // For modular compilation we need to include initializers of all const
+    // fields and all non-static final fields in classes with const constructors
+    // into the outline.
+    if ((isConst ||
+            (isFinal &&
+                !isStatic &&
+                isClassMember &&
+                classBuilder!.declaresConstConstructor)) &&
+        _constInitializerToken != null) {
+      Scope scope = declarationBuilder?.scope ?? library.scope;
+      BodyBuilder bodyBuilder = library.loader
+          .createBodyBuilderForOutlineExpression(
+              library, declarationBuilder, this, scope, fileUri);
+      bodyBuilder.constantContext =
+          isConst ? ConstantContext.inferred : ConstantContext.required;
+      Expression initializer = bodyBuilder.typeInferrer
+          .inferFieldInitializer(bodyBuilder, fieldType,
+              bodyBuilder.parseFieldInitializer(_constInitializerToken!))
+          .expression;
+      if (bodyBuilder.transformSetLiterals ||
+          bodyBuilder.transformCollections) {
+        // Wrap the initializer in a temporary parent expression; the
+        // transformations need a parent relation.
+        Not wrapper = new Not(initializer);
+        SourceLoader loader = library.loader;
+        loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
+            bodyBuilder.transformCollections, library.library);
+        initializer = wrapper.operand;
+      }
+      buildBody(classHierarchy.coreTypes, initializer);
+      bodyBuilder.performBacklogComputations(delayedActionPerformers);
+    }
+    _constInitializerToken = null;
+  }
+
+  DartType get fieldType => _fieldEncoding.type;
+
+  void set fieldType(DartType value) {
+    _fieldEncoding.type = value;
+    if (!isFinal && !isConst && parent is ClassBuilder) {
+      Class enclosingClass = classBuilder!.cls;
+      if (enclosingClass.typeParameters.isNotEmpty) {
+        IncludesTypeParametersNonCovariantly needsCheckVisitor =
+            new IncludesTypeParametersNonCovariantly(
+                enclosingClass.typeParameters,
+                // We are checking the field type as if it is the type of the
+                // parameter of the implicit setter and this is a contravariant
+                // position.
+                initialVariance: Variance.contravariant);
+        if (value.accept(needsCheckVisitor)) {
+          _fieldEncoding.setGenericCovariantImpl();
+        }
+      }
+    }
+  }
+
+  DartType inferType() {
+    SourceLibraryBuilder library = this.library;
+    if (fieldType is! ImplicitFieldType) {
+      // We have already inferred a type.
+      return fieldType;
+    }
+
+    ImplicitFieldType implicitFieldType = fieldType as ImplicitFieldType;
+    DartType inferredType = implicitFieldType.computeType();
+    if (fieldType is ImplicitFieldType) {
+      // `fieldType` may have changed if a circularity was detected when
+      // [inferredType] was computed.
+      if (!library.isNonNullableByDefault) {
+        inferredType = legacyErasure(inferredType);
+      }
+      fieldType = implicitFieldType.checkInferred(inferredType);
+
+      IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+      if (parent is ClassBuilder) {
+        Class enclosingClass = classBuilder!.cls;
+        if (enclosingClass.typeParameters.isNotEmpty) {
+          needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
+              enclosingClass.typeParameters,
+              // We are checking the field type as if it is the type of the
+              // parameter of the implicit setter and this is a contravariant
+              // position.
+              initialVariance: Variance.contravariant);
+        }
+      }
+      if (needsCheckVisitor != null) {
+        if (fieldType.accept(needsCheckVisitor)) {
+          _fieldEncoding.setGenericCovariantImpl();
+        }
+      }
+    }
+    return fieldType;
+  }
+
+  DartType get builtType => fieldType;
+
+  List<ClassMember>? _localMembers;
+  List<ClassMember>? _localSetters;
+
+  @override
+  List<ClassMember> get localMembers =>
+      _localMembers ??= _fieldEncoding.getLocalMembers(this);
+
+  @override
+  List<ClassMember> get localSetters =>
+      _localSetters ??= _fieldEncoding.getLocalSetters(this);
+}
+
+/// Strategy pattern for creating different encodings of a declared field.
+///
+/// This is used to provide lowerings for late fields using synthesized getters
+/// and setters.
+abstract class FieldEncoding {
+  /// The type of the declared field.
+  abstract DartType type;
+
+  /// Creates the bodies needed for the field encoding using [initializer] as
+  /// the declared initializer expression.
+  ///
+  /// This method is not called for fields in outlines unless their are constant
+  /// or part of a const constructor.
+  void createBodies(CoreTypes coreTypes, Expression? initializer);
+
+  List<Initializer> createInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic});
+
+  /// Registers that the (implicit) setter associated with this field needs to
+  /// contain a runtime type check to deal with generic covariance.
+  void setGenericCovariantImpl();
+
+  /// Returns the field that holds the field value at runtime.
+  Field get field;
+
+  /// Returns the members that holds the field annotations.
+  Iterable<Annotatable> get annotatables;
+
+  /// Returns the member used to read the field value.
+  Member get readTarget;
+
+  /// Returns the member used to write to the field.
+  Member? get writeTarget;
+
+  /// Returns the generated members that are visible through exports.
+  Iterable<Member> get exportedMembers;
+
+  /// Creates the members necessary for this field encoding.
+  ///
+  /// This method is called for both outline and full compilation so the created
+  /// members should be without body. The member bodies are created through
+  /// [createBodies].
+  void build(
+      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder);
+
+  /// Calls [f] for each member needed for this field encoding.
+  void registerMembers(
+      SourceLibraryBuilder library,
+      SourceFieldBuilder fieldBuilder,
+      void Function(Member, BuiltMemberKind) f);
+
+  /// Returns a list of the field, getters and methods created by this field
+  /// encoding.
+  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder);
+
+  /// Returns a list of the setters created by this field encoding.
+  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder);
+
+  /// Ensures that the signatures all members created by this field encoding
+  /// are fully typed.
+  void completeSignature(CoreTypes coreTypes);
+
+  /// Returns `true` if this encoding is a late lowering.
+  bool get isLateLowering;
+}
+
+class RegularFieldEncoding implements FieldEncoding {
+  late final Field _field;
+
+  RegularFieldEncoding(String name, NameScheme nameScheme, Uri fileUri,
+      int charOffset, int charEndOffset,
+      {required bool isFinal,
+      required bool isConst,
+      required bool isLate,
+      required bool hasInitializer,
+      required bool isNonNullableByDefault,
+      required Reference? fieldReference,
+      required Reference? getterReference,
+      required Reference? setterReference}) {
+    // ignore: unnecessary_null_comparison
+    assert(isFinal != null);
+    // ignore: unnecessary_null_comparison
+    assert(isConst != null);
+    // ignore: unnecessary_null_comparison
+    assert(isLate != null);
+    // ignore: unnecessary_null_comparison
+    assert(hasInitializer != null);
+    bool isImmutable =
+        isLate ? (isFinal && hasInitializer) : (isFinal || isConst);
+    _field = isImmutable
+        ? new Field.immutable(
+            nameScheme.getFieldName(FieldNameType.Field, name,
+                isSynthesized: false),
+            isFinal: isFinal,
+            isConst: isConst,
+            isLate: isLate,
+            fileUri: fileUri,
+            fieldReference: fieldReference,
+            getterReference: getterReference)
+        : new Field.mutable(
+            nameScheme.getFieldName(FieldNameType.Field, name,
+                isSynthesized: false),
+            isFinal: isFinal,
+            isLate: isLate,
+            fileUri: fileUri,
+            fieldReference: fieldReference,
+            getterReference: getterReference,
+            setterReference: setterReference);
+    _field
+      ..fileOffset = charOffset
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = isNonNullableByDefault;
+  }
+
+  @override
+  DartType get type => _field.type;
+
+  @override
+  void set type(DartType value) {
+    _field.type = value;
+  }
+
+  @override
+  void completeSignature(CoreTypes coreTypes) {}
+
+  @override
+  void createBodies(CoreTypes coreTypes, Expression? initializer) {
+    if (initializer != null) {
+      _field.initializer = initializer..parent = _field;
+    }
+  }
+
+  @override
+  List<Initializer> createInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic}) {
+    return <Initializer>[
+      new FieldInitializer(_field, value)
+        ..fileOffset = fileOffset
+        ..isSynthetic = isSynthetic
+    ];
+  }
+
+  @override
+  void build(
+      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+    _field..isCovariantByDeclaration = fieldBuilder.isCovariantByDeclaration;
+    if (fieldBuilder.isExtensionMember) {
+      _field
+        ..isStatic = true
+        ..isExtensionMember = true;
+    } else {
+      bool isInstanceMember =
+          !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+      _field
+        ..isStatic = !isInstanceMember
+        ..isExtensionMember = false;
+    }
+    _field.isLate = fieldBuilder.isLate;
+    updatePrivateMemberName(_field, libraryBuilder);
+  }
+
+  @override
+  void registerMembers(
+      SourceLibraryBuilder library,
+      SourceFieldBuilder fieldBuilder,
+      void Function(Member, BuiltMemberKind) f) {
+    f(
+        _field,
+        fieldBuilder.isExtensionMember
+            ? BuiltMemberKind.ExtensionField
+            : BuiltMemberKind.Field);
+  }
+
+  @override
+  void setGenericCovariantImpl() {
+    _field.isCovariantByClass = true;
+  }
+
+  @override
+  Field get field => _field;
+
+  @override
+  Iterable<Annotatable> get annotatables => [_field];
+
+  @override
+  Member get readTarget => _field;
+
+  @override
+  Member get writeTarget => _field;
+
+  @override
+  Iterable<Member> get exportedMembers => [_field];
+
+  @override
+  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
+      <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: false)];
+
+  @override
+  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
+      fieldBuilder.isAssignable
+          ? <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: true)]
+          : const <ClassMember>[];
+
+  @override
+  bool get isLateLowering => false;
+}
+
+class SourceFieldMember extends BuilderClassMember {
+  @override
+  final SourceFieldBuilder memberBuilder;
+
+  Covariance? _covariance;
+
+  @override
+  final bool forSetter;
+
+  SourceFieldMember(this.memberBuilder, {required this.forSetter})
+      // ignore: unnecessary_null_comparison
+      : assert(forSetter != null);
+
+  @override
+  void inferType(ClassMembersBuilder membersBuilder) {
+    memberBuilder._ensureType(membersBuilder);
+  }
+
+  @override
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    memberBuilder.registerOverrideDependency(overriddenMembers);
+  }
+
+  @override
+  Member getMember(ClassMembersBuilder membersBuilder) {
+    memberBuilder._ensureType(membersBuilder);
+    return memberBuilder.field;
+  }
+
+  @override
+  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+    return _covariance ??= forSetter
+        ? new Covariance.fromMember(getMember(membersBuilder),
+            forSetter: forSetter)
+        : const Covariance.empty();
+  }
+
+  @override
+  bool get isSourceDeclaration => true;
+
+  @override
+  bool get isProperty => true;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    return other is SourceFieldMember && memberBuilder == other.memberBuilder;
+  }
+}
+
+abstract class AbstractLateFieldEncoding implements FieldEncoding {
+  final String name;
+  final int fileOffset;
+  final int fileEndOffset;
+  DartType? _type;
+  late final Field _field;
+  Field? _lateIsSetField;
+  late Procedure _lateGetter;
+  Procedure? _lateSetter;
+
+  // If `true`, an isSet field is used even when the type of the field is
+  // not potentially nullable.
+  //
+  // This is used to force use isSet fields in mixed mode encoding since
+  // we cannot trust non-nullable fields to be initialized with non-null values.
+  final late_lowering.IsSetStrategy _isSetStrategy;
+  late_lowering.IsSetEncoding? _isSetEncoding;
+
+  // If `true`, the is-set field was register before the type was known to be
+  // nullable or non-nullable. In this case we do not try to remove it from
+  // the generated AST to avoid inconsistency between the class hierarchy used
+  // during and after inference.
+  //
+  // This is also used to force use isSet fields in mixed mode encoding since
+  // we cannot trust non-nullable fields to be initialized with non-null values.
+  bool _forceIncludeIsSetField;
+
+  AbstractLateFieldEncoding(
+      this.name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      bool isCovariantByDeclaration,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : fileOffset = charOffset,
+        fileEndOffset = charEndOffset,
+        _isSetStrategy = isSetStrategy,
+        _forceIncludeIsSetField =
+            isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
+    _field = new Field.mutable(
+        nameScheme.getFieldName(FieldNameType.Field, name, isSynthesized: true),
+        fileUri: fileUri,
+        fieldReference: fieldReference,
+        getterReference: fieldGetterReference,
+        setterReference: fieldSetterReference)
+      ..fileOffset = charOffset
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = true
+      ..isInternalImplementation = true;
+    switch (_isSetStrategy) {
+      case late_lowering.IsSetStrategy.useSentinelOrNull:
+      case late_lowering.IsSetStrategy.forceUseSentinel:
+        // [_lateIsSetField] is never needed.
+        break;
+      case late_lowering.IsSetStrategy.forceUseIsSetField:
+      case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
+        _lateIsSetField = new Field.mutable(
+            nameScheme.getFieldName(FieldNameType.IsSetField, name,
+                isSynthesized: true),
+            fileUri: fileUri,
+            fieldReference: lateIsSetFieldReference,
+            getterReference: lateIsSetGetterReference,
+            setterReference: lateIsSetSetterReference)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = true
+          ..isInternalImplementation = true;
+        break;
+    }
+    _lateGetter = new Procedure(
+        nameScheme.getFieldName(FieldNameType.Getter, name,
+            isSynthesized: true),
+        ProcedureKind.Getter,
+        new FunctionNode(null)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset,
+        fileUri: fileUri,
+        reference: lateGetterReference)
+      ..fileOffset = charOffset
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = true;
+    _lateSetter = _createSetter(
+        nameScheme.getFieldName(FieldNameType.Setter, name,
+            isSynthesized: true),
+        fileUri,
+        charOffset,
+        lateSetterReference,
+        isCovariantByDeclaration: isCovariantByDeclaration);
+  }
+
+  late_lowering.IsSetEncoding get isSetEncoding {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return _isSetEncoding ??=
+        late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
+  }
+
+  @override
+  void completeSignature(CoreTypes coreTypes) {
+    _lateIsSetField?.type = coreTypes.boolRawType(Nullability.nonNullable);
+  }
+
+  @override
+  void createBodies(CoreTypes coreTypes, Expression? initializer) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
+      _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
+          new Arguments([], types: [_type!])..fileOffset = fileOffset)
+        ..fileOffset = fileOffset
+        ..parent = _field;
+    } else {
+      _field.initializer = new NullLiteral()
+        ..fileOffset = fileOffset
+        ..parent = _field;
+    }
+    if (_lateIsSetField != null) {
+      _lateIsSetField!.initializer = new BoolLiteral(false)
+        ..fileOffset = fileOffset
+        ..parent = _lateIsSetField;
+    }
+    _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
+      ..parent = _lateGetter.function;
+    if (_lateSetter != null) {
+      _lateSetter!.function.body = _createSetterBody(
+          coreTypes, name, _lateSetter!.function.positionalParameters.first)
+        ..parent = _lateSetter!.function;
+    }
+  }
+
+  @override
+  List<Initializer> createInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic}) {
+    List<Initializer> initializers = <Initializer>[];
+    if (_lateIsSetField != null) {
+      initializers.add(new FieldInitializer(
+          _lateIsSetField!, new BoolLiteral(true)..fileOffset = fileOffset)
+        ..fileOffset = fileOffset
+        ..isSynthetic = isSynthetic);
+    }
+    initializers.add(new FieldInitializer(_field, value)
+      ..fileOffset = fileOffset
+      ..isSynthetic = isSynthetic);
+    return initializers;
+  }
+
+  /// Creates an [Expression] that reads [_field].
+  ///
+  /// If [needsPromotion] is `true`, the field will be read through a `let`
+  /// expression that promotes the expression to [_type]. This is needed for a
+  /// sound encoding of fields with type variable type of undetermined
+  /// nullability.
+  Expression _createFieldRead({bool needsPromotion: false}) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    if (needsPromotion) {
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          _createFieldGet(_field),
+          type: _type!.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new Let(
+          variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
+    } else {
+      return _createFieldGet(_field);
+    }
+  }
+
+  /// Creates an [Expression] that reads [field].
+  Expression _createFieldGet(Field field) {
+    if (field.isStatic) {
+      return new StaticGet(field)..fileOffset = fileOffset;
+    } else {
+      // No substitution needed for the result type, since any type variables
+      // in there are also in scope at the access site.
+      return new InstanceGet(InstanceAccessKind.Instance,
+          new ThisExpression()..fileOffset = fileOffset, field.name,
+          interfaceTarget: field, resultType: field.type)
+        ..fileOffset = fileOffset;
+    }
+  }
+
+  /// Creates an [Expression] that writes [value] to [field].
+  Expression _createFieldSet(Field field, Expression value) {
+    if (field.isStatic) {
+      return new StaticSet(field, value)..fileOffset = fileOffset;
+    } else {
+      return new InstanceSet(InstanceAccessKind.Instance,
+          new ThisExpression()..fileOffset = fileOffset, field.name, value,
+          interfaceTarget: field)
+        ..fileOffset = fileOffset;
+    }
+  }
+
+  Statement _createGetterBody(
+      CoreTypes coreTypes, String name, Expression? initializer);
+
+  Procedure? _createSetter(
+      Name name, Uri fileUri, int charOffset, Reference? reference,
+      {required bool isCovariantByDeclaration}) {
+    // ignore: unnecessary_null_comparison
+    assert(isCovariantByDeclaration != null);
+    VariableDeclaration parameter = new VariableDeclaration("${name}#param")
+      ..isCovariantByDeclaration = isCovariantByDeclaration
+      ..fileOffset = fileOffset;
+    return new Procedure(
+        name,
+        ProcedureKind.Setter,
+        new FunctionNode(null,
+            positionalParameters: [parameter], returnType: const VoidType())
+          ..fileOffset = charOffset
+          ..fileEndOffset = fileEndOffset,
+        fileUri: fileUri,
+        reference: reference)
+      ..fileOffset = charOffset
+      ..fileEndOffset = fileEndOffset
+      ..isNonNullableByDefault = true;
+  }
+
+  Statement _createSetterBody(
+      CoreTypes coreTypes, String name, VariableDeclaration parameter);
+
+  @override
+  DartType get type {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return _type!;
+  }
+
+  @override
+  void set type(DartType value) {
+    assert(_type == null || _type is ImplicitFieldType,
+        "Type has already been computed for field $name.");
+    _type = value;
+    if (value is! ImplicitFieldType) {
+      _field.type = value.withDeclaredNullability(Nullability.nullable);
+      _lateGetter.function.returnType = value;
+      if (_lateSetter != null) {
+        _lateSetter!.function.positionalParameters.single.type = value;
+      }
+      if (!_type!.isPotentiallyNullable && !_forceIncludeIsSetField) {
+        // We only need the is-set field if the field is potentially nullable.
+        //  Otherwise we use `null` to signal that the field is uninitialized.
+        _lateIsSetField = null;
+      }
+    }
+  }
+
+  @override
+  void setGenericCovariantImpl() {
+    _field.isCovariantByClass = true;
+    _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
+  }
+
+  @override
+  Field get field => _field;
+
+  @override
+  Iterable<Annotatable> get annotatables {
+    List<Annotatable> list = [_lateGetter];
+    if (_lateSetter != null) {
+      list.add(_lateSetter!);
+    }
+    return list;
+  }
+
+  @override
+  Member get readTarget => _lateGetter;
+
+  @override
+  Member? get writeTarget => _lateSetter;
+
+  @override
+  Iterable<Member> get exportedMembers {
+    if (_lateSetter != null) {
+      return [_lateGetter, _lateSetter!];
+    }
+    return [_lateGetter];
+  }
+
+  @override
+  void build(
+      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+    bool isInstanceMember;
+    bool isExtensionMember = fieldBuilder.isExtensionMember;
+    if (isExtensionMember) {
+      _field
+        ..isStatic = true
+        ..isExtensionMember = isExtensionMember;
+      isInstanceMember = false;
+    } else {
+      isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+      _field
+        ..isStatic = !isInstanceMember
+        ..isExtensionMember = false;
+    }
+    updatePrivateMemberName(_field, libraryBuilder);
+    if (_lateIsSetField != null) {
+      _lateIsSetField!
+        ..isStatic = !isInstanceMember
+        ..isStatic = _field.isStatic
+        ..isExtensionMember = isExtensionMember;
+      updatePrivateMemberName(_lateIsSetField!, libraryBuilder);
+    }
+    _lateGetter
+      ..isStatic = !isInstanceMember
+      ..isExtensionMember = isExtensionMember;
+    updatePrivateMemberName(_lateGetter, libraryBuilder);
+    if (_lateSetter != null) {
+      _lateSetter!
+        ..isStatic = !isInstanceMember
+        ..isExtensionMember = isExtensionMember;
+      updatePrivateMemberName(_lateSetter!, libraryBuilder);
+    }
+  }
+
+  @override
+  void registerMembers(
+      SourceLibraryBuilder library,
+      SourceFieldBuilder fieldBuilder,
+      void Function(Member, BuiltMemberKind) f) {
+    f(
+        _field,
+        fieldBuilder.isExtensionMember
+            ? BuiltMemberKind.ExtensionField
+            : BuiltMemberKind.Field);
+    if (_lateIsSetField != null) {
+      _forceIncludeIsSetField = true;
+      f(_lateIsSetField!, BuiltMemberKind.LateIsSetField);
+    }
+    f(_lateGetter, BuiltMemberKind.LateGetter);
+    if (_lateSetter != null) {
+      f(_lateSetter!, BuiltMemberKind.LateSetter);
+    }
+  }
+
+  @override
+  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
+    List<ClassMember> list = <ClassMember>[
+      new _SynthesizedFieldClassMember(
+          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
+          isInternalImplementation: true),
+      new _SynthesizedFieldClassMember(fieldBuilder, _lateGetter,
+          _SynthesizedFieldMemberKind.LateGetterSetter,
+          isInternalImplementation: false)
+    ];
+    if (_lateIsSetField != null) {
+      list.add(new _SynthesizedFieldClassMember(
+          fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
+          isInternalImplementation: true));
+    }
+    return list;
+  }
+
+  @override
+  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
+    List<ClassMember> list = <ClassMember>[
+      new _SynthesizedFieldClassMember(
+          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
+          forSetter: true, isInternalImplementation: true),
+    ];
+    if (_lateIsSetField != null) {
+      list.add(new _SynthesizedFieldClassMember(
+          fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
+          forSetter: true, isInternalImplementation: true));
+    }
+    if (_lateSetter != null) {
+      list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateSetter!,
+          _SynthesizedFieldMemberKind.LateGetterSetter,
+          forSetter: true, isInternalImplementation: false));
+    }
+    return list;
+  }
+
+  @override
+  bool get isLateLowering => true;
+}
+
+mixin NonFinalLate on AbstractLateFieldEncoding {
+  @override
+  Statement _createSetterBody(
+      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return late_lowering.createSetterBody(
+        coreTypes, fileOffset, name, parameter, _type!,
+        shouldReturnValue: false,
+        createVariableWrite: (Expression value) =>
+            _createFieldSet(_field, value),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
+        isSetEncoding: isSetEncoding);
+  }
+}
+
+mixin LateWithoutInitializer on AbstractLateFieldEncoding {
+  @override
+  Statement _createGetterBody(
+      CoreTypes coreTypes, String name, Expression? initializer) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return late_lowering.createGetterBodyWithoutInitializer(
+        coreTypes, fileOffset, name, type,
+        createVariableRead: _createFieldRead,
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        isSetEncoding: isSetEncoding,
+        forField: true);
+  }
+}
+
+class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+    with NonFinalLate, LateWithoutInitializer {
+  LateFieldWithoutInitializerEncoding(
+      String name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      bool isCovariantByDeclaration,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : super(
+            name,
+            nameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+}
+
+class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
+    with NonFinalLate {
+  LateFieldWithInitializerEncoding(
+      String name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      bool isCovariantByDeclaration,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : super(
+            name,
+            nameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+
+  @override
+  Statement _createGetterBody(
+      CoreTypes coreTypes, String name, Expression? initializer) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return late_lowering.createGetterWithInitializer(
+        coreTypes, fileOffset, name, _type!, initializer!,
+        createVariableRead: _createFieldRead,
+        createVariableWrite: (Expression value) =>
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
+        isSetEncoding: isSetEncoding);
+  }
+}
+
+class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+    with LateWithoutInitializer {
+  LateFinalFieldWithoutInitializerEncoding(
+      String name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      bool isCovariantByDeclaration,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : super(
+            name,
+            nameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+
+  @override
+  Statement _createSetterBody(
+      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return late_lowering.createSetterBodyFinal(
+        coreTypes, fileOffset, name, parameter, type,
+        shouldReturnValue: false,
+        createVariableRead: () => _createFieldGet(_field),
+        createVariableWrite: (Expression value) =>
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
+        isSetEncoding: isSetEncoding,
+        forField: true);
+  }
+}
+
+class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
+  LateFinalFieldWithInitializerEncoding(
+      String name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? fieldReference,
+      Reference? fieldGetterReference,
+      Reference? fieldSetterReference,
+      Reference? lateIsSetFieldReference,
+      Reference? lateIsSetGetterReference,
+      Reference? lateIsSetSetterReference,
+      Reference? lateGetterReference,
+      Reference? lateSetterReference,
+      bool isCovariantByDeclaration,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : super(
+            name,
+            nameScheme,
+            fileUri,
+            charOffset,
+            charEndOffset,
+            fieldReference,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetFieldReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            lateGetterReference,
+            lateSetterReference,
+            isCovariantByDeclaration,
+            isSetStrategy);
+
+  @override
+  Statement _createGetterBody(
+      CoreTypes coreTypes, String name, Expression? initializer) {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return late_lowering.createGetterWithInitializerWithRecheck(
+        coreTypes, fileOffset, name, _type!, initializer!,
+        createVariableRead: _createFieldRead,
+        createVariableWrite: (Expression value) =>
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
+        isSetEncoding: isSetEncoding,
+        forField: true);
+  }
+
+  @override
+  Procedure? _createSetter(
+          Name name, Uri fileUri, int charOffset, Reference? reference,
+          {required bool isCovariantByDeclaration}) =>
+      null;
+
+  @override
+  Statement _createSetterBody(
+          CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
+      throw new UnsupportedError(
+          '$runtimeType._createSetterBody is not supported.');
+}
+
+class _SynthesizedFieldClassMember implements ClassMember {
+  final SourceFieldBuilder fieldBuilder;
+  final _SynthesizedFieldMemberKind _kind;
+
+  final Member _member;
+
+  Covariance? _covariance;
+
+  @override
+  final bool forSetter;
+
+  @override
+  final bool isInternalImplementation;
+
+  _SynthesizedFieldClassMember(this.fieldBuilder, this._member, this._kind,
+      {this.forSetter: false, required this.isInternalImplementation})
+      // ignore: unnecessary_null_comparison
+      : assert(isInternalImplementation != null);
+
+  @override
+  Member getMember(ClassMembersBuilder membersBuilder) {
+    fieldBuilder._ensureType(membersBuilder);
+    return _member;
+  }
+
+  @override
+  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+    return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
+        forSetter: forSetter);
+  }
+
+  @override
+  void inferType(ClassMembersBuilder membersBuilder) {
+    fieldBuilder._ensureType(membersBuilder);
+  }
+
+  @override
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    fieldBuilder.registerOverrideDependency(overriddenMembers);
+  }
+
+  @override
+  bool get isSourceDeclaration => true;
+
+  @override
+  bool get isProperty => isField || isGetter || isSetter;
+
+  @override
+  ClassBuilder get classBuilder => fieldBuilder.classBuilder!;
+
+  @override
+  bool isObjectMember(ClassBuilder objectClass) {
+    return classBuilder == objectClass;
+  }
+
+  @override
+  bool get isDuplicate => fieldBuilder.isDuplicate;
+
+  @override
+  bool get isStatic => fieldBuilder.isStatic;
+
+  @override
+  bool get isField => _member is Field;
+
+  @override
+  bool get isAssignable {
+    Member field = _member;
+    return field is Field && field.hasSetter;
+  }
+
+  @override
+  bool get isSetter {
+    Member procedure = _member;
+    return procedure is Procedure && procedure.kind == ProcedureKind.Setter;
+  }
+
+  @override
+  bool get isGetter {
+    Member procedure = _member;
+    return procedure is Procedure && procedure.kind == ProcedureKind.Getter;
+  }
+
+  @override
+  bool get isFinal {
+    Member field = _member;
+    return field is Field && field.isFinal;
+  }
+
+  @override
+  bool get isConst {
+    Member field = _member;
+    return field is Field && field.isConst;
+  }
+
+  @override
+  Name get name => _member.name;
+
+  @override
+  String get fullName {
+    String suffix = isSetter ? "=" : "";
+    String className = classBuilder.fullNameForErrors;
+    // ignore: unnecessary_null_comparison
+    return className == null
+        ? "${fullNameForErrors}$suffix"
+        : "${className}.${fullNameForErrors}$suffix";
+  }
+
+  @override
+  String get fullNameForErrors => fieldBuilder.fullNameForErrors;
+
+  @override
+  Uri get fileUri => fieldBuilder.fileUri;
+
+  @override
+  int get charOffset => fieldBuilder.charOffset;
+
+  @override
+  bool get isAbstract => _member.isAbstract;
+
+  @override
+  bool get isSynthesized => false;
+
+  @override
+  bool get hasDeclarations => false;
+
+  @override
+  List<ClassMember> get declarations =>
+      throw new UnsupportedError("$runtimeType.declarations");
+
+  @override
+  ClassMember get interfaceMember => this;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    if (identical(this, other)) return true;
+    return other is _SynthesizedFieldClassMember &&
+        fieldBuilder == other.fieldBuilder &&
+        _kind == other._kind;
+  }
+
+  @override
+  String toString() => '_SynthesizedFieldClassMember('
+      '$fieldBuilder,$_member,$_kind,forSetter=${forSetter})';
+}
+
+class AbstractOrExternalFieldEncoding implements FieldEncoding {
+  final SourceFieldBuilder _fieldBuilder;
+  final bool isAbstract;
+  final bool isExternal;
+  final bool _isExtensionInstanceMember;
+
+  late Procedure _getter;
+  Procedure? _setter;
+  DartType? _type;
+
+  AbstractOrExternalFieldEncoding(
+      this._fieldBuilder,
+      String name,
+      NameScheme nameScheme,
+      Uri fileUri,
+      int charOffset,
+      int charEndOffset,
+      Reference? getterReference,
+      Reference? setterReference,
+      {required this.isAbstract,
+      required this.isExternal,
+      required bool isFinal,
+      required bool isCovariantByDeclaration,
+      required bool isNonNullableByDefault})
+      // ignore: unnecessary_null_comparison
+      : assert(isAbstract != null),
+        // ignore: unnecessary_null_comparison
+        assert(isExternal != null),
+        // ignore: unnecessary_null_comparison
+        assert(isFinal != null),
+        // ignore: unnecessary_null_comparison
+        assert(isCovariantByDeclaration != null),
+        // ignore: unnecessary_null_comparison
+        assert(isNonNullableByDefault != null),
+        _isExtensionInstanceMember = isExternal &&
+            nameScheme.isExtensionMember &&
+            nameScheme.isInstanceMember {
+    if (_isExtensionInstanceMember) {
+      _getter = new Procedure(
+          nameScheme.getProcedureName(ProcedureKind.Getter, name),
+          ProcedureKind.Method,
+          new FunctionNode(null, positionalParameters: [
+            new VariableDeclaration(extensionThisName)..fileOffset
+          ]),
+          fileUri: fileUri,
+          reference: getterReference)
+        ..fileOffset = charOffset
+        ..fileEndOffset = charEndOffset
+        ..isNonNullableByDefault = isNonNullableByDefault;
+      if (!isFinal) {
+        VariableDeclaration parameter =
+            new VariableDeclaration("#externalFieldValue")
+              ..isCovariantByDeclaration = isCovariantByDeclaration
+              ..fileOffset = charOffset;
+        _setter = new Procedure(
+            nameScheme.getProcedureName(ProcedureKind.Setter, name),
+            ProcedureKind.Method,
+            new FunctionNode(null,
+                positionalParameters: [
+                  new VariableDeclaration(extensionThisName)..fileOffset,
+                  parameter
+                ],
+                returnType: const VoidType())
+              ..fileOffset = charOffset
+              ..fileEndOffset = charEndOffset,
+            fileUri: fileUri,
+            reference: setterReference)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = isNonNullableByDefault;
+      }
+    } else {
+      _getter = new Procedure(
+          nameScheme.getFieldName(FieldNameType.Getter, name,
+              isSynthesized: true),
+          ProcedureKind.Getter,
+          new FunctionNode(null),
+          fileUri: fileUri,
+          reference: getterReference)
+        ..fileOffset = charOffset
+        ..fileEndOffset = charEndOffset
+        ..isNonNullableByDefault = isNonNullableByDefault;
+      if (!isFinal) {
+        VariableDeclaration parameter =
+            new VariableDeclaration("#externalFieldValue")
+              ..isCovariantByDeclaration = isCovariantByDeclaration
+              ..fileOffset = charOffset;
+        _setter = new Procedure(
+            nameScheme.getFieldName(FieldNameType.Setter, name,
+                isSynthesized: true),
+            ProcedureKind.Setter,
+            new FunctionNode(null,
+                positionalParameters: [parameter], returnType: const VoidType())
+              ..fileOffset = charOffset
+              ..fileEndOffset = charEndOffset,
+            fileUri: fileUri,
+            reference: setterReference)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = isNonNullableByDefault;
+      }
+    }
+  }
+
+  @override
+  DartType get type {
+    assert(_type != null,
+        "Type has not been computed for field ${_fieldBuilder.name}.");
+    return _type!;
+  }
+
+  @override
+  void set type(DartType value) {
+    assert(_type == null || _type is ImplicitFieldType,
+        "Type has already been computed for field ${_fieldBuilder.name}.");
+    _type = value;
+    if (value is! ImplicitFieldType) {
+      if (_isExtensionInstanceMember) {
+        SourceExtensionBuilder extensionBuilder =
+            _fieldBuilder.parent as SourceExtensionBuilder;
+        DartType onType = extensionBuilder.extension.onType;
+        List<TypeParameter> typeParameters =
+            extensionBuilder.extension.typeParameters;
+        if (typeParameters.isNotEmpty) {
+          FreshTypeParameters getterTypeParameters =
+              getFreshTypeParameters(typeParameters);
+          _getter.function.positionalParameters.first.type =
+              getterTypeParameters.substitute(onType);
+          _getter.function.returnType = getterTypeParameters.substitute(value);
+          _getter.function.typeParameters =
+              getterTypeParameters.freshTypeParameters;
+          setParents(
+              getterTypeParameters.freshTypeParameters, _getter.function);
+
+          Procedure? setter = _setter;
+          if (setter != null) {
+            FreshTypeParameters setterTypeParameters =
+                getFreshTypeParameters(typeParameters);
+            setter.function.positionalParameters.first.type =
+                setterTypeParameters.substitute(onType);
+            setter.function.positionalParameters[1].type =
+                setterTypeParameters.substitute(value);
+            setter.function.typeParameters =
+                setterTypeParameters.freshTypeParameters;
+            setParents(
+                setterTypeParameters.freshTypeParameters, setter.function);
+          }
+        } else {
+          _getter.function.returnType = value;
+          _setter?.function.positionalParameters[1].type = value;
+          _getter.function.positionalParameters.first.type = onType;
+          _setter?.function.positionalParameters.first.type = onType;
+        }
+      } else {
+        _getter.function.returnType = value;
+        Procedure? setter = _setter;
+        if (setter != null) {
+          if (setter.kind == ProcedureKind.Method) {
+            setter.function.positionalParameters[1].type = value;
+          } else {
+            setter.function.positionalParameters.first.type = value;
+          }
+        }
+      }
+    }
+  }
+
+  @override
+  void completeSignature(CoreTypes coreTypes) {}
+
+  @override
+  void createBodies(CoreTypes coreTypes, Expression? initializer) {
+    //assert(initializer != null);
+  }
+
+  @override
+  List<Initializer> createInitializer(int fileOffset, Expression value,
+      {required bool isSynthetic}) {
+    throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
+  }
+
+  @override
+  void build(
+      SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+    bool isExtensionMember = fieldBuilder.isExtensionMember;
+    bool isInstanceMember = !fieldBuilder.isExtensionMember &&
+        !fieldBuilder.isStatic &&
+        !fieldBuilder.isTopLevel;
+    _getter..isConst = fieldBuilder.isConst;
+    _getter
+      ..isStatic = !isInstanceMember
+      ..isExtensionMember = isExtensionMember
+      ..isAbstract = isAbstract && !isExternal
+      ..isExternal = isExternal;
+    updatePrivateMemberName(_getter, libraryBuilder);
+
+    if (_setter != null) {
+      _setter!
+        ..isStatic = !isInstanceMember
+        ..isExtensionMember = isExtensionMember
+        ..isAbstract = isAbstract && !isExternal
+        ..isExternal = isExternal;
+      updatePrivateMemberName(_setter!, libraryBuilder);
+    }
+  }
+
+  @override
+  void registerMembers(
+      SourceLibraryBuilder library,
+      SourceFieldBuilder fieldBuilder,
+      void Function(Member, BuiltMemberKind) f) {
+    f(
+        _getter,
+        fieldBuilder.isExtensionMember
+            ? BuiltMemberKind.ExtensionGetter
+            : BuiltMemberKind.Method);
+    if (_setter != null) {
+      f(
+          _setter!,
+          fieldBuilder.isExtensionMember
+              ? BuiltMemberKind.ExtensionSetter
+              : BuiltMemberKind.Method);
+    }
+  }
+
+  @override
+  void setGenericCovariantImpl() {
+    _setter!.function.positionalParameters.first.isCovariantByClass = true;
+  }
+
+  @override
+  Field get field {
+    throw new UnsupportedError("ExternalFieldEncoding.field");
+  }
+
+  @override
+  Iterable<Annotatable> get annotatables {
+    List<Annotatable> list = [_getter];
+    if (_setter != null) {
+      list.add(_setter!);
+    }
+    return list;
+  }
+
+  @override
+  Member get readTarget => _getter;
+
+  @override
+  Member? get writeTarget => _setter;
+
+  @override
+  Iterable<Member> get exportedMembers {
+    if (_setter != null) {
+      return [_getter, _setter!];
+    }
+    return [_getter];
+  }
+
+  @override
+  List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
+      <ClassMember>[
+        new _SynthesizedFieldClassMember(fieldBuilder, _getter,
+            _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+            forSetter: false, isInternalImplementation: false)
+      ];
+
+  @override
+  List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
+      _setter != null
+          ? <ClassMember>[
+              new _SynthesizedFieldClassMember(fieldBuilder, _setter!,
+                  _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+                  forSetter: true, isInternalImplementation: false)
+            ]
+          : const <ClassMember>[];
+
+  @override
+  bool get isLateLowering => false;
+}
+
+enum _SynthesizedFieldMemberKind {
+  /// A `isSet` field used for late lowering.
+  LateIsSet,
+
+  /// A field used for the value of a late lowered field.
+  LateField,
+
+  /// A getter or setter used for late lowering.
+  LateGetterSetter,
+
+  /// A getter or setter used for abstract or external fields.
+  AbstractExternalGetterSetter,
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_function_builder.dart b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart
new file mode 100644
index 0000000..52c156d
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart
@@ -0,0 +1,515 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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.procedure_builder;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/declaration_builder.dart';
+import '../builder/extension_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/function_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../identifiers.dart';
+import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
+import '../kernel/kernel_helper.dart';
+import '../messages.dart'
+    show
+        messagePatchDeclarationMismatch,
+        messagePatchDeclarationOrigin,
+        messagePatchNonExternal,
+        noLength,
+        templateRequiredNamedParameterHasDefaultValueError;
+import '../modifier.dart';
+import '../scope.dart';
+import '../source/source_loader.dart' show SourceLoader;
+import '../type_inference/type_inference_engine.dart'
+    show IncludesTypeParametersNonCovariantly;
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_member_builder.dart';
+
+abstract class SourceFunctionBuilder
+    implements FunctionBuilder, SourceMemberBuilder {
+  List<MetadataBuilder>? get metadata;
+
+  TypeBuilder? get returnType;
+
+  List<TypeVariableBuilder>? get typeVariables;
+
+  List<FormalParameterBuilder>? get formals;
+
+  AsyncMarker get asyncModifier;
+
+  @override
+  ProcedureKind? get kind;
+
+  @override
+  bool get isAbstract;
+
+  @override
+  bool get isConstructor;
+
+  @override
+  bool get isRegularMethod;
+
+  @override
+  bool get isGetter;
+
+  @override
+  bool get isSetter;
+
+  @override
+  bool get isOperator;
+
+  @override
+  bool get isFactory;
+
+  /// This is the formal parameter scope as specified in the Dart Programming
+  /// Language Specification, 4th ed, section 9.2.
+  Scope computeFormalParameterScope(Scope parent);
+
+  Scope computeFormalParameterInitializerScope(Scope parent);
+
+  /// This scope doesn't correspond to any scope specified in the Dart
+  /// Programming Language Specification, 4th ed. It's an unspecified extension
+  /// to support generic methods.
+  Scope computeTypeParameterScope(Scope parent);
+
+  FormalParameterBuilder? getFormal(Identifier identifier);
+
+  String? get nativeMethodName;
+
+  Statement? get body;
+
+  void set body(Statement? newBody);
+
+  @override
+  bool get isNative;
+
+  /// Returns the [index]th parameter of this function.
+  ///
+  /// The index is the syntactical index, including both positional and named
+  /// parameter in the order they are declared, and excluding the synthesized
+  /// this parameter on extension instance members.
+  VariableDeclaration getFormalParameter(int index);
+
+  /// If this is an extension instance method or constructor with lowering
+  /// enabled, the tear off parameter corresponding to the [index]th parameter
+  /// on the instance method or constructor is returned.
+  ///
+  /// This is used to update the default value for the closure parameter when
+  /// it has been computed for the original parameter.
+  VariableDeclaration? getTearOffParameter(int index);
+
+  /// Returns the parameter for 'this' synthetically added to extension
+  /// instance members.
+  VariableDeclaration? get extensionThis;
+
+  /// Returns a list of synthetic type parameters added to extension instance
+  /// members.
+  List<TypeParameter>? get extensionTypeParameters;
+
+  void becomeNative(SourceLoader loader);
+
+  bool checkPatch(FunctionBuilder patch);
+
+  void reportPatchMismatch(Builder patch);
+}
+
+/// Common base class for constructor and procedure builders.
+abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
+    implements SourceFunctionBuilder {
+  @override
+  final List<MetadataBuilder>? metadata;
+
+  @override
+  final int modifiers;
+
+  @override
+  final TypeBuilder? returnType;
+
+  @override
+  final String name;
+
+  @override
+  final List<TypeVariableBuilder>? typeVariables;
+
+  @override
+  final List<FormalParameterBuilder>? formals;
+
+  /// If this procedure is an extension instance member, [_extensionThis] holds
+  /// the synthetically added `this` parameter.
+  VariableDeclaration? _extensionThis;
+
+  /// If this procedure is an extension instance member,
+  /// [_extensionTypeParameters] holds the type parameters copied from the
+  /// extension declaration.
+  List<TypeParameter>? _extensionTypeParameters;
+
+  SourceFunctionBuilderImpl(
+      this.metadata,
+      this.modifiers,
+      this.returnType,
+      this.name,
+      this.typeVariables,
+      this.formals,
+      LibraryBuilder compilationUnit,
+      int charOffset,
+      this.nativeMethodName)
+      : super(compilationUnit, charOffset) {
+    if (formals != null) {
+      for (int i = 0; i < formals!.length; i++) {
+        formals![i].parent = this;
+      }
+    }
+  }
+
+  @override
+  String get debugName => "FunctionBuilder";
+
+  @override
+  AsyncMarker get asyncModifier;
+
+  @override
+  bool get isConstructor => false;
+
+  @override
+  bool get isAbstract => (modifiers & abstractMask) != 0;
+
+  @override
+  bool get isRegularMethod => identical(ProcedureKind.Method, kind);
+
+  @override
+  bool get isGetter => identical(ProcedureKind.Getter, kind);
+
+  @override
+  bool get isSetter => identical(ProcedureKind.Setter, kind);
+
+  @override
+  bool get isOperator => identical(ProcedureKind.Operator, kind);
+
+  @override
+  bool get isFactory => identical(ProcedureKind.Factory, kind);
+
+  @override
+  bool get isExternal => (modifiers & externalMask) != 0;
+
+  @override
+  bool get isAssignable => false;
+
+  @override
+  Scope computeFormalParameterScope(Scope parent) {
+    if (formals == null) return parent;
+    Map<String, Builder> local = <String, Builder>{};
+    for (FormalParameterBuilder formal in formals!) {
+      if (!isConstructor ||
+          !formal.isInitializingFormal && !formal.isSuperInitializingFormal) {
+        local[formal.name] = formal;
+      }
+    }
+    return new Scope(
+        local: local,
+        parent: parent,
+        debugName: "formal parameter",
+        isModifiable: false);
+  }
+
+  @override
+  Scope computeFormalParameterInitializerScope(Scope parent) {
+    // From
+    // [dartLangSpec.tex](../../../../../../docs/language/dartLangSpec.tex) at
+    // revision 94b23d3b125e9d246e07a2b43b61740759a0dace:
+    //
+    // When the formal parameter list of a non-redirecting generative
+    // constructor contains any initializing formals, a new scope is
+    // introduced, the _formal parameter initializer scope_, which is the
+    // current scope of the initializer list of the constructor, and which is
+    // enclosed in the scope where the constructor is declared.  Each
+    // initializing formal in the formal parameter list introduces a final
+    // local variable into the formal parameter initializer scope, but not into
+    // the formal parameter scope; every other formal parameter introduces a
+    // local variable into both the formal parameter scope and the formal
+    // parameter initializer scope.
+
+    if (formals == null) return parent;
+    Map<String, Builder> local = <String, Builder>{};
+    for (FormalParameterBuilder formal in formals!) {
+      local[formal.name] = formal.forFormalParameterInitializerScope();
+    }
+    return new Scope(
+        local: local,
+        parent: parent,
+        debugName: "formal parameter initializer",
+        isModifiable: false);
+  }
+
+  @override
+  Scope computeTypeParameterScope(Scope parent) {
+    if (typeVariables == null) return parent;
+    Map<String, Builder> local = <String, Builder>{};
+    for (TypeVariableBuilder variable in typeVariables!) {
+      local[variable.name] = variable;
+    }
+    return new Scope(
+        local: local,
+        parent: parent,
+        debugName: "type parameter",
+        isModifiable: false);
+  }
+
+  @override
+  FormalParameterBuilder? getFormal(Identifier identifier) {
+    if (formals != null) {
+      for (FormalParameterBuilder formal in formals!) {
+        if (formal.name == identifier.name &&
+            formal.charOffset == identifier.charOffset) {
+          return formal;
+        }
+      }
+      // If we have any formals we should find the one we're looking for.
+      assert(false, "$identifier not found in $formals");
+    }
+    return null;
+  }
+
+  @override
+  final String? nativeMethodName;
+
+  Statement? bodyInternal;
+
+  @override
+  void set body(Statement? newBody) {
+//    if (newBody != null) {
+//      if (isAbstract) {
+//        // TODO(danrubel): Is this check needed?
+//        return internalProblem(messageInternalProblemBodyOnAbstractMethod,
+//            newBody.fileOffset, fileUri);
+//      }
+//    }
+    bodyInternal = newBody;
+    // A forwarding semi-stub is a method that is abstract in the source code,
+    // but which needs to have a forwarding stub body in order to ensure that
+    // covariance checks occur.  We don't want to replace the forwarding stub
+    // body with null.
+    TreeNode? parent = function.parent;
+    if (!(newBody == null &&
+        parent is Procedure &&
+        parent.isForwardingSemiStub)) {
+      function.body = newBody;
+      newBody?.parent = function;
+    }
+  }
+
+  @override
+  Statement? get body => bodyInternal ??= new EmptyStatement();
+
+  @override
+  bool get isNative => nativeMethodName != null;
+
+  void buildFunction(SourceLibraryBuilder library) {
+    function.asyncMarker = asyncModifier;
+    function.body = body;
+    body?.parent = function;
+    IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+    if (!isConstructor && !isFactory && parent is ClassBuilder) {
+      Class enclosingClass = classBuilder!.cls;
+      if (enclosingClass.typeParameters.isNotEmpty) {
+        needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
+            enclosingClass.typeParameters,
+            // We are checking the parameter types which are in a
+            // contravariant position.
+            initialVariance: Variance.contravariant);
+      }
+    }
+    if (typeVariables != null) {
+      for (TypeVariableBuilder t in typeVariables!) {
+        TypeParameter parameter = t.parameter;
+        function.typeParameters.add(parameter);
+        if (needsCheckVisitor != null) {
+          if (parameter.bound.accept(needsCheckVisitor)) {
+            parameter.isCovariantByClass = true;
+          }
+        }
+      }
+      setParents(function.typeParameters, function);
+    }
+    if (formals != null) {
+      for (FormalParameterBuilder formal in formals!) {
+        VariableDeclaration parameter = formal.build(library, 0);
+        if (needsCheckVisitor != null) {
+          if (parameter.type.accept(needsCheckVisitor)) {
+            parameter.isCovariantByClass = true;
+          }
+        }
+        if (formal.isNamed) {
+          function.namedParameters.add(parameter);
+        } else {
+          function.positionalParameters.add(parameter);
+        }
+        parameter.parent = function;
+        if (formal.isRequired) {
+          function.requiredParameterCount++;
+        }
+
+        if (library.isNonNullableByDefault) {
+          // Required named parameters can't have default values.
+          if (formal.isNamedRequired && formal.initializerToken != null) {
+            library.addProblem(
+                templateRequiredNamedParameterHasDefaultValueError
+                    .withArguments(formal.name),
+                formal.charOffset,
+                formal.name.length,
+                formal.fileUri);
+          }
+        }
+      }
+    }
+    if (!isExtensionInstanceMember &&
+        isSetter &&
+        (formals?.length != 1 || formals![0].isOptional)) {
+      // Replace illegal parameters by single dummy parameter.
+      // Do this after building the parameters, since the diet listener
+      // assumes that parameters are built, even if illegal in number.
+      VariableDeclaration parameter =
+          new VariableDeclarationImpl("#synthetic", 0);
+      function.positionalParameters.clear();
+      function.positionalParameters.add(parameter);
+      parameter.parent = function;
+      function.namedParameters.clear();
+      function.requiredParameterCount = 1;
+    }
+    if (returnType != null) {
+      function.returnType = returnType!.build(library);
+    }
+    if (isExtensionInstanceMember) {
+      ExtensionBuilder extensionBuilder = parent as ExtensionBuilder;
+      _extensionThis = function.positionalParameters.first;
+      if (extensionBuilder.typeParameters != null) {
+        int count = extensionBuilder.typeParameters!.length;
+        _extensionTypeParameters = new List<TypeParameter>.generate(
+            count, (int index) => function.typeParameters[index],
+            growable: false);
+      }
+    }
+  }
+
+  @override
+  VariableDeclaration getFormalParameter(int index) {
+    if (isExtensionInstanceMember) {
+      return formals![index + 1].variable!;
+    } else {
+      return formals![index].variable!;
+    }
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) => null;
+
+  @override
+  VariableDeclaration? get extensionThis {
+    assert(_extensionThis != null || !isExtensionInstanceMember,
+        "ProcedureBuilder.extensionThis has not been set.");
+    return _extensionThis;
+  }
+
+  @override
+  List<TypeParameter>? get extensionTypeParameters {
+    // Use [_extensionThis] as marker for whether extension type parameters have
+    // been computed.
+    assert(_extensionThis != null || !isExtensionInstanceMember,
+        "ProcedureBuilder.extensionTypeParameters has not been set.");
+    return _extensionTypeParameters;
+  }
+
+  bool _hasBuiltOutlineExpressions = false;
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+    if (!_hasBuiltOutlineExpressions) {
+      DeclarationBuilder? classOrExtensionBuilder =
+          isClassMember || isExtensionMember
+              ? parent as DeclarationBuilder
+              : null;
+      Scope parentScope = classOrExtensionBuilder?.scope ?? library.scope;
+      MetadataBuilder.buildAnnotations(member, metadata, library,
+          classOrExtensionBuilder, this, fileUri, parentScope);
+      if (typeVariables != null) {
+        for (int i = 0; i < typeVariables!.length; i++) {
+          typeVariables![i].buildOutlineExpressions(
+              library,
+              classOrExtensionBuilder,
+              this,
+              classHierarchy,
+              delayedActionPerformers,
+              computeTypeParameterScope(parentScope));
+        }
+      }
+
+      if (formals != null) {
+        // For const constructors we need to include default parameter values
+        // into the outline. For all other formals we need to call
+        // buildOutlineExpressions to clear initializerToken to prevent
+        // consuming too much memory.
+        for (FormalParameterBuilder formal in formals!) {
+          formal.buildOutlineExpressions(library, delayedActionPerformers);
+        }
+      }
+      _hasBuiltOutlineExpressions = true;
+    }
+  }
+
+  Member build(SourceLibraryBuilder library);
+
+  @override
+  void becomeNative(SourceLoader loader) {
+    MemberBuilder constructor = loader.getNativeAnnotation();
+    Arguments arguments =
+        new Arguments(<Expression>[new StringLiteral(nativeMethodName!)]);
+    Expression annotation;
+    if (constructor.isConstructor) {
+      annotation = new ConstructorInvocation(
+          constructor.member as Constructor, arguments)
+        ..isConst = true;
+    } else {
+      annotation =
+          new StaticInvocation(constructor.member as Procedure, arguments)
+            ..isConst = true;
+    }
+    member.addAnnotation(annotation);
+  }
+
+  @override
+  bool checkPatch(FunctionBuilder patch) {
+    if (!isExternal) {
+      patch.library.addProblem(
+          messagePatchNonExternal, patch.charOffset, noLength, patch.fileUri!,
+          context: [
+            messagePatchDeclarationOrigin.withLocation(
+                fileUri, charOffset, noLength)
+          ]);
+      return false;
+    }
+    return true;
+  }
+
+  @override
+  void reportPatchMismatch(Builder patch) {
+    library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
+        noLength, patch.fileUri!, context: [
+      messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
+    ]);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 3c68b27..a0bf299 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -8,44 +8,31 @@
 import 'dart:convert' show jsonEncode;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
 import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
     show resolveRelativeUri;
-
 import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
-
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
-import 'package:kernel/core_types.dart';
-
 import 'package:kernel/reference_from_index.dart'
     show IndexedClass, IndexedContainer, IndexedLibrary;
-
 import 'package:kernel/src/bounds_checks.dart'
     show
         TypeArgumentIssue,
         findTypeArgumentIssues,
         findTypeArgumentIssuesForInvocation,
         getGenericTypeName;
-
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
-
 import 'package:kernel/type_environment.dart'
     show SubtypeCheckMode, TypeEnvironment;
 
 import '../../api_prototype/experimental_flags.dart';
 import '../../base/nnbd_mode.dart';
-
 import '../builder/builder.dart';
 import '../builder/builtin_type_declaration_builder.dart';
 import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
 import '../builder/constructor_reference_builder.dart';
 import '../builder/dynamic_type_declaration_builder.dart';
-import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
-import '../builder/factory_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_builder.dart';
@@ -66,23 +53,15 @@
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
 import '../builder/void_type_declaration_builder.dart';
-
 import '../combinator.dart' show CombinatorBuilder;
-
 import '../configuration.dart' show Configuration;
-
 import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
-
 import '../export.dart' show Export;
-
 import '../fasta_codes.dart';
-
 import '../identifiers.dart' show QualifiedName, flattenName;
-
 import '../import.dart' show Import;
-
-import '../kernel/hierarchy/members_builder.dart';
 import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/hierarchy/members_builder.dart';
 import '../kernel/implicit_field_type.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/kernel_helper.dart';
@@ -98,7 +77,6 @@
         getNonSimplicityIssuesForTypeVariables,
         pendingVariance;
 import '../kernel/utils.dart' show compareProcedures, toKernelCombinators;
-
 import '../modifier.dart'
     show
         abstractMask,
@@ -113,22 +91,23 @@
         mixinDeclarationMask,
         namedMixinApplicationMask,
         staticMask;
-
 import '../names.dart' show indexSetName;
-
 import '../operator.dart';
-
 import '../problems.dart' show unexpected, unhandled;
-
 import '../scope.dart';
-
 import '../type_inference/type_inferrer.dart' show TypeInferrerImpl;
-
 import '../util/helpers.dart';
 import 'name_scheme.dart';
 import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_enum_builder.dart';
 import 'source_extension_builder.dart';
+import 'source_factory_builder.dart';
+import 'source_field_builder.dart';
+import 'source_function_builder.dart';
 import 'source_loader.dart' show SourceLoader;
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
 import 'source_type_alias_builder.dart';
 
 class SourceLibraryBuilder extends LibraryBuilderImpl {
@@ -160,6 +139,9 @@
 
   Uri? get packageUriForTesting => _packageUri;
 
+  @override
+  final bool isUnsupported;
+
   final List<Object> accessors = <Object>[];
 
   @override
@@ -186,7 +168,7 @@
 
   final SourceLibraryBuilder? _origin;
 
-  final List<FunctionBuilder> nativeMethods = <FunctionBuilder>[];
+  final List<SourceFunctionBuilder> nativeMethods = <SourceFunctionBuilder>[];
 
   final List<TypeVariableBuilder> unboundTypeVariables =
       <TypeVariableBuilder>[];
@@ -234,7 +216,7 @@
   /// the error message is the corresponding value in the map.
   Map<String, String?>? unserializableExports;
 
-  List<FieldBuilder>? _implicitlyTypedFields;
+  List<SourceFieldBuilder>? _implicitlyTypedFields;
 
   /// The language version of this library as defined by the language version
   /// of the package it belongs to, if present, or the current language version
@@ -271,7 +253,8 @@
       Library library,
       LibraryBuilder? nameOrigin,
       Library? referencesFrom,
-      bool? referenceIsPartOwner)
+      bool? referenceIsPartOwner,
+      bool isUnsupported)
       : this.fromScopes(
             loader,
             fileUri,
@@ -282,7 +265,8 @@
             origin,
             library,
             nameOrigin,
-            referencesFrom);
+            referencesFrom,
+            isUnsupported);
 
   SourceLibraryBuilder.fromScopes(
       this.loader,
@@ -294,7 +278,8 @@
       SourceLibraryBuilder? origin,
       this.library,
       this._nameOrigin,
-      this.referencesFrom)
+      this.referencesFrom,
+      this.isUnsupported)
       : _languageVersion = packageLanguageVersion,
         currentTypeParameterScopeBuilder = _libraryTypeParameterScopeBuilder,
         referencesFromIndexed =
@@ -483,7 +468,8 @@
       Library? target,
       LibraryBuilder? nameOrigin,
       Library? referencesFrom,
-      bool? referenceIsPartOwner})
+      bool? referenceIsPartOwner,
+      required bool isUnsupported})
       : this.internal(
             loader,
             fileUri,
@@ -501,7 +487,8 @@
                   ..setLanguageVersion(packageLanguageVersion.version)),
             nameOrigin,
             referencesFrom,
-            referenceIsPartOwner);
+            referenceIsPartOwner,
+            isUnsupported);
 
   @override
   bool get isPart => partOfName != null || partOfUri != null;
@@ -724,7 +711,8 @@
       int uriOffset) {
     if (configurations != null) {
       for (Configuration config in configurations) {
-        if (lookupImportCondition(config.dottedName) == config.condition) {
+        if (loader.getLibrarySupportValue(config.dottedName) ==
+            config.condition) {
           uri = config.importUri;
           break;
         }
@@ -738,26 +726,6 @@
     exports.add(new Export(this, exportedLibrary, combinators, charOffset));
   }
 
-  String lookupImportCondition(String dottedName) {
-    const String prefix = "dart.library.";
-    if (!dottedName.startsWith(prefix)) return "";
-    dottedName = dottedName.substring(prefix.length);
-    if (!loader.target.uriTranslator.isLibrarySupported(dottedName)) return "";
-
-    LibraryBuilder? imported =
-        loader.lookupLibraryBuilder(new Uri(scheme: "dart", path: dottedName));
-
-    if (imported == null) {
-      LibraryBuilder coreLibrary = loader.readAsEntryPoint(resolve(
-          this.importUri,
-          new Uri(scheme: "dart", path: "core").toString(),
-          -1));
-      imported = coreLibrary.loader
-          .lookupLibraryBuilder(new Uri(scheme: 'dart', path: dottedName));
-    }
-    return imported != null && !imported.isSynthetic ? "true" : "";
-  }
-
   void addImport(
       List<MetadataBuilder>? metadata,
       String uri,
@@ -771,7 +739,8 @@
       int importIndex) {
     if (configurations != null) {
       for (Configuration config in configurations) {
-        if (lookupImportCondition(config.dottedName) == config.condition) {
+        if (loader.getLibrarySupportValue(config.dottedName) ==
+            config.condition) {
           uri = config.importUri;
           break;
         }
@@ -1025,9 +994,10 @@
           conflictingGetables.add(currentGetable);
         }
       }
-      for (MemberBuilderImpl? currentSetter = setter as MemberBuilderImpl?;
+      for (SourceMemberBuilderImpl? currentSetter =
+              setter as SourceMemberBuilderImpl?;
           currentSetter != null;
-          currentSetter = currentSetter.next as MemberBuilderImpl?) {
+          currentSetter = currentSetter.next as SourceMemberBuilderImpl?) {
         bool conflict = conflictingGetables.isNotEmpty;
         for (Builder? currentGetable = getable;
             currentGetable != null;
@@ -1096,6 +1066,7 @@
     if (!modifyTarget) return library;
 
     library.isSynthetic = isSynthetic;
+    library.isUnsupported = isUnsupported;
     addDependencies(library, new Set<SourceLibraryBuilder>());
 
     library.name = name;
@@ -1330,7 +1301,7 @@
         (library.problemsAsJson ??= <String>[])
             .addAll(part.library.problemsAsJson!);
       }
-      List<FieldBuilder> partImplicitlyTypedFields = [];
+      List<SourceFieldBuilder> partImplicitlyTypedFields = [];
       part.collectImplicitlyTypedFields(partImplicitlyTypedFields);
       if (partImplicitlyTypedFields.isNotEmpty) {
         if (_implicitlyTypedFields == null) {
@@ -1659,7 +1630,7 @@
   TypeBuilder addVoidType(int charOffset) {
     // 'void' is always nullable.
     return addNamedType(
-        "void", const NullabilityBuilder.nullable(), null, charOffset,
+        "void", const NullabilityBuilder.inherent(), null, charOffset,
         instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
       ..bind(
           new VoidTypeDeclarationBuilder(const VoidType(), this, charOffset));
@@ -1865,7 +1836,7 @@
         classScope,
         constructorScope,
         this,
-        new List<ConstructorReferenceBuilder>.from(constructorReferences),
+        new List<ConstructorReferenceBuilder>.of(constructorReferences),
         startOffset,
         nameOffset,
         endOffset,
@@ -2554,22 +2525,23 @@
           .lookupGetterReference(constructorTearOffName(
               constructorName, _currentClassReferencesFromIndexed!.library));
     }
-    ConstructorBuilder constructorBuilder = new SourceConstructorBuilder(
-        metadata,
-        modifiers & ~abstractMask,
-        returnType,
-        constructorName,
-        typeVariables,
-        formals,
-        this,
-        startCharOffset,
-        charOffset,
-        charOpenParenOffset,
-        charEndOffset,
-        constructorReference,
-        tearOffReference,
-        nativeMethodName: nativeMethodName,
-        forAbstractClassOrEnum: forAbstractClass);
+    DeclaredSourceConstructorBuilder constructorBuilder =
+        new DeclaredSourceConstructorBuilder(
+            metadata,
+            modifiers & ~abstractMask,
+            returnType,
+            constructorName,
+            typeVariables,
+            formals,
+            this,
+            startCharOffset,
+            charOffset,
+            charOpenParenOffset,
+            charEndOffset,
+            constructorReference,
+            tearOffReference,
+            nativeMethodName: nativeMethodName,
+            forAbstractClassOrEnum: forAbstractClass);
     checkTypeVariables(typeVariables, constructorBuilder);
     // TODO(johnniwinther): There is no way to pass the tear off reference here.
     addBuilder(constructorName, constructorBuilder, charOffset,
@@ -2579,8 +2551,11 @@
     }
     if (constructorBuilder.isConst) {
       currentTypeParameterScopeBuilder.declaresConstConstructor = true;
+    }
+    if (constructorBuilder.isConst || enableSuperParametersInLibrary) {
       // const constructors will have their initializers compiled and written
-      // into the outline.
+      // into the outline. In case of super-parameters language feature, the
+      // super initializers are required to infer the types of super parameters.
       constructorBuilder.beginInitializers =
           beginInitializers ?? new Token.eof(-1);
     }
@@ -2657,7 +2632,7 @@
         }
       }
     }
-    ProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
+    SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
         metadata,
         modifiers,
         returnType,
@@ -2815,6 +2790,9 @@
   void addEnum(
       List<MetadataBuilder>? metadata,
       String name,
+      List<TypeVariableBuilder>? typeVariables,
+      TypeBuilder? supertypeBuilder,
+      List<TypeBuilder>? interfaceBuilders,
       List<EnumConstantInfo?>? enumConstantInfos,
       int startCharOffset,
       int charOffset,
@@ -2825,13 +2803,21 @@
           referencesFromIndexed!.lookupIndexedClass(name);
     }
     // Nested declaration began in `OutlineBuilder.beginEnum`.
-    // TODO(cstefantsova): Use actual type variables here.
     TypeParameterScopeBuilder declaration =
         endNestedDeclaration(TypeParameterScopeKind.enumDeclaration, name)
-          ..resolveNamedTypes([], this);
-    EnumBuilder builder = new EnumBuilder(
+          ..resolveNamedTypes(typeVariables, this);
+    Map<String, Builder> members = declaration.members!;
+    Map<String, MemberBuilder> constructors = declaration.constructors!;
+    Map<String, MemberBuilder> setters = declaration.setters!;
+
+    SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
         metadata,
         name,
+        typeVariables,
+        applyMixins(supertypeBuilder, startCharOffset, charOffset,
+            charEndOffset, name, /* isMixinDeclaration = */ false,
+            typeVariables: typeVariables, isMacro: false),
+        interfaceBuilders,
         enumConstantInfos,
         this,
         startCharOffset,
@@ -2839,12 +2825,44 @@
         charEndOffset,
         referencesFromIndexedClass,
         new Scope(
-            local: declaration.members!,
-            setters: declaration.setters!,
-            parent: scope.withTypeVariables(<TypeVariableBuilder>[]),
+            local: members,
+            setters: setters,
+            parent: scope.withTypeVariables(typeVariables),
             debugName: "enum $name",
-            isModifiable: false));
-    addBuilder(name, builder, charOffset,
+            isModifiable: false),
+        new ConstructorScope(name, constructors));
+
+    Map<String, TypeVariableBuilder>? typeVariablesByName =
+        checkTypeVariables(typeVariables, enumBuilder);
+
+    void setParent(String name, MemberBuilder? member) {
+      while (member != null) {
+        member.parent = enumBuilder;
+        member = member.next as MemberBuilder?;
+      }
+    }
+
+    void setParentAndCheckConflicts(String name, Builder member) {
+      if (typeVariablesByName != null) {
+        TypeVariableBuilder? tv = typeVariablesByName[name];
+        if (tv != null) {
+          enumBuilder.addProblem(
+              templateConflictsWithTypeVariable.withArguments(name),
+              member.charOffset,
+              name.length,
+              context: [
+                messageConflictsWithTypeVariableCause.withLocation(
+                    tv.fileUri!, tv.charOffset, name.length)
+              ]);
+        }
+      }
+      setParent(name, member as MemberBuilder);
+    }
+
+    members.forEach(setParentAndCheckConflicts);
+    constructors.forEach(setParentAndCheckConflicts);
+    setters.forEach(setParentAndCheckConflicts);
+    addBuilder(name, enumBuilder, charOffset,
         getterReference: referencesFromIndexedClass?.cls.reference);
   }
 
@@ -2934,14 +2952,14 @@
   }
 
   void buildOutlineExpressions(
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes,
       List<DelayedActionPerformer> delayedActionPerformers) {
     Iterable<SourceLibraryBuilder>? patches = this.patchLibraries;
     if (patches != null) {
       for (SourceLibraryBuilder patchLibrary in patches) {
         patchLibrary.buildOutlineExpressions(
-            coreTypes, synthesizedFunctionNodes, delayedActionPerformers);
+            classHierarchy, synthesizedFunctionNodes, delayedActionPerformers);
       }
     }
 
@@ -2951,18 +2969,18 @@
     Iterator<Builder> iterator = this.iterator;
     while (iterator.moveNext()) {
       Builder declaration = iterator.current;
-      if (declaration is ClassBuilder) {
-        declaration.buildOutlineExpressions(
-            this, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
+      if (declaration is SourceClassBuilder) {
+        declaration.buildOutlineExpressions(this, classHierarchy,
+            delayedActionPerformers, synthesizedFunctionNodes);
       } else if (declaration is ExtensionBuilder) {
-        declaration.buildOutlineExpressions(
-            this, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
-      } else if (declaration is MemberBuilder) {
-        declaration.buildOutlineExpressions(
-            this, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
+        declaration.buildOutlineExpressions(this, classHierarchy,
+            delayedActionPerformers, synthesizedFunctionNodes);
+      } else if (declaration is SourceMemberBuilder) {
+        declaration.buildOutlineExpressions(this, classHierarchy,
+            delayedActionPerformers, synthesizedFunctionNodes);
       } else if (declaration is SourceTypeAliasBuilder) {
-        declaration.buildOutlineExpressions(
-            this, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
+        declaration.buildOutlineExpressions(this, classHierarchy,
+            delayedActionPerformers, synthesizedFunctionNodes);
       } else {
         assert(
             declaration is PrefixBuilder ||
@@ -3001,7 +3019,7 @@
       if (!declaration.isPatch && !declaration.isDuplicate) {
         library.addExtension(extension);
       }
-    } else if (declaration is MemberBuilderImpl) {
+    } else if (declaration is SourceMemberBuilder) {
       declaration.buildMembers(this,
           (Member member, BuiltMemberKind memberKind) {
         if (member is Field) {
@@ -3026,7 +3044,7 @@
       if (!declaration.isPatch && !declaration.isDuplicate) {
         library.addTypedef(typedef);
       }
-    } else if (declaration is EnumBuilder) {
+    } else if (declaration is SourceEnumBuilder) {
       Class cls = declaration.build(this, coreLibrary);
       if (!declaration.isPatch) {
         cls.name += findDuplicateSuffix(declaration);
@@ -3265,7 +3283,7 @@
     return count;
   }
 
-  void addNativeMethod(FunctionBuilder method) {
+  void addNativeMethod(SourceFunctionBuilder method) {
     nativeMethods.add(method);
   }
 
@@ -3279,7 +3297,7 @@
       }
     }
 
-    for (FunctionBuilder method in nativeMethods) {
+    for (SourceFunctionBuilder method in nativeMethods) {
       method.becomeNative(loader);
     }
     count += nativeMethods.length;
@@ -3641,9 +3659,9 @@
                   inErrorRecovery: issues.isNotEmpty);
               formals = member.formals;
             } else {
-              assert(member is ConstructorBuilder,
+              assert(member is DeclaredSourceConstructorBuilder,
                   "Unexpected constructor member (${member.runtimeType}).");
-              formals = (member as ConstructorBuilder).formals;
+              formals = (member as DeclaredSourceConstructorBuilder).formals;
             }
             if (formals != null && formals.isNotEmpty) {
               for (FormalParameterBuilder formal in formals) {
@@ -3657,7 +3675,7 @@
           });
         }
         declaration.forEach((String name, Builder member) {
-          if (member is ProcedureBuilder) {
+          if (member is SourceProcedureBuilder) {
             List<NonSimplicityIssue> issues =
                 getNonSimplicityIssuesForTypeVariables(member.typeVariables);
             if (member.formals != null && member.formals!.isNotEmpty) {
@@ -3676,9 +3694,9 @@
             count += computeDefaultTypesForVariables(member.typeVariables,
                 inErrorRecovery: issues.isNotEmpty);
           } else {
-            assert(member is FieldBuilder,
+            assert(member is SourceFieldBuilder,
                 "Unexpected class member $member (${member.runtimeType}).");
-            TypeBuilder? fieldType = (member as FieldBuilder).type;
+            TypeBuilder? fieldType = (member as SourceFieldBuilder).type;
             if (fieldType != null) {
               List<NonSimplicityIssue> issues =
                   getInboundReferenceIssuesInType(fieldType);
@@ -3696,7 +3714,7 @@
         count += computeDefaultTypesForVariables(declaration.typeVariables,
             inErrorRecovery: issues.isNotEmpty);
         _recursivelyReportGenericFunctionTypesAsBoundsForType(declaration.type);
-      } else if (declaration is FunctionBuilder) {
+      } else if (declaration is SourceFunctionBuilder) {
         List<NonSimplicityIssue> issues =
             getNonSimplicityIssuesForTypeVariables(declaration.typeVariables);
         if (declaration.formals != null && declaration.formals!.isNotEmpty) {
@@ -3724,7 +3742,7 @@
               inErrorRecovery: issues.isNotEmpty);
         }
         declaration.forEach((String name, Builder member) {
-          if (member is ProcedureBuilder) {
+          if (member is SourceProcedureBuilder) {
             List<NonSimplicityIssue> issues =
                 getNonSimplicityIssuesForTypeVariables(member.typeVariables);
             if (member.formals != null && member.formals!.isNotEmpty) {
@@ -3742,7 +3760,7 @@
             reportIssues(issues);
             count += computeDefaultTypesForVariables(member.typeVariables,
                 inErrorRecovery: issues.isNotEmpty);
-          } else if (member is FieldBuilder) {
+          } else if (member is SourceFieldBuilder) {
             if (member.type != null) {
               _recursivelyReportGenericFunctionTypesAsBoundsForType(
                   member.type);
@@ -3752,7 +3770,7 @@
                 "Unexpected extension member $member (${member.runtimeType}).");
           }
         });
-      } else if (declaration is FieldBuilder) {
+      } else if (declaration is SourceFieldBuilder) {
         if (declaration.type != null) {
           List<NonSimplicityIssue> issues =
               getInboundReferenceIssuesInType(declaration.type);
@@ -3772,10 +3790,10 @@
     for (Builder declaration
         in _libraryTypeParameterScopeBuilder.setters!.values) {
       assert(
-          declaration is ProcedureBuilder,
+          declaration is SourceProcedureBuilder,
           "Expected setter to be a ProcedureBuilder, "
           "but got '${declaration.runtimeType}'");
-      if (declaration is ProcedureBuilder &&
+      if (declaration is SourceProcedureBuilder &&
           declaration.formals != null &&
           declaration.formals!.isNotEmpty) {
         for (FormalParameterBuilder formal in declaration.formals!) {
@@ -4025,10 +4043,10 @@
   }
 
   void checkTypesInField(
-      FieldBuilder fieldBuilder, TypeEnvironment typeEnvironment) {
+      SourceFieldBuilder fieldBuilder, TypeEnvironment typeEnvironment) {
     // Check the bounds in the field's type.
     checkBoundsInType(fieldBuilder.fieldType, typeEnvironment,
-        fieldBuilder.fileUri!, fieldBuilder.charOffset,
+        fieldBuilder.fileUri, fieldBuilder.charOffset,
         allowSuperBounded: true);
 
     // Check that the field has an initializer if its type is potentially
@@ -4198,7 +4216,7 @@
   }
 
   void checkTypesInFunctionBuilder(
-      FunctionBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
+      SourceFunctionBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
     checkBoundsInFunctionNode(
         procedureBuilder.function, typeEnvironment, procedureBuilder.fileUri!);
     if (procedureBuilder.formals != null &&
@@ -4208,7 +4226,8 @@
   }
 
   void checkTypesInConstructorBuilder(
-      ConstructorBuilder constructorBuilder, TypeEnvironment typeEnvironment) {
+      DeclaredSourceConstructorBuilder constructorBuilder,
+      TypeEnvironment typeEnvironment) {
     checkBoundsInFunctionNode(
         constructorBuilder.constructor.function, typeEnvironment, fileUri);
     if (!constructorBuilder.isExternal && constructorBuilder.formals != null) {
@@ -4369,9 +4388,13 @@
     if (arguments.types.isEmpty) return;
     Class klass;
     List<DartType> receiverTypeArguments;
+    Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
     if (receiverType is InterfaceType) {
       klass = receiverType.classNode;
       receiverTypeArguments = receiverType.typeArguments;
+      for (int i = 0; i < receiverTypeArguments.length; ++i) {
+        substitutionMap[klass.typeParameters[i]] = receiverTypeArguments[i];
+      }
     } else {
       return;
     }
@@ -4387,10 +4410,12 @@
           hierarchy.getClassAsInstanceOf(klass, method.enclosingClass!)!;
       klass = method.enclosingClass!;
       receiverTypeArguments = parent.typeArguments;
-    }
-    Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
-    for (int i = 0; i < receiverTypeArguments.length; ++i) {
-      substitutionMap[klass.typeParameters[i]] = receiverTypeArguments[i];
+      Map<TypeParameter, DartType> instanceSubstitutionMap = substitutionMap;
+      substitutionMap = <TypeParameter, DartType>{};
+      for (int i = 0; i < receiverTypeArguments.length; ++i) {
+        substitutionMap[klass.typeParameters[i]] =
+            substitute(receiverTypeArguments[i], instanceSubstitutionMap);
+      }
     }
     List<TypeParameter> methodParameters = method.function.typeParameters;
     // The error is to be reported elsewhere.
@@ -4510,9 +4535,9 @@
     Iterator<Builder> iterator = this.iterator;
     while (iterator.moveNext()) {
       Builder declaration = iterator.current;
-      if (declaration is FieldBuilder) {
+      if (declaration is SourceFieldBuilder) {
         checkTypesInField(declaration, typeEnvironment);
-      } else if (declaration is ProcedureBuilder) {
+      } else if (declaration is SourceProcedureBuilder) {
         checkTypesInFunctionBuilder(declaration, typeEnvironment);
         if (declaration.isGetter) {
           Builder? setterDeclaration =
@@ -4549,8 +4574,10 @@
 
     assert(currentTypeParameterScopeBuilder.kind ==
         TypeParameterScopeKind.library);
-    for (SourceExtensionBuilder extensionBuilder
+    for (ExtensionBuilder _extensionBuilder
         in currentTypeParameterScopeBuilder.extensions!) {
+      ExtensionBuilder extensionBuilder = _extensionBuilder;
+      if (extensionBuilder is! SourceExtensionBuilder) continue;
       DartType onType = extensionBuilder.extension.onType;
       if (onType is InterfaceType) {
         ExtensionTypeShowHideClause showHideClause =
@@ -4754,8 +4781,8 @@
     }
   }
 
-  void registerImplicitlyTypedField(FieldBuilder fieldBuilder) {
-    (_implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
+  void registerImplicitlyTypedField(SourceFieldBuilder fieldBuilder) {
+    (_implicitlyTypedFields ??= <SourceFieldBuilder>[]).add(fieldBuilder);
   }
 
   void collectImplicitlyTypedFields(
@@ -4897,7 +4924,7 @@
 
   final Map<String, MemberBuilder>? setters;
 
-  final Set<SourceExtensionBuilder>? extensions;
+  final Set<ExtensionBuilder>? extensions;
 
   final List<NamedTypeBuilder> unresolvedNamedTypes = <NamedTypeBuilder>[];
 
@@ -4938,7 +4965,7 @@
             <String, Builder>{},
             <String, MemberBuilder>{},
             null, // No support for constructors in library scopes.
-            <SourceExtensionBuilder>{},
+            <ExtensionBuilder>{},
             "<library>",
             -1,
             null);
@@ -5006,6 +5033,17 @@
     _typeVariables = typeVariables;
   }
 
+  /// Registers that this builder is preparing for an enum declaration with
+  /// the given [name] and [typeVariables] located [charOffset].
+  void markAsEnumDeclaration(
+      String name, int charOffset, List<TypeVariableBuilder>? typeVariables) {
+    assert(_kind == TypeParameterScopeKind.enumDeclaration,
+        "Unexpected declaration kind: $_kind");
+    _name = name;
+    _charOffset = charOffset;
+    _typeVariables = typeVariables;
+  }
+
   /// Registers the 'extension this type' of the extension declaration prepared
   /// for by this builder.
   ///
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 2f6b52c..97db119 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -8,6 +8,8 @@
 import 'dart:convert' show utf8;
 import 'dart:typed_data' show Uint8List;
 
+import 'package:_fe_analyzer_shared/src/macros/executor.dart'
+    show MacroExecutor;
 import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
     show ClassMemberParser;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
@@ -26,6 +28,7 @@
     show ClassHierarchy, HandleAmbiguousSupertypes;
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
+import 'package:kernel/target/targets.dart';
 import 'package:kernel/type_environment.dart';
 import 'package:kernel/util/graph.dart';
 import 'package:package_config/package_config.dart' as package_config;
@@ -35,13 +38,9 @@
 import '../../base/common.dart';
 import '../../base/instrumentation.dart' show Instrumentation;
 import '../../base/nnbd_mode.dart';
-import '../dill/dill_library_builder.dart';
-import '../builder_graph.dart';
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
 import '../builder/declaration_builder.dart';
-import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
@@ -53,9 +52,11 @@
 import '../builder/type_alias_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
+import '../builder_graph.dart';
 import '../crash.dart' show firstSourceUri;
 import '../denylisted_classes.dart'
     show denylistedCoreClasses, denylistedTypedDataClasses;
+import '../dill/dill_library_builder.dart';
 import '../export.dart' show Export;
 import '../fasta_codes.dart';
 import '../kernel/body_builder.dart' show BodyBuilder;
@@ -67,6 +68,7 @@
     show SynthesizedFunctionNode, TypeDependency;
 import '../kernel/kernel_target.dart' show KernelTarget;
 import '../kernel/macro.dart';
+import '../kernel/macro_annotation_parser.dart';
 import '../kernel/transform_collections.dart' show CollectionTransformer;
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
 import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
@@ -82,12 +84,16 @@
 import 'name_scheme.dart';
 import 'outline_builder.dart' show OutlineBuilder;
 import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_enum_builder.dart';
+import 'source_field_builder.dart';
 import 'source_library_builder.dart'
     show
         ImplicitLanguageVersion,
         InvalidLanguageVersion,
         LanguageVersion,
         SourceLibraryBuilder;
+import 'source_procedure_builder.dart';
 import 'stack_listener_impl.dart' show offsetForToken;
 
 class SourceLoader extends Loader {
@@ -243,6 +249,14 @@
     return _sourceLibraryBuilders!;
   }
 
+  void clearSourceLibraryBuilders() {
+    assert(
+        _sourceLibraryBuilders != null,
+        "Source library builder hasn't been computed yet. "
+        "The source libraries are in SourceLoader.resolveParts.");
+    _sourceLibraryBuilders!.clear();
+  }
+
   Iterable<Uri> get libraryImportUris => _builders.keys;
 
   void registerLibraryBuilder(LibraryBuilder libraryBuilder) {
@@ -306,7 +320,32 @@
         loader: this,
         origin: origin,
         referencesFrom: referencesFrom,
-        referenceIsPartOwner: referenceIsPartOwner);
+        referenceIsPartOwner: referenceIsPartOwner,
+        isUnsupported: origin?.library.isUnsupported ??
+            importUri.scheme == 'dart' &&
+                !target.uriTranslator.isLibrarySupported(importUri.path));
+  }
+
+  /// Return `"true"` if the [dottedName] is a 'dart.library.*' qualifier for a
+  /// supported dart:* library, and `""` otherwise.
+  ///
+  /// This is used to determine conditional imports and `bool.fromEnvironment`
+  /// constant values for "dart.library.[libraryName]" values.
+  String getLibrarySupportValue(String dottedName) {
+    if (!DartLibrarySupport.isDartLibraryQualifier(dottedName)) {
+      return "";
+    }
+    String libraryName = DartLibrarySupport.getDartLibraryName(dottedName);
+    Uri uri = new Uri(scheme: "dart", path: libraryName);
+    LibraryBuilder? library = lookupLibraryBuilder(uri);
+    // TODO(johnniwinther): Why is the dill target sometimes not loaded at this
+    // point? And does it matter?
+    library ??= target.dillTarget.loader.lookupLibraryBuilder(uri);
+    return DartLibrarySupport.getDartLibrarySupportValue(libraryName,
+        libraryExists: library != null,
+        isSynthetic: library?.isSynthetic ?? true,
+        isUnsupported: library?.isUnsupported ?? true,
+        dartLibrarySupport: target.backendTarget.dartLibrarySupport);
   }
 
   SourceLibraryBuilder _createSourceLibraryBuilder(
@@ -603,6 +642,9 @@
       currentUriForCrashReporting = library.importUri;
       await buildBody(library);
     }
+    // Workaround: This will return right away but avoid a "semi leak"
+    // where the latest library is saved in a context somewhere.
+    await buildBody(null);
     currentUriForCrashReporting = null;
     logSummary(templateSourceBodySummary);
   }
@@ -716,9 +758,11 @@
       DeclarationBuilder? declarationBuilder,
       ModifierBuilder member,
       Scope scope,
-      Uri fileUri) {
+      Uri fileUri,
+      {Scope? formalParameterScope}) {
     return new BodyBuilder.forOutlineExpression(
-        library, declarationBuilder, member, scope, fileUri);
+        library, declarationBuilder, member, scope, fileUri,
+        formalParameterScope: formalParameterScope);
   }
 
   NnbdMode get nnbdMode => target.context.options.nnbdMode;
@@ -844,7 +888,7 @@
         // setting a breakpoint on line 42 of some import uri mean, if the uri
         // represented several files?
         List<String> newPathSegments =
-            new List<String>.from(importUri.pathSegments);
+            new List<String>.of(importUri.pathSegments);
         newPathSegments.add(library.fileUri.pathSegments.last);
         newPathSegments[0] = "${newPathSegments[0]}-patch";
         importUri = importUri.replace(pathSegments: newPathSegments);
@@ -908,7 +952,7 @@
   }
 
   void registerConstructorToBeInferred(
-      Constructor constructor, ConstructorBuilder builder) {
+      Constructor constructor, DeclaredSourceConstructorBuilder builder) {
     _typeInferenceEngine!.toBeInferred[constructor] = builder;
   }
 
@@ -1035,7 +1079,10 @@
   }
 
   /// Builds all the method bodies found in the given [library].
-  Future<Null> buildBody(SourceLibraryBuilder library) async {
+  Future<Null> buildBody(SourceLibraryBuilder? library) async {
+    // [library] is only nullable so we can call this a "dummy-time" to get rid
+    // of a semi-leak.
+    if (library == null) return;
     Iterable<SourceLibraryBuilder>? patches = library.patchLibraries;
     if (patches != null) {
       for (SourceLibraryBuilder patchLibrary in patches) {
@@ -1124,6 +1171,9 @@
         builder, dietListener.memberScope,
         isDeclarationInstanceMember: isClassInstanceMember,
         extensionThis: extensionThis);
+    for (VariableDeclaration variable in parameters.positionalParameters) {
+      listener.typeInferrer.assignedVariables.declare(variable);
+    }
 
     return listener.parseSingleExpression(
         new Parser(listener,
@@ -1301,18 +1351,24 @@
     ticker.logMs("Resolved $typeCount types");
   }
 
-  void computeMacroDeclarations(List<SourceClassBuilder> sourceClassBuilders) {
-    if (!enableMacros) return;
+  /// Computes which macro declarations that needs to be precompiled in order
+  /// to support macro application during compilation.
+  ///
+  /// If no macros need precompilation, `null` is returned. Otherwise a map
+  /// from library uris to macro class names and the names of constructor their
+  /// constructors is returned.
+  Map<Uri, Map<String, List<String>>>? computeMacroDeclarations() {
+    if (!enableMacros) return null;
 
     LibraryBuilder? macroLibraryBuilder = lookupLibraryBuilder(macroLibraryUri);
-    if (macroLibraryBuilder == null) return;
+    if (macroLibraryBuilder == null) return null;
 
     Builder? macroClassBuilder =
         macroLibraryBuilder.lookupLocalMember(macroClassName);
     if (macroClassBuilder is! ClassBuilder) {
       // TODO(johnniwinther): Report this when the actual macro builder package
       // exists. It should at least be a warning.
-      return;
+      return null;
     }
 
     _macroClassBuilder = macroClassBuilder;
@@ -1320,22 +1376,40 @@
       dataForTesting!.macroDeclarationData.macrosAreAvailable = true;
     }
 
-    Set<ClassBuilder> macroClasses = {macroClassBuilder};
-    Set<Uri> macroLibraries = {macroLibraryBuilder.importUri};
+    /// Libraries containing macros that need compilation mapped to the
+    /// [ClassBuilder]s for the macro classes.
+    Map<Uri, List<ClassBuilder>> macroLibraries = {};
 
-    for (SourceClassBuilder sourceClassBuilder in sourceClassBuilders) {
-      if (sourceClassBuilder.isMacro) {
-        macroClasses.add(sourceClassBuilder);
-        macroLibraries.add(sourceClassBuilder.library.importUri);
-        if (retainDataForTesting) {
-          (dataForTesting!.macroDeclarationData.macroDeclarations[
-                  sourceClassBuilder.library.importUri] ??= [])
-              .add(sourceClassBuilder.name);
+    /// Libraries containing precompiled macro classes.
+    Set<Uri> precompiledMacroLibraries = {};
+
+    Map<MacroClass, Uri> precompiledMacroUris =
+        target.context.options.precompiledMacroUris;
+
+    for (LibraryBuilder libraryBuilder in libraryBuilders) {
+      Iterator<Builder> iterator = libraryBuilder.iterator;
+      while (iterator.moveNext()) {
+        Builder builder = iterator.current;
+        if (builder is ClassBuilder && builder.isMacro) {
+          Uri libraryUri = builder.library.importUri;
+          MacroClass macroClass = new MacroClass(libraryUri, builder.name);
+          if (!precompiledMacroUris.containsKey(macroClass)) {
+            (macroLibraries[libraryUri] ??= []).add(builder);
+            if (retainDataForTesting) {
+              (dataForTesting!.macroDeclarationData
+                      .macroDeclarations[libraryUri] ??= [])
+                  .add(builder.name);
+            }
+          } else {
+            precompiledMacroLibraries.add(libraryUri);
+          }
         }
       }
     }
 
-    bool isDillLibrary(Uri uri) => _builders[uri]?.loader != this;
+    if (macroLibraries.isEmpty) {
+      return null;
+    }
 
     List<List<Uri>> computeCompilationSequence(Graph<Uri> libraryGraph,
         {required bool Function(Uri) filter}) {
@@ -1353,7 +1427,7 @@
         for (List<Uri> component in layer) {
           for (Uri uri in component) {
             if (filter(uri)) continue;
-            if (macroLibraries.contains(uri)) {
+            if (macroLibraries.containsKey(uri)) {
               declaresMacro = true;
             }
             currentLayer.add(uri);
@@ -1370,92 +1444,192 @@
       return layeredComponents;
     }
 
-    List<List<Uri>> compilationSteps = computeCompilationSequence(
-        new BuilderGraph(_builders),
-        filter: isDillLibrary);
+    Graph<Uri> graph = new BuilderGraph(_builders);
+
+    /// Libraries that are considered precompiled. These are libraries that are
+    /// either given as precompiled macro libraries, or libraries that these
+    /// depend upon.
+    // TODO(johnniwinther): Can we assume that the precompiled dills are
+    // self-contained?
+    Set<Uri> precompiledLibraries = {};
+
+    void addPrecompiledLibrary(Uri uri) {
+      if (precompiledLibraries.add(uri)) {
+        for (Uri neighbor in graph.neighborsOf(uri)) {
+          addPrecompiledLibrary(neighbor);
+        }
+      }
+    }
+
+    for (LibraryBuilder builder in _builders.values) {
+      if (builder.loader != this) {
+        addPrecompiledLibrary(builder.importUri);
+      } else if (precompiledMacroLibraries.contains(builder.importUri)) {
+        assert(
+            !macroLibraries.containsKey(builder.importUri),
+            "Macro library ${builder.importUri} is only partially "
+            "precompiled.");
+        addPrecompiledLibrary(builder.importUri);
+      }
+    }
+
+    bool isPrecompiledLibrary(Uri uri) => precompiledLibraries.contains(uri);
+
+    List<List<Uri>> compilationSteps =
+        computeCompilationSequence(graph, filter: isPrecompiledLibrary);
     if (retainDataForTesting) {
       dataForTesting!.macroDeclarationData.compilationSequence =
           compilationSteps;
     }
+
+    if (compilationSteps.length > 1) {
+      // We have at least 1 layer of macros that need to be precompiled before
+      // we can compile the program itself.
+      Map<Uri, Map<String, List<String>>> neededPrecompilations = {};
+      for (int i = 0; i < compilationSteps.length - 1; i++) {
+        List<Uri> compilationStep = compilationSteps[i];
+        for (Uri uri in compilationStep) {
+          List<ClassBuilder>? macroClasses = macroLibraries[uri];
+          // [uri] might not itself declare any macros but instead a part of the
+          // libraries that macros depend upon.
+          if (macroClasses != null) {
+            Map<String, List<String>>? constructorMap;
+            for (ClassBuilder macroClass in macroClasses) {
+              List<String> constructors =
+                  macroClass.constructors.local.keys.toList();
+              if (constructors.isNotEmpty) {
+                // TODO(johnniwinther): If there is no constructor here, it
+                // means the macro had no _explicit_ constructors. Since macro
+                // constructor are required to be const, this would be an error
+                // case. We need to handle that precompilation could result in
+                // errors like this. For this case we should probably add 'new'
+                // in case of [constructors] being empty in expectation of
+                // triggering the error during precompilation.
+                (constructorMap ??= {})[macroClass.name] = constructors;
+              }
+            }
+            if (constructorMap != null) {
+              neededPrecompilations[uri] = constructorMap;
+            }
+          }
+        }
+        if (neededPrecompilations.isNotEmpty) {
+          if (retainDataForTesting) {
+            dataForTesting!.macroDeclarationData.neededPrecompilations
+                .add(neededPrecompilations);
+          }
+          // We have found the first needed layer of precompilation. There might
+          // be more layers but we'll compute these at the next attempt at
+          // compilation, when this layer has been precompiled.
+          // TODO(johnniwinther): Use this to trigger a precompile step.
+          return neededPrecompilations;
+        }
+      }
+    }
+    return null;
   }
 
-  void computeMacroApplications() {
-    if (!enableMacros || _macroClassBuilder == null) return;
-    Class macroClass = _macroClassBuilder!.cls;
+  Future<MacroApplications?> computeMacroApplications() async {
+    if (!enableMacros || _macroClassBuilder == null) return null;
 
-    Class? computeApplication(Expression expression) {
-      if (expression is ConstructorInvocation) {
-        Class cls = expression.target.enclosingClass;
-        if (hierarchy.isSubtypeOf(cls, macroClass)) {
-          return cls;
-        }
-      }
-      return null;
-    }
-
-    MacroApplications? computeApplications(List<Expression> annotations) {
-      List<Class> macros = [];
-      for (Expression annotation in annotations) {
-        Class? cls = computeApplication(annotation);
-        if (cls != null) {
-          macros.add(cls);
-        }
-      }
-      return macros.isNotEmpty ? new MacroApplications(macros) : null;
-    }
-
+    Map<SourceLibraryBuilder, LibraryMacroApplicationData> libraryData = {};
     for (SourceLibraryBuilder libraryBuilder in sourceLibraryBuilders) {
       // TODO(johnniwinther): Handle patch libraries.
       LibraryMacroApplicationData libraryMacroApplicationData =
           new LibraryMacroApplicationData();
-      Library library = libraryBuilder.library;
-      libraryMacroApplicationData.libraryApplications =
-          computeApplications(library.annotations);
-      for (Class cls in library.classes) {
-        ClassMacroApplicationData classMacroApplicationData =
-            new ClassMacroApplicationData();
-        classMacroApplicationData.classApplications =
-            computeApplications(cls.annotations);
-        for (Member member in cls.members) {
-          MacroApplications? macroApplications =
-              computeApplications(member.annotations);
+      Iterator<Builder> iterator = libraryBuilder.iterator;
+      while (iterator.moveNext()) {
+        Builder builder = iterator.current;
+        if (builder is SourceClassBuilder) {
+          SourceClassBuilder classBuilder = builder;
+          ClassMacroApplicationData classMacroApplicationData =
+              new ClassMacroApplicationData();
+          classMacroApplicationData.classApplications = prebuildAnnotations(
+              enclosingLibrary: libraryBuilder,
+              scope: classBuilder.scope,
+              fileUri: classBuilder.fileUri,
+              metadataBuilders: classBuilder.metadata);
+          builder.forEach((String name, Builder memberBuilder) {
+            if (memberBuilder is SourceProcedureBuilder) {
+              List<MacroApplication>? macroApplications = prebuildAnnotations(
+                  enclosingLibrary: libraryBuilder,
+                  scope: classBuilder.scope,
+                  fileUri: memberBuilder.fileUri,
+                  metadataBuilders: memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData.memberApplications[memberBuilder] =
+                    macroApplications;
+              }
+            } else if (memberBuilder is SourceFieldBuilder) {
+              List<MacroApplication>? macroApplications = prebuildAnnotations(
+                  enclosingLibrary: libraryBuilder,
+                  scope: classBuilder.scope,
+                  fileUri: memberBuilder.fileUri,
+                  metadataBuilders: memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData.memberApplications[memberBuilder] =
+                    macroApplications;
+              }
+            }
+          });
+          classBuilder.forEachConstructor((String name, Builder memberBuilder) {
+            if (memberBuilder is DeclaredSourceConstructorBuilder) {
+              List<MacroApplication>? macroApplications = prebuildAnnotations(
+                  enclosingLibrary: libraryBuilder,
+                  scope: classBuilder.scope,
+                  fileUri: memberBuilder.fileUri,
+                  metadataBuilders: memberBuilder.metadata);
+              if (macroApplications != null) {
+                classMacroApplicationData.memberApplications[memberBuilder] =
+                    macroApplications;
+              }
+            }
+          });
+
+          if (classMacroApplicationData.classApplications != null ||
+              classMacroApplicationData.memberApplications.isNotEmpty) {
+            libraryMacroApplicationData.classData[builder] =
+                classMacroApplicationData;
+          }
+        } else if (builder is SourceProcedureBuilder) {
+          List<MacroApplication>? macroApplications = prebuildAnnotations(
+              enclosingLibrary: libraryBuilder,
+              scope: libraryBuilder.scope,
+              fileUri: builder.fileUri,
+              metadataBuilders: builder.metadata);
           if (macroApplications != null) {
-            classMacroApplicationData.memberApplications[member] =
+            libraryMacroApplicationData.memberApplications[builder] =
+                macroApplications;
+          }
+        } else if (builder is SourceFieldBuilder) {
+          List<MacroApplication>? macroApplications = prebuildAnnotations(
+              enclosingLibrary: libraryBuilder,
+              scope: libraryBuilder.scope,
+              fileUri: builder.fileUri,
+              metadataBuilders: builder.metadata);
+          if (macroApplications != null) {
+            libraryMacroApplicationData.memberApplications[builder] =
                 macroApplications;
           }
         }
-        if (classMacroApplicationData.classApplications != null ||
-            classMacroApplicationData.memberApplications.isNotEmpty) {
-          libraryMacroApplicationData.classData[cls] =
-              classMacroApplicationData;
-        }
       }
-      for (Member member in library.members) {
-        MacroApplications? macroApplications =
-            computeApplications(member.annotations);
-        if (macroApplications != null) {
-          libraryMacroApplicationData.memberApplications[member] =
-              macroApplications;
-        }
-      }
-      for (Typedef typedef in library.typedefs) {
-        MacroApplications? macroApplications =
-            computeApplications(typedef.annotations);
-        if (macroApplications != null) {
-          libraryMacroApplicationData.typedefApplications[typedef] =
-              macroApplications;
-        }
-      }
-      if (libraryMacroApplicationData.libraryApplications != null ||
-          libraryMacroApplicationData.classData.isNotEmpty ||
-          libraryMacroApplicationData.typedefApplications.isNotEmpty ||
+      if (libraryMacroApplicationData.classData.isNotEmpty ||
           libraryMacroApplicationData.memberApplications.isNotEmpty) {
-        if (retainDataForTesting) {
-          dataForTesting!.macroApplicationData.libraryData[library] =
-              libraryMacroApplicationData;
-        }
+        libraryData[libraryBuilder] = libraryMacroApplicationData;
       }
     }
+    if (libraryData.isNotEmpty) {
+      MacroExecutor macroExecutor =
+          await target.context.options.macroExecutorProvider();
+      Map<MacroClass, Uri> precompiledMacroUris =
+          target.context.options.precompiledMacroUris;
+      return await MacroApplications.loadMacroIds(
+          macroExecutor,
+          precompiledMacroUris,
+          libraryData,
+          dataForTesting?.macroApplicationData);
+    }
+    return null;
   }
 
   void finishDeferredLoadTearoffs() {
@@ -1576,6 +1750,8 @@
           denylistedCoreClasses[i],
           required: true) as ClassBuilder);
     }
+    ClassBuilder enumClass =
+        coreLibrary.lookupLocalMember("Enum", required: true) as ClassBuilder;
     if (typedDataLibrary != null) {
       for (int i = 0; i < denylistedTypedDataClasses.length; i++) {
         // Allow the member to not exist. If it doesn't, nobody can extend it.
@@ -1592,8 +1768,8 @@
         topologicalSort(classGraph);
     List<SourceClassBuilder> classes = result.sortedVertices;
     for (SourceClassBuilder cls in classes) {
-      checkClassSupertypes(
-          cls, classGraph.directSupertypeMap[cls]!, denyListedClasses);
+      checkClassSupertypes(cls, classGraph.directSupertypeMap[cls]!,
+          denyListedClasses, enumClass);
     }
 
     List<SourceClassBuilder> classesWithCycles = result.cyclicVertices;
@@ -1636,20 +1812,34 @@
     }
   }
 
+  bool checkEnumSupertypeIsDenylisted(SourceClassBuilder cls) {
+    if (!cls.library.enableEnhancedEnumsInLibrary) {
+      cls.addProblem(
+          templateEnumSupertypeOfNonAbstractClass.withArguments(cls.name),
+          cls.charOffset,
+          noLength);
+      return true;
+    }
+    return false;
+  }
+
   void checkClassSupertypes(
       SourceClassBuilder cls,
       Map<TypeDeclarationBuilder?, TypeAliasBuilder?> directSupertypeMap,
-      Set<ClassBuilder> denyListedClasses) {
+      Set<ClassBuilder> denyListedClasses,
+      ClassBuilder enumClass) {
     // Check that the direct supertypes aren't deny-listed or enums.
     List<TypeDeclarationBuilder?> directSupertypes =
         directSupertypeMap.keys.toList();
     for (int i = 0; i < directSupertypes.length; i++) {
       TypeDeclarationBuilder? supertype = directSupertypes[i];
-      if (supertype is EnumBuilder) {
+      if (supertype is SourceEnumBuilder) {
         cls.addProblem(templateExtendingEnum.withArguments(supertype.name),
             cls.charOffset, noLength);
       } else if (!cls.library.mayImplementRestrictedTypes &&
-          denyListedClasses.contains(supertype)) {
+          (denyListedClasses.contains(supertype) ||
+              identical(supertype, enumClass) &&
+                  checkEnumSupertypeIsDenylisted(cls))) {
         TypeAliasBuilder? aliasBuilder = directSupertypeMap[supertype];
         if (aliasBuilder != null) {
           cls.addProblem(
@@ -1829,10 +2019,11 @@
     ticker.logMs("Computed core types");
   }
 
-  void checkSupertypes(List<SourceClassBuilder> sourceClasses) {
+  void checkSupertypes(
+      List<SourceClassBuilder> sourceClasses, Class enumClass) {
     for (SourceClassBuilder builder in sourceClasses) {
       if (builder.library.loader == this && !builder.isPatch) {
-        builder.checkSupertypes(coreTypes);
+        builder.checkSupertypes(coreTypes, hierarchyBuilder, enumClass);
       }
     }
     ticker.logMs("Checked supertypes");
@@ -1911,13 +2102,13 @@
     ticker.logMs("Checked mixin declaration applications");
   }
 
-  void buildOutlineExpressions(CoreTypes coreTypes,
+  void buildOutlineExpressions(ClassHierarchy classHierarchy,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     List<DelayedActionPerformer> delayedActionPerformers =
         <DelayedActionPerformer>[];
     for (SourceLibraryBuilder library in sourceLibraryBuilders) {
       library.buildOutlineExpressions(
-          coreTypes, synthesizedFunctionNodes, delayedActionPerformers);
+          classHierarchy, synthesizedFunctionNodes, delayedActionPerformers);
     }
     for (DelayedActionPerformer delayedActionPerformer
         in delayedActionPerformers) {
@@ -1931,11 +2122,15 @@
     ClassHierarchyBuilder hierarchyBuilder = _hierarchyBuilder =
         ClassHierarchyBuilder.build(
             objectClass, sourceClasses, this, coreTypes);
+    typeInferenceEngine.hierarchyBuilder = hierarchyBuilder;
+    ticker.logMs("Built class hierarchy");
+  }
+
+  void buildClassHierarchyMembers(List<SourceClassBuilder> sourceClasses) {
     ClassMembersBuilder membersBuilder = _membersBuilder =
         ClassMembersBuilder.build(hierarchyBuilder, sourceClasses);
-    typeInferenceEngine.hierarchyBuilder = hierarchyBuilder;
     typeInferenceEngine.membersBuilder = membersBuilder;
-    ticker.logMs("Built class hierarchy");
+    ticker.logMs("Built class hierarchy members");
   }
 
   void createTypeInferenceEngine() {
@@ -1950,7 +2145,7 @@
     typeInferenceEngine.prepareTopLevel(coreTypes, hierarchy);
     membersBuilder.computeTypes();
 
-    List<FieldBuilder> allImplicitlyTypedFields = <FieldBuilder>[];
+    List<SourceFieldBuilder> allImplicitlyTypedFields = [];
     for (SourceLibraryBuilder library in sourceLibraryBuilders) {
       library.collectImplicitlyTypedFields(allImplicitlyTypedFields);
     }
@@ -2477,7 +2672,8 @@
 
   final MacroDeclarationData macroDeclarationData = new MacroDeclarationData();
 
-  final MacroApplicationData macroApplicationData = new MacroApplicationData();
+  final MacroApplicationDataForTesting macroApplicationData =
+      new MacroApplicationDataForTesting();
 }
 
 class _SourceClassGraph implements Graph<SourceClassBuilder> {
diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
new file mode 100644
index 0000000..edfb1a1
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for 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.member_builder;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+
+import '../../base/common.dart';
+import '../builder/builder.dart';
+import '../builder/declaration_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../kernel/kernel_helper.dart';
+import '../problems.dart' show unsupported;
+import '../source/source_library_builder.dart';
+import '../type_inference/type_inference_engine.dart'
+    show InferenceDataForTesting;
+import '../util/helpers.dart' show DelayedActionPerformer;
+
+abstract class SourceMemberBuilder implements MemberBuilder {
+  MemberDataForTesting? get dataForTesting;
+
+  /// Builds the core AST structures for this member as needed for the outline.
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
+
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes);
+}
+
+mixin SourceMemberBuilderMixin implements SourceMemberBuilder {
+  @override
+  MemberDataForTesting? dataForTesting =
+      retainDataForTesting ? new MemberDataForTesting() : null;
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    assert(false, "Unexpected call to $runtimeType.buildMembers.");
+  }
+}
+
+abstract class SourceMemberBuilderImpl extends MemberBuilderImpl
+    implements SourceMemberBuilder {
+  @override
+  MemberDataForTesting? dataForTesting;
+
+  SourceMemberBuilderImpl(Builder parent, int charOffset, [Uri? fileUri])
+      : dataForTesting =
+            retainDataForTesting ? new MemberDataForTesting() : null,
+        super(parent, charOffset, fileUri);
+
+  bool get isRedirectingGenerativeConstructor => false;
+
+  bool? _isConflictingSetter;
+
+  @override
+  bool get isConflictingSetter {
+    return _isConflictingSetter ??= false;
+  }
+
+  void set isConflictingSetter(bool value) {
+    assert(_isConflictingSetter == null,
+        '$this.isConflictingSetter has already been fixed.');
+    _isConflictingSetter = value;
+  }
+
+  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
+  @override
+  ProcedureKind? get kind => unsupported("kind", charOffset, fileUri);
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      ClassHierarchy classHierarchy,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
+
+  @override
+  StringBuffer printOn(StringBuffer buffer) {
+    if (isClassMember) {
+      buffer.write(classBuilder!.name);
+      buffer.write('.');
+    }
+    buffer.write(name);
+    return buffer;
+  }
+
+  /// The builder for the enclosing class or extension, if any.
+  DeclarationBuilder? get declarationBuilder =>
+      parent is DeclarationBuilder ? parent as DeclarationBuilder : null;
+}
+
+enum BuiltMemberKind {
+  Constructor,
+  RedirectingFactory,
+  Field,
+  Method,
+  ExtensionField,
+  ExtensionMethod,
+  ExtensionGetter,
+  ExtensionSetter,
+  ExtensionOperator,
+  ExtensionTearOff,
+  LateIsSetField,
+  LateGetter,
+  LateSetter,
+}
+
+class MemberDataForTesting {
+  final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
+
+  MemberBuilder? patchForTesting;
+}
+
+/// If the name of [member] is private, update it to use the library reference
+/// of [libraryBuilder].
+// TODO(johnniwinther): Avoid having to update private names by setting
+// the correct library reference when creating parts.
+void updatePrivateMemberName(Member member, LibraryBuilder libraryBuilder) {
+  if (member.name.isPrivate) {
+    member.name = new Name(member.name.text, libraryBuilder.library);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
new file mode 100644
index 0000000..44af31f
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
@@ -0,0 +1,534 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All 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/type_algebra.dart';
+
+import '../builder/builder.dart';
+import '../builder/extension_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/procedure_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../kernel/hierarchy/class_member.dart';
+import '../kernel/hierarchy/members_builder.dart';
+import '../kernel/member_covariance.dart';
+import '../source/name_scheme.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import 'source_function_builder.dart';
+import 'source_member_builder.dart';
+
+class SourceProcedureBuilder extends SourceFunctionBuilderImpl
+    implements ProcedureBuilder {
+  final int charOpenParenOffset;
+
+  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+  @override
+  final bool isExtensionInstanceMember;
+
+  late Procedure _procedure;
+
+  final Reference? _tearOffReference;
+
+  /// If this is an extension instance method then [_extensionTearOff] holds
+  /// the synthetically created tear off function.
+  Procedure? _extensionTearOff;
+
+  /// If this is an extension instance method then
+  /// [_extensionTearOffParameterMap] holds a map from the parameters of
+  /// the methods to the parameter of the closure returned in the tear-off.
+  ///
+  /// This map is used to set the default values on the closure parameters when
+  /// these have been built.
+  Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
+
+  @override
+  final ProcedureKind kind;
+
+  SourceProcedureBuilder? actualOrigin;
+
+  SourceProcedureBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder? returnType,
+      String name,
+      List<TypeVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      this.kind,
+      SourceLibraryBuilder libraryBuilder,
+      int startCharOffset,
+      int charOffset,
+      this.charOpenParenOffset,
+      int charEndOffset,
+      Reference? procedureReference,
+      this._tearOffReference,
+      AsyncMarker asyncModifier,
+      NameScheme nameScheme,
+      {required bool isExtensionMember,
+      required bool isInstanceMember,
+      String? nativeMethodName})
+      // ignore: unnecessary_null_comparison
+      : assert(isExtensionMember != null),
+        // ignore: unnecessary_null_comparison
+        assert(isInstanceMember != null),
+        assert(kind != ProcedureKind.Factory),
+        this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
+        super(metadata, modifiers, returnType, name, typeVariables, formals,
+            libraryBuilder, charOffset, nativeMethodName) {
+    _procedure = new Procedure(
+        nameScheme.getProcedureName(kind, name),
+        isExtensionInstanceMember ? ProcedureKind.Method : kind,
+        new FunctionNode(null),
+        fileUri: libraryBuilder.fileUri,
+        reference: procedureReference)
+      ..startFileOffset = startCharOffset
+      ..fileOffset = charOffset
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+    this.asyncModifier = asyncModifier;
+    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+      _extensionTearOff ??= new Procedure(
+          nameScheme.getProcedureName(ProcedureKind.Getter, name),
+          ProcedureKind.Method,
+          new FunctionNode(null),
+          isStatic: true,
+          isExtensionMember: true,
+          reference: _tearOffReference,
+          fileUri: fileUri)
+        ..isNonNullableByDefault = library.isNonNullableByDefault;
+    }
+  }
+
+  ProcedureBuilder? get patchForTesting =>
+      dataForTesting?.patchForTesting as ProcedureBuilder?;
+
+  @override
+  AsyncMarker get asyncModifier => actualAsyncModifier;
+
+  @override
+  Statement? get body {
+    if (bodyInternal == null && !isAbstract && !isExternal) {
+      bodyInternal = new EmptyStatement();
+    }
+    return bodyInternal;
+  }
+
+  void set asyncModifier(AsyncMarker newModifier) {
+    actualAsyncModifier = newModifier;
+    function.asyncMarker = actualAsyncModifier;
+    function.dartAsyncMarker = actualAsyncModifier;
+  }
+
+  bool get isEligibleForTopLevelInference {
+    if (isDeclarationInstanceMember) {
+      if (returnType == null) return true;
+      if (formals != null) {
+        for (FormalParameterBuilder formal in formals!) {
+          if (formal.type == null) return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  bool get isExtensionMethod {
+    return parent is ExtensionBuilder;
+  }
+
+  @override
+  Member get member => procedure;
+
+  @override
+  SourceProcedureBuilder get origin => actualOrigin ?? this;
+
+  @override
+  Procedure get procedure => isPatch ? origin.procedure : _procedure;
+
+  Procedure get actualProcedure => _procedure;
+
+  @override
+  FunctionNode get function => _procedure.function;
+
+  bool _typeEnsured = false;
+  Set<ClassMember>? _overrideDependencies;
+
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    assert(
+        overriddenMembers.every((overriddenMember) =>
+            overriddenMember.classBuilder != classBuilder),
+        "Unexpected override dependencies for $this: $overriddenMembers");
+    _overrideDependencies ??= {};
+    _overrideDependencies!.addAll(overriddenMembers);
+  }
+
+  void _ensureTypes(ClassMembersBuilder membersBuilder) {
+    if (_typeEnsured) return;
+    if (_overrideDependencies != null) {
+      if (isGetter) {
+        membersBuilder.inferGetterType(this, _overrideDependencies!);
+      } else if (isSetter) {
+        membersBuilder.inferSetterType(this, _overrideDependencies!);
+      } else {
+        membersBuilder.inferMethodType(this, _overrideDependencies!);
+      }
+      _overrideDependencies = null;
+    }
+    _typeEnsured = true;
+  }
+
+  @override
+  Member? get readTarget {
+    switch (kind) {
+      case ProcedureKind.Method:
+        return extensionTearOff ?? procedure;
+      case ProcedureKind.Getter:
+        return procedure;
+      case ProcedureKind.Factory:
+        return procedure;
+      case ProcedureKind.Operator:
+      case ProcedureKind.Setter:
+        return null;
+    }
+  }
+
+  @override
+  Member? get writeTarget {
+    switch (kind) {
+      case ProcedureKind.Setter:
+        return procedure;
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return null;
+    }
+  }
+
+  @override
+  Member? get invokeTarget {
+    switch (kind) {
+      case ProcedureKind.Method:
+      case ProcedureKind.Getter:
+      case ProcedureKind.Operator:
+      case ProcedureKind.Factory:
+        return procedure;
+      case ProcedureKind.Setter:
+        return null;
+    }
+  }
+
+  @override
+  Iterable<Member> get exportedMembers => [procedure];
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    if (isExtensionMethod) {
+      switch (kind) {
+        case ProcedureKind.Method:
+          f(member, BuiltMemberKind.ExtensionMethod);
+          break;
+        case ProcedureKind.Getter:
+          f(member, BuiltMemberKind.ExtensionGetter);
+          break;
+        case ProcedureKind.Setter:
+          f(member, BuiltMemberKind.ExtensionSetter);
+          break;
+        case ProcedureKind.Operator:
+          f(member, BuiltMemberKind.ExtensionOperator);
+          break;
+        case ProcedureKind.Factory:
+          throw new UnsupportedError(
+              'Unexpected extension method kind ${kind}');
+      }
+      if (extensionTearOff != null) {
+        f(extensionTearOff!, BuiltMemberKind.ExtensionTearOff);
+      }
+    } else {
+      f(member, BuiltMemberKind.Method);
+    }
+  }
+
+  @override
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    buildFunction(libraryBuilder);
+    _procedure.function.fileOffset = charOpenParenOffset;
+    _procedure.function.fileEndOffset = _procedure.fileEndOffset;
+    _procedure.isAbstract = isAbstract;
+    _procedure.isExternal = isExternal;
+    _procedure.isConst = isConst;
+    updatePrivateMemberName(_procedure, libraryBuilder);
+    if (isExtensionMethod) {
+      _procedure.isExtensionMember = true;
+      _procedure.isStatic = true;
+      if (isExtensionInstanceMember) {
+        assert(_procedure.kind == ProcedureKind.Method);
+      }
+    } else {
+      _procedure.isStatic = isStatic;
+    }
+    if (extensionTearOff != null) {
+      _buildExtensionTearOff(libraryBuilder, parent as ExtensionBuilder);
+      updatePrivateMemberName(extensionTearOff!, libraryBuilder);
+    }
+    return _procedure;
+  }
+
+  /// Creates a top level function that creates a tear off of an extension
+  /// instance method.
+  ///
+  /// For this declaration
+  ///
+  ///     extension E<T> on A<T> {
+  ///       X method<S>(S s, Y y) {}
+  ///     }
+  ///
+  /// we create the top level function
+  ///
+  ///     X E|method<T, S>(A<T> #this, S s, Y y) {}
+  ///
+  /// and the tear off function
+  ///
+  ///     X Function<S>(S, Y) E|get#method<T>(A<T> #this) {
+  ///       return (S s, Y y) => E|method<T, S>(#this, s, y);
+  ///     }
+  ///
+  void _buildExtensionTearOff(
+      SourceLibraryBuilder libraryBuilder, ExtensionBuilder extensionBuilder) {
+    assert(
+        _extensionTearOff != null, "No extension tear off created for $this.");
+
+    _extensionTearOffParameterMap = {};
+
+    int fileOffset = _procedure.fileOffset;
+    int fileEndOffset = _procedure.fileEndOffset;
+
+    int extensionTypeParameterCount =
+        extensionBuilder.typeParameters?.length ?? 0;
+
+    List<TypeParameter> typeParameters = <TypeParameter>[];
+
+    Map<TypeParameter, DartType> substitutionMap = {};
+    List<DartType> typeArguments = <DartType>[];
+    for (TypeParameter typeParameter in function.typeParameters) {
+      TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
+      typeParameters.add(newTypeParameter);
+      typeArguments.add(substitutionMap[typeParameter] =
+          new TypeParameterType.forAlphaRenaming(
+              typeParameter, newTypeParameter));
+    }
+
+    List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
+    List<TypeParameter> closureTypeParameters = <TypeParameter>[];
+    Substitution substitution = Substitution.fromMap(substitutionMap);
+    for (int index = 0; index < typeParameters.length; index++) {
+      TypeParameter newTypeParameter = typeParameters[index];
+      newTypeParameter.bound =
+          substitution.substituteType(function.typeParameters[index].bound);
+      newTypeParameter.defaultType = function.typeParameters[index].defaultType;
+      if (index < extensionTypeParameterCount) {
+        tearOffTypeParameters.add(newTypeParameter);
+      } else {
+        closureTypeParameters.add(newTypeParameter);
+      }
+    }
+
+    VariableDeclaration copyParameter(
+        VariableDeclaration parameter, DartType type,
+        {required bool isOptional}) {
+      VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
+          type: type,
+          isFinal: parameter.isFinal,
+          isLowered: parameter.isLowered)
+        ..fileOffset = parameter.fileOffset;
+      _extensionTearOffParameterMap![parameter] = newParameter;
+      return newParameter;
+    }
+
+    VariableDeclaration extensionThis = copyParameter(
+        function.positionalParameters.first,
+        substitution.substituteType(function.positionalParameters.first.type),
+        isOptional: false);
+
+    DartType closureReturnType =
+        substitution.substituteType(function.returnType);
+    List<VariableDeclaration> closurePositionalParameters = [];
+    List<Expression> closurePositionalArguments = [];
+
+    for (int position = 0;
+        position < function.positionalParameters.length;
+        position++) {
+      VariableDeclaration parameter = function.positionalParameters[position];
+      if (position == 0) {
+        /// Pass `this` as a captured variable.
+        closurePositionalArguments
+            .add(new VariableGet(extensionThis)..fileOffset = fileOffset);
+      } else {
+        DartType type = substitution.substituteType(parameter.type);
+        VariableDeclaration newParameter = copyParameter(parameter, type,
+            isOptional: position >= function.requiredParameterCount);
+        closurePositionalParameters.add(newParameter);
+        closurePositionalArguments
+            .add(new VariableGet(newParameter)..fileOffset = fileOffset);
+      }
+    }
+    List<VariableDeclaration> closureNamedParameters = [];
+    List<NamedExpression> closureNamedArguments = [];
+    for (VariableDeclaration parameter in function.namedParameters) {
+      DartType type = substitution.substituteType(parameter.type);
+      VariableDeclaration newParameter =
+          copyParameter(parameter, type, isOptional: true);
+      closureNamedParameters.add(newParameter);
+      closureNamedArguments.add(new NamedExpression(parameter.name!,
+          new VariableGet(newParameter)..fileOffset = fileOffset));
+    }
+
+    Statement closureBody = new ReturnStatement(
+        new StaticInvocation(
+            _procedure,
+            new Arguments(closurePositionalArguments,
+                types: typeArguments, named: closureNamedArguments))
+          ..fileOffset = fileOffset)
+      ..fileOffset = fileOffset;
+
+    FunctionExpression closure = new FunctionExpression(
+        new FunctionNode(closureBody,
+            typeParameters: closureTypeParameters,
+            positionalParameters: closurePositionalParameters,
+            namedParameters: closureNamedParameters,
+            requiredParameterCount:
+                _procedure.function.requiredParameterCount - 1,
+            returnType: closureReturnType)
+          ..fileOffset = fileOffset
+          ..fileEndOffset = fileEndOffset)
+      ..fileOffset = fileOffset;
+
+    _extensionTearOff!
+      ..function = (new FunctionNode(
+          new ReturnStatement(closure)..fileOffset = fileOffset,
+          typeParameters: tearOffTypeParameters,
+          positionalParameters: [extensionThis],
+          requiredParameterCount: 1,
+          returnType: closure.function.computeFunctionType(library.nonNullable))
+        ..fileOffset = fileOffset
+        ..fileEndOffset = fileEndOffset)
+      ..fileUri = fileUri
+      ..fileOffset = fileOffset
+      ..fileEndOffset = fileEndOffset;
+    _extensionTearOff!.function.parent = _extensionTearOff;
+  }
+
+  Procedure? get extensionTearOff => _extensionTearOff;
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    return _extensionTearOffParameterMap?[getFormalParameter(index)];
+  }
+
+  List<ClassMember>? _localMembers;
+  List<ClassMember>? _localSetters;
+
+  @override
+  List<ClassMember> get localMembers => _localMembers ??= isSetter
+      ? const <ClassMember>[]
+      : <ClassMember>[new SourceProcedureMember(this)];
+
+  @override
+  List<ClassMember> get localSetters =>
+      _localSetters ??= isSetter && !isConflictingSetter
+          ? <ClassMember>[new SourceProcedureMember(this)]
+          : const <ClassMember>[];
+
+  @override
+  void becomeNative(SourceLoader loader) {
+    _procedure.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is SourceProcedureBuilder) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin.procedure.fileUri = fileUri;
+    origin.procedure.startFileOffset = _procedure.startFileOffset;
+    origin.procedure.fileOffset = _procedure.fileOffset;
+    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
+    origin.procedure.annotations
+        .forEach((m) => m.fileOffset = _procedure.fileOffset);
+
+    origin.procedure.isAbstract = _procedure.isAbstract;
+    origin.procedure.isExternal = _procedure.isExternal;
+    origin.procedure.function = _procedure.function;
+    origin.procedure.function.parent = origin.procedure;
+    origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
+    return 1;
+  }
+}
+
+class SourceProcedureMember extends BuilderClassMember {
+  @override
+  final SourceProcedureBuilder memberBuilder;
+
+  Covariance? _covariance;
+
+  SourceProcedureMember(this.memberBuilder);
+
+  @override
+  bool get isSourceDeclaration => true;
+
+  @override
+  void inferType(ClassMembersBuilder membersBuilder) {
+    memberBuilder._ensureTypes(membersBuilder);
+  }
+
+  @override
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    memberBuilder.registerOverrideDependency(overriddenMembers);
+  }
+
+  @override
+  Member getMember(ClassMembersBuilder membersBuilder) {
+    memberBuilder._ensureTypes(membersBuilder);
+    return memberBuilder.member;
+  }
+
+  @override
+  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+    return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
+        forSetter: forSetter);
+  }
+
+  @override
+  bool get forSetter => isSetter;
+
+  @override
+  bool get isProperty =>
+      memberBuilder.kind == ProcedureKind.Getter ||
+      memberBuilder.kind == ProcedureKind.Setter;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    return other is SourceProcedureMember &&
+        memberBuilder == other.memberBuilder;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index 9585ec4..7ff533d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -6,8 +6,7 @@
 
 import 'package:front_end/src/fasta/kernel/expression_generator_helper.dart';
 import 'package:kernel/ast.dart';
-
-import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
 
 import 'package:kernel/type_algebra.dart'
     show FreshTypeParameters, getFreshTypeParameters;
@@ -258,7 +257,7 @@
 
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
-      CoreTypes coreTypes,
+      ClassHierarchy classHierarchy,
       List<DelayedActionPerformer> delayedActionPerformers,
       List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     MetadataBuilder.buildAnnotations(
@@ -269,7 +268,7 @@
             library,
             null,
             null,
-            coreTypes,
+            classHierarchy,
             delayedActionPerformers,
             computeTypeParameterScope(library.scope));
       }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index b14927c..fcc9c8e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -3,32 +3,22 @@
 // BSD-style license that can be found in the LICENSE.md file.
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
 import 'package:kernel/ast.dart';
-
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
 import 'package:kernel/core_types.dart' show CoreTypes;
-
 import 'package:kernel/type_environment.dart';
 
 import '../../base/instrumentation.dart' show Instrumentation;
-
-import '../builder/constructor_builder.dart';
-
 import '../kernel/forest.dart';
-import '../kernel/implicit_field_type.dart';
-import '../kernel/internal_ast.dart';
 import '../kernel/hierarchy/hierarchy_builder.dart' show ClassHierarchyBuilder;
 import '../kernel/hierarchy/members_builder.dart' show ClassMembersBuilder;
+import '../kernel/implicit_field_type.dart';
+import '../kernel/internal_ast.dart';
 import '../kernel/kernel_helper.dart';
-
+import '../source/source_constructor_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
 import 'factor_type.dart';
-
 import 'type_inferrer.dart';
-
 import 'type_schema_environment.dart' show TypeSchemaEnvironment;
 
 /// Visitor to check whether a given type mentions any of a class's type
@@ -122,14 +112,14 @@
   /// This is represented as a map from a constructor to its library
   /// builder because the builder is used to report errors due to cyclic
   /// inference dependencies.
-  final Map<Constructor, ConstructorBuilder> toBeInferred = {};
+  final Map<Constructor, DeclaredSourceConstructorBuilder> toBeInferred = {};
 
   /// A map containing constructors in the process of being inferred.
   ///
   /// This is used to detect cyclic inference dependencies.  It is represented
   /// as a map from a constructor to its library builder because the builder
   /// is used to report errors.
-  final Map<Constructor, ConstructorBuilder> beingInferred = {};
+  final Map<Constructor, DeclaredSourceConstructorBuilder> beingInferred = {};
 
   final Map<Member, TypeDependency> typeDependencies = {};
 
@@ -153,8 +143,8 @@
   void finishTopLevelInitializingFormals() {
     // Field types have all been inferred so we don't need to guard against
     // cyclic dependency.
-    for (ConstructorBuilder builder in toBeInferred.values) {
-      builder.inferFormalTypes();
+    for (DeclaredSourceConstructorBuilder builder in toBeInferred.values) {
+      builder.inferFormalTypes(classHierarchy);
     }
     toBeInferred.clear();
     for (TypeDependency typeDependency in typeDependencies.values) {
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 5dc515a..bdf3e38 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
@@ -3,19 +3,17 @@
 // BSD-style license that can be found in the LICENSE.md file.
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/util/link.dart';
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/canonical_name.dart' as kernel;
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_algebra.dart';
-import 'package:kernel/type_environment.dart';
 import 'package:kernel/src/bounds_checks.dart' show calculateBounds;
 import 'package:kernel/src/future_value_type.dart';
 import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/type_algebra.dart';
+import 'package:kernel/type_environment.dart';
 
 import '../../base/instrumentation.dart'
     show
@@ -23,32 +21,23 @@
         InstrumentationValueForMember,
         InstrumentationValueForType,
         InstrumentationValueForTypeArgs;
-
 import '../../base/nnbd_mode.dart';
-
 import '../../testing/id_extractor.dart';
 import '../../testing/id_testing_utils.dart';
-
-import '../builder/constructor_builder.dart';
 import '../builder/extension_builder.dart';
 import '../builder/member_builder.dart';
-
 import '../fasta_codes.dart';
-
-import '../kernel/hierarchy/class_member.dart' show ClassMember;
 import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/kernel_helper.dart';
+import '../kernel/hierarchy/class_member.dart' show ClassMember;
 import '../kernel/inference_visitor.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/invalid_type.dart';
+import '../kernel/kernel_helper.dart';
 import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
-
 import '../names.dart';
-
 import '../problems.dart' show internalProblem, unexpected, unhandled;
-
+import '../source/source_constructor_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
 import 'inference_helper.dart' show InferenceHelper;
 import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
 import 'type_demotion.dart';
@@ -127,7 +116,7 @@
   AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables;
 
   /// Performs full type inference on the given field initializer.
-  Expression inferFieldInitializer(
+  ExpressionInferenceResult inferFieldInitializer(
       InferenceHelper helper, DartType declaredType, Expression initializer);
 
   /// Returns the type used as the inferred type of a variable declaration,
@@ -181,8 +170,17 @@
   final TypeInferenceEngine engine;
 
   @override
-  final FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration,
-      DartType> flowAnalysis;
+  late final FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration,
+          DartType> flowAnalysis =
+      library.isNonNullableByDefault
+          ? new FlowAnalysis(
+              new TypeOperationsCfe(engine.typeSchemaEnvironment),
+              assignedVariables,
+              respectImplicitlyTypedVarInitializers:
+                  library.enableConstructorTearOffsInLibrary)
+          : new FlowAnalysis.legacy(
+              new TypeOperationsCfe(engine.typeSchemaEnvironment),
+              assignedVariables);
 
   @override
   final AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;
@@ -224,16 +222,7 @@
         classHierarchy = engine.classHierarchy,
         instrumentation = topLevel ? null : engine.instrumentation,
         typeSchemaEnvironment = engine.typeSchemaEnvironment,
-        isTopLevel = topLevel,
-        flowAnalysis = library.isNonNullableByDefault
-            ? new FlowAnalysis(
-                new TypeOperationsCfe(engine.typeSchemaEnvironment),
-                assignedVariables,
-                respectImplicitlyTypedVarInitializers:
-                    library.enableConstructorTearOffsInLibrary)
-            : new FlowAnalysis.legacy(
-                new TypeOperationsCfe(engine.typeSchemaEnvironment),
-                assignedVariables) {}
+        isTopLevel = topLevel {}
 
   CoreTypes get coreTypes => engine.coreTypes;
 
@@ -376,7 +365,8 @@
 
   @override
   void inferConstructorParameterTypes(Constructor target) {
-    ConstructorBuilder? constructor = engine.beingInferred[target];
+    DeclaredSourceConstructorBuilder? constructor =
+        engine.beingInferred[target];
     if (constructor != null) {
       // There is a cyclic dependency where inferring the types of the
       // initializing formals of a constructor required us to infer the
@@ -405,7 +395,7 @@
     } else if ((constructor = engine.toBeInferred[target]) != null) {
       engine.toBeInferred.remove(target);
       engine.beingInferred[target] = constructor!;
-      constructor.inferFormalTypes();
+      constructor.inferFormalTypes(classHierarchy);
       engine.beingInferred.remove(target);
     }
   }
@@ -2041,7 +2031,7 @@
   }
 
   @override
-  Expression inferFieldInitializer(
+  ExpressionInferenceResult inferFieldInitializer(
     InferenceHelper helper,
     DartType context,
     Expression initializer,
@@ -2054,7 +2044,8 @@
     initializer = ensureAssignableResult(context, initializerResult,
         isVoidAllowed: context is VoidType);
     this.helper = null;
-    return initializer;
+    return new ExpressionInferenceResult(
+        initializerResult.inferredType, initializer);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/uri_translator.dart b/pkg/front_end/lib/src/fasta/uri_translator.dart
index cf624b4..dac8845 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator.dart
@@ -50,9 +50,7 @@
   }
 
   bool isLibrarySupported(String libraryName) {
-    // TODO(sigmund): change this to `?? false` when all backends provide the
-    // `libraries.json` file by default (Issue #32657).
-    return dartLibraries.libraryInfoFor(libraryName)?.isSupported ?? true;
+    return dartLibraries.libraryInfoFor(libraryName)?.isSupported ?? false;
   }
 
   Uri? _translateDartUri(Uri uri) {
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 4d54b4b..948c756 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -23,7 +23,7 @@
 
 import 'fasta/fasta_codes.dart' show LocatedMessage;
 
-import 'fasta/kernel/kernel_target.dart' show KernelTarget;
+import 'fasta/kernel/kernel_target.dart' show BuildResult, KernelTarget;
 
 import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
 
@@ -96,8 +96,9 @@
         new KernelTarget(fs, false, dillTarget, uriTranslator);
     sourceLoader = kernelTarget.loader;
     kernelTarget.setEntryPoints(options.inputs);
-    Component summaryComponent =
-        (await kernelTarget.buildOutlines(nameRoot: nameRoot))!;
+    BuildResult buildResult =
+        await kernelTarget.buildOutlines(nameRoot: nameRoot);
+    Component summaryComponent = buildResult.component!;
     List<int>? summary = null;
     if (buildSummary) {
       if (options.verify) {
@@ -159,13 +160,19 @@
 
     Component? component;
     if (buildComponent) {
-      component = await kernelTarget.buildComponent(verify: options.verify);
+      buildResult = await kernelTarget.buildComponent(
+          macroApplications: buildResult.macroApplications,
+          verify: options.verify);
+      component = buildResult.component;
       if (options.debugDump) {
         printComponentText(component,
             libraryFilter: kernelTarget.isSourceLibraryForDebugging);
       }
       options.ticker.logMs("Generated component");
     }
+    // TODO(johnniwinther): Should we reuse the macro executor on subsequent
+    // compilations where possible?
+    buildResult.macroApplications?.close();
 
     return new InternalCompilerResult(
         summary: summary,
@@ -176,7 +183,7 @@
             includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
         coreTypes:
             includeHierarchyAndCoreTypes ? kernelTarget.loader.coreTypes : null,
-        deps: new List<Uri>.from(CompilerContext.current.dependencies),
+        deps: new List<Uri>.of(CompilerContext.current.dependencies),
         kernelTargetForTesting: retainDataForTesting ? kernelTarget : null);
   }, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
 }
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index 77a6a44..b9a1a86 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -4,11 +4,20 @@
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 import 'package:_fe_analyzer_shared/src/testing/id.dart'
-    show ActualData, ClassId, Id, IdKind, IdValue, MemberId, NodeId;
+    show
+        ActualData,
+        ClassId,
+        DataRegistry,
+        Id,
+        IdKind,
+        IdValue,
+        MemberId,
+        NodeId;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/base/nnbd_mode.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/target/targets.dart';
+
 import '../api_prototype/compiler_options.dart'
     show CompilerOptions, DiagnosticMessage;
 import '../api_prototype/experimental_flags.dart'
@@ -23,8 +32,8 @@
 import 'id_testing_utils.dart';
 
 export '../fasta/compiler_context.dart' show CompilerContext;
-export '../kernel_generator_impl.dart' show InternalCompilerResult;
 export '../fasta/messages.dart' show FormattedMessage;
+export '../kernel_generator_impl.dart' show InternalCompilerResult;
 
 /// Test configuration used for testing CFE in its default state.
 const TestConfig defaultCfeConfig = const TestConfig(cfeMarker, 'cfe');
@@ -68,58 +77,53 @@
       this.targetFlags: const TestTargetFlags(),
       this.nnbdMode: NnbdMode.Weak});
 
-  void customizeCompilerOptions(CompilerOptions options, TestData testData) {}
+  /// Called before running test on [testData].
+  ///
+  /// This allows tests to customize the [options] based on the [testData].
+  ///
+  /// A custom object can be returned. This is passed to data computer.
+  dynamic customizeCompilerOptions(
+          CompilerOptions options, TestData testData) =>
+      null;
 }
 
-// TODO(johnniwinther): Support annotations for compile-time errors.
 abstract class DataComputer<T> {
   const DataComputer();
 
   /// Called before testing to setup flags needed for data collection.
   void setup() {}
 
-  // Called to allow for (awaited) inspection of the compilation result.
-  Future<void> inspectComponent(Component component) {
+  /// Called to allow for (awaited) inspection of the [testResultData] from
+  /// running the test.
+  Future<void> inspectTestResultData(TestResultData testResultData) {
     return new Future.value(null);
   }
 
   /// Function that computes a data mapping for [member].
   ///
   /// Fills [actualMap] with the data.
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<T>> actualMap,
       {bool? verbose}) {}
 
   /// Function that computes a data mapping for [cls].
   ///
   /// Fills [actualMap] with the data.
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<T>> actualMap,
       {bool? verbose}) {}
 
   /// Function that computes a data mapping for [extension].
   ///
   /// Fills [actualMap] with the data.
-  void computeExtensionData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Extension extension,
+  void computeExtensionData(TestResultData testResultData, Extension extension,
       Map<Id, ActualData<T>> actualMap,
       {bool? verbose}) {}
 
   /// Function that computes a data mapping for [library].
   ///
   /// Fills [actualMap] with the data.
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<T>> actualMap,
       {bool? verbose}) {}
 
@@ -131,7 +135,7 @@
   bool get supportsErrors => false;
 
   /// Returns data corresponding to [error].
-  T? computeErrorData(TestConfig config, InternalCompilerResult compiler, Id id,
+  T? computeErrorData(TestResultData testResultData, Id id,
           List<FormattedMessage> errors) =>
       null;
 
@@ -143,6 +147,21 @@
   bool get includeMemberSignatures => false;
 }
 
+/// Auxiliary data from running a test.
+class TestResultData {
+  /// The test config used to run the test.
+  final TestConfig config;
+
+  /// CustomData is passed from [TestConfig.customizeCompilerOptions].
+  final dynamic customData;
+
+  /// The compiler result from running the test, include access to the used
+  /// compiler.
+  final InternalCompilerResult compilerResult;
+
+  TestResultData(this.config, this.customData, this.compilerResult);
+}
+
 class CfeCompiledData<T> extends CompiledData<T> {
   final InternalCompilerResult compilerResult;
 
@@ -203,11 +222,8 @@
   }
 }
 
-abstract class CfeDataExtractor<T> extends DataExtractor<T> {
-  final InternalCompilerResult compilerResult;
-
-  CfeDataExtractor(this.compilerResult, Map<Id, ActualData<T>> actualMap)
-      : super(actualMap);
+mixin CfeDataRegistryMixin<T> implements DataRegistry<T> {
+  InternalCompilerResult get compilerResult;
 
   @override
   void report(Uri uri, int offset, String message) {
@@ -221,6 +237,25 @@
   }
 }
 
+class CfeDataRegistry<T> with DataRegistry<T>, CfeDataRegistryMixin<T> {
+  @override
+  final InternalCompilerResult compilerResult;
+
+  @override
+  final Map<Id, ActualData<T>> actualMap;
+
+  CfeDataRegistry(this.compilerResult, this.actualMap);
+}
+
+abstract class CfeDataExtractor<T> extends DataExtractor<T>
+    with CfeDataRegistryMixin<T> {
+  @override
+  final InternalCompilerResult compilerResult;
+
+  CfeDataExtractor(this.compilerResult, Map<Id, ActualData<T>> actualMap)
+      : super(actualMap);
+}
+
 /// Create the testing URI used for [fileName] in annotated tests.
 Uri createUriForFileName(String fileName) => toTestUri(fileName);
 
@@ -325,13 +360,16 @@
     }
   }
   options.packagesFileUri = config.packageConfigUri;
-  config.customizeCompilerOptions(options, testData);
+  dynamic customData = config.customizeCompilerOptions(options, testData);
   InternalCompilerResult compilerResult = await compileScript(
       testData.memorySourceFiles,
       options: options,
       retainDataForTesting: true,
       requireMain: false) as InternalCompilerResult;
 
+  TestResultData testResultData =
+      new TestResultData(config, customData, compilerResult);
+
   Component component = compilerResult.component!;
   Map<Uri, Map<Id, ActualData<T>>> actualMaps = <Uri, Map<Id, ActualData<T>>>{};
   Map<Id, ActualData<T>> globalData = <Id, ActualData<T>>{};
@@ -362,8 +400,7 @@
           offset = 0;
         }
         NodeId id = new NodeId(offset, IdKind.error);
-        T? data =
-            dataComputer.computeErrorData(config, compilerResult, id, list);
+        T? data = dataComputer.computeErrorData(testResultData, id, list);
         if (data != null) {
           Map<Id, ActualData<T>> actualMap = actualMapForUri(uri);
           actualMap[id] = new ActualData<T>(id, data, uri, offset, list);
@@ -398,18 +435,17 @@
         return;
       }
     }
-    dataComputer.computeMemberData(config, compilerResult, member, actualMap,
+    dataComputer.computeMemberData(testResultData, member, actualMap,
         verbose: verbose);
   }
 
   void processClass(Class cls, Map<Id, ActualData<T>> actualMap) {
-    dataComputer.computeClassData(config, compilerResult, cls, actualMap,
+    dataComputer.computeClassData(testResultData, cls, actualMap,
         verbose: verbose);
   }
 
   void processExtension(Extension extension, Map<Id, ActualData<T>> actualMap) {
-    dataComputer.computeExtensionData(
-        config, compilerResult, extension, actualMap,
+    dataComputer.computeExtensionData(testResultData, extension, actualMap,
         verbose: verbose);
   }
 
@@ -419,7 +455,7 @@
             library.importUri.scheme == 'package');
   }
 
-  await dataComputer.inspectComponent(component);
+  await dataComputer.inspectTestResultData(testResultData);
 
   for (Library library in component.libraries) {
     if (excludeLibrary(library) &&
@@ -427,7 +463,7 @@
       continue;
     }
     dataComputer.computeLibraryData(
-        config, compilerResult, library, actualMapFor(library));
+        testResultData, library, actualMapFor(library));
     for (Class cls in library.classes) {
       processClass(cls, actualMapFor(cls));
       for (Member member in cls.members) {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 10ad152..74da302 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -111,6 +111,7 @@
 ConstEvalExternalFactory/example: Fail
 ConstEvalFailedAssertion/example: Fail
 ConstEvalFailedAssertionWithMessage/example: Fail
+ConstEvalFailedAssertionWithNonStringMessage/example: Fail
 ConstEvalFreeTypeParameter/analyzerCode: Fail
 ConstEvalFreeTypeParameter/example: Fail
 ConstEvalGetterNotFound/analyzerCode: Fail
@@ -212,9 +213,15 @@
 DuplicatedParameterName/example: Fail
 Encoding/analyzerCode: Fail
 EnumConstantSameNameAsEnclosing/example: Fail
+EnumDeclaresConstFactory/analyzerCode: Fail
+EnumDeclaresConstFactory/example: Fail
 EnumDeclaresFactory/analyzerCode: Fail
 EnumDeclaresFactory/example: Fail
+EnumEntryWithTypeArgumentsWithoutArguments/analyzerCode: Fail
+EnumEntryWithTypeArgumentsWithoutArguments/example: Fail
 EnumInstantiation/example: Fail
+EnumSupertypeOfNonAbstractClass/analyzerCode: Fail
+EnumSupertypeOfNonAbstractClass/example: Fail
 EqualityCannotBeEqualityOperand/part_wrapped_script1: Fail
 EqualityCannotBeEqualityOperand/part_wrapped_script2: Fail
 EqualityCannotBeEqualityOperand/script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 6632763..67467be 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -189,6 +189,10 @@
   problemMessage: "This assertion failed with message: #stringOKEmpty"
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
 
+ConstEvalFailedAssertionWithNonStringMessage:
+  problemMessage: "This assertion failed with a non-String message."
+  analyzerCode: CONST_EVAL_THROWS_EXCEPTION
+
 ConstEvalNonConstantVariableGet:
   problemMessage: "The variable '#nameOKEmpty' is not a constant, only constant expressions are allowed."
   analyzerCode: NON_CONSTANT_VALUE_IN_INITIALIZER
@@ -4460,16 +4464,6 @@
   problemMessage: "If you want '#type' to be a super-bounded type, note that the inverted type '#type2' must then satisfy its bounds, which it does not."
   severity: CONTEXT
 
-InferredPackageUri:
-  problemMessage: "Interpreting this as package URI, '#uri'."
-  severity: WARNING
-  frontendInternal: true
-  script:
-    "main.dart": |
-      main() {}
-    ".packages": |
-      example:./
-
 MixinApplicationIncompatibleSupertype:
   problemMessage: "'#type' doesn't implement '#type2' so it can't be used with '#type3'."
   analyzerCode: MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE
@@ -5451,8 +5445,8 @@
   script: |
     method(dynamic d) => d.new;
 
-EnumDeclaresFactory:
-  problemMessage: "Enums can't declare factory constructors."
+EnumDeclaresConstFactory:
+  problemMessage: "Enums can't declare const factory constructors."
   correctionMessage: "Try removing the factory constructor declaration."
 
 PositionalSuperParametersAndArguments:
@@ -5461,3 +5455,9 @@
 SuperInitializerParameter:
   problemMessage: "This is the super-initializer parameter."
   severity: CONTEXT
+
+EnumSupertypeOfNonAbstractClass:
+  problemMessage: "Non-abstract class '#name' has 'Enum' as a superinterface."
+
+EnumEntryWithTypeArgumentsWithoutArguments:
+  problemMessage: "Missing arguments in enum constructor invocation."
diff --git a/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart b/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
index 76f3281..9110735 100644
--- a/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
+++ b/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
@@ -34,24 +34,18 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new InheritanceDataExtractor(compilerResult, actualMap)
+    new InheritanceDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new InheritanceDataExtractor(compilerResult, actualMap)
+    new InheritanceDataExtractor(testResultData.compilerResult, actualMap)
         .computeForClass(cls);
   }
 
@@ -59,8 +53,8 @@
   bool get supportsErrors => true;
 
   @override
-  Features? computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  Features? computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     return null; //errorsToText(errors, useCodes: true);
   }
 
diff --git a/pkg/front_end/test/constant_evaluator_benchmark.dart b/pkg/front_end/test/constant_evaluator_benchmark.dart
index 35f5faa..c86c066 100644
--- a/pkg/front_end/test/constant_evaluator_benchmark.dart
+++ b/pkg/front_end/test/constant_evaluator_benchmark.dart
@@ -7,43 +7,33 @@
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart';
 import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
-
 import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
-
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions, DiagnosticMessage;
-
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
     show ExperimentalFlag;
-
 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/incremental_compiler.dart'
     show IncrementalCompiler;
 import 'package:front_end/src/fasta/kernel/constant_evaluator.dart' as constants
     show EvaluationMode, transformLibraries, ErrorReporter;
-
 import 'package:front_end/src/fasta/kernel/kernel_target.dart';
+import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
 import 'package:kernel/ast.dart';
 import 'package:kernel/binary/ast_from_binary.dart';
-import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
 import 'package:kernel/target/changed_structure_notifier.dart';
 import 'package:kernel/target/targets.dart'
-    show ConstantsBackend, DiagnosticReporter, Target, TargetFlags;
+    show DiagnosticReporter, Target, TargetFlags;
 import 'package:kernel/type_environment.dart';
-
 import "package:vm/target/flutter.dart" show FlutterTarget;
-
 import "package:vm/target/vm.dart" show VmTarget;
 
 import 'incremental_suite.dart' show getOptions;
 
-import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
-
 bool? tryWithNoEnvironment;
 bool verbose = false;
 bool skipNonNullEnvironment = false;
@@ -80,8 +70,6 @@
 
         stopwatch.reset();
         CoreTypes coreTypes = new CoreTypes(component);
-        ConstantsBackend constantsBackend =
-            target.backendTarget.constantsBackend;
         ClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes);
         TypeEnvironment environment = new TypeEnvironment(coreTypes, hierarchy);
         if (verbose) {
@@ -91,8 +79,9 @@
 
         stopwatch.reset();
         constants.transformLibraries(
+            component,
             component.libraries,
-            constantsBackend,
+            target.backendTarget,
             environmentDefines,
             environment,
             new SilentErrorReporter(),
diff --git a/pkg/front_end/test/covariance_check/covariance_check_test.dart b/pkg/front_end/test/covariance_check/covariance_check_test.dart
index c91c012..074088c 100644
--- a/pkg/front_end/test/covariance_check/covariance_check_test.dart
+++ b/pkg/front_end/test/covariance_check/covariance_check_test.dart
@@ -26,24 +26,19 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new CovarianceCheckDataExtractor(compilerResult, actualMap)
+    new CovarianceCheckDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    member.accept(new CovarianceCheckDataExtractor(compilerResult, actualMap));
+    member.accept(new CovarianceCheckDataExtractor(
+        testResultData.compilerResult, actualMap));
   }
 
   @override
diff --git a/pkg/front_end/test/explicit_creation_git_test.dart b/pkg/front_end/test/explicit_creation_git_test.dart
index dc8e3a1..3200635 100644
--- a/pkg/front_end/test/explicit_creation_git_test.dart
+++ b/pkg/front_end/test/explicit_creation_git_test.dart
@@ -101,8 +101,10 @@
 
     kernelTarget.setEntryPoints(c.options.inputs);
     dillTarget.buildOutlines();
-    await kernelTarget.buildOutlines();
-    await kernelTarget.buildComponent();
+    BuildResult buildResult = await kernelTarget.buildOutlines();
+    buildResult = await kernelTarget.buildComponent(
+        macroApplications: buildResult.macroApplications);
+    buildResult.macroApplications?.close();
   });
 
   print("Done in ${stopwatch.elapsedMilliseconds} ms. "
@@ -137,9 +139,11 @@
       DeclarationBuilder? declarationBuilder,
       ModifierBuilder member,
       Scope scope,
-      Uri fileUri) {
+      Uri fileUri,
+      {Scope? formalParameterScope}) {
     return new BodyBuilderTest.forOutlineExpression(
-        library, declarationBuilder, member, scope, fileUri);
+        library, declarationBuilder, member, scope, fileUri,
+        formalParameterScope: formalParameterScope);
   }
 
   @override
@@ -220,9 +224,11 @@
       DeclarationBuilder? declarationBuilder,
       ModifierBuilder member,
       Scope scope,
-      Uri fileUri)
+      Uri fileUri,
+      {Scope? formalParameterScope})
       : super.forOutlineExpression(
-            library, declarationBuilder, member, scope, fileUri);
+            library, declarationBuilder, member, scope, fileUri,
+            formalParameterScope: formalParameterScope);
 
   @override
   Expression buildConstructorInvocation(
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index 2bb86f3..bb09833 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -3,20 +3,20 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
-
 import 'package:front_end/src/fasta/builder/class_builder.dart';
 import 'package:front_end/src/fasta/builder/extension_builder.dart';
 import 'package:front_end/src/fasta/builder/formal_parameter_builder.dart';
-import 'package:front_end/src/fasta/builder/function_builder.dart';
 import 'package:front_end/src/fasta/builder/library_builder.dart';
 import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/builder/type_builder.dart';
 import 'package:front_end/src/fasta/builder/type_variable_builder.dart';
+import 'package:front_end/src/fasta/source/source_function_builder.dart';
 import 'package:front_end/src/fasta/source/source_library_builder.dart';
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart';
@@ -38,44 +38,34 @@
   const ExtensionsDataComputer();
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    member.accept(new ExtensionsDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new ExtensionsDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new ExtensionsDataExtractor(compilerResult, actualMap).computeForClass(cls);
+    new ExtensionsDataExtractor(testResultData.compilerResult, actualMap)
+        .computeForClass(cls);
   }
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new ExtensionsDataExtractor(compilerResult, actualMap)
+    new ExtensionsDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeExtensionData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Extension extension,
+  void computeExtensionData(TestResultData testResultData, Extension extension,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new ExtensionsDataExtractor(compilerResult, actualMap)
+    new ExtensionsDataExtractor(testResultData.compilerResult, actualMap)
         .computeForExtension(extension);
   }
 
@@ -83,8 +73,8 @@
   bool get supportsErrors => true;
 
   @override
-  Features computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  Features computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     Features features = new Features();
     for (FormattedMessage error in errors) {
       if (error.problemMessage.contains(',')) {
@@ -240,7 +230,7 @@
     MemberBuilder memberBuilder = lookupMemberBuilder(compilerResult, member)!;
     Features features = new Features();
     features[Tags.builderName] = memberBuilder.name;
-    if (memberBuilder is FunctionBuilder) {
+    if (memberBuilder is SourceFunctionBuilder) {
       if (memberBuilder.formals != null) {
         for (FormalParameterBuilder parameter in memberBuilder.formals!) {
           if (parameter.isRequired) {
diff --git a/pkg/front_end/test/fasta/expression_suite.dart b/pkg/front_end/test/fasta/expression_suite.dart
index 371e8ef..03eeb59 100644
--- a/pkg/front_end/test/fasta/expression_suite.dart
+++ b/pkg/front_end/test/fasta/expression_suite.dart
@@ -8,6 +8,8 @@
 
 import "dart:io" show File, IOSink;
 
+import 'dart:typed_data' show Uint8List;
+
 import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
 
 import "package:front_end/src/api_prototype/compiler_options.dart"
@@ -48,7 +50,7 @@
 import "package:yaml/yaml.dart" show YamlMap, YamlList, loadYamlNode;
 
 import '../../lib/src/fasta/kernel/utils.dart'
-    show writeComponentToFile, serializeProcedure;
+    show serializeComponent, serializeProcedure;
 
 import '../utils/kernel_chain.dart' show runDiff, openWrite;
 
@@ -375,17 +377,16 @@
       Component component = sourceCompilerResult.component;
       var errors = context.takeErrors();
       if (!errors.isEmpty) {
-        return fail(tests, "Couldn't compile entry-point: $errors");
+        return fail(
+            tests,
+            "Couldn't compile entry-point: "
+            "${errors.map((e) => e.plainTextFormatted.first).toList()}");
       }
       Uri dillFileUri = new Uri(
           scheme: test.entryPoint!.scheme,
           path: test.entryPoint!.path + ".dill");
-      File dillFile = new File.fromUri(dillFileUri);
-      if (!await dillFile.exists()) {
-        await writeComponentToFile(component, dillFileUri);
-        context.fileSystem.entityForUri(dillFileUri).writeAsBytesSync(
-            await new File.fromUri(dillFileUri).readAsBytes());
-      }
+      Uint8List dillData = await serializeComponent(component);
+      context.fileSystem.entityForUri(dillFileUri).writeAsBytesSync(dillData);
       await compileExpression(test, sourceCompiler, component, context);
 
       var dillCompiler =
@@ -394,7 +395,6 @@
           await dillCompiler.computeDelta(entryPoints: [test.entryPoint!]);
       component = dillCompilerResult.component;
       component.computeCanonicalNames();
-      await dillFile.delete();
 
       errors = context.takeErrors();
       // Since it compiled successfully from source, the bootstrap-from-Dill
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index f4790b9..787ad86 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -94,7 +94,8 @@
                 new DillTarget(c.options.ticker, uriTranslator,
                     new NoneTarget(new TargetFlags())),
                 uriTranslator)
-            .loader);
+            .loader,
+        isUnsupported: false);
     libraryBuilder.markLanguageVersionFinal();
     LoadLibraryBuilder loadLibraryBuilder =
         new LoadLibraryBuilder(libraryBuilder, dummyLibraryDependency, -1);
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index f7221fd..02231dd 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -5,91 +5,63 @@
 library fasta.testing.suite;
 
 import 'dart:convert' show jsonDecode, utf8;
-
 import 'dart:io' show Directory, File, Platform;
-
 import 'dart:typed_data' show Uint8List;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show LanguageVersionToken, Token;
-
 import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
 import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart'
     show LibraryInfo;
 import 'package:_fe_analyzer_shared/src/util/options.dart';
 import 'package:compiler/src/kernel/dart2js_target.dart';
 import 'package:dev_compiler/src/kernel/target.dart';
-
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show
         CompilerOptions,
         DiagnosticMessage,
         parseExperimentalArguments,
         parseExperimentalFlags;
-
 import 'package:front_end/src/api_prototype/constant_evaluator.dart'
     show ConstantEvaluator, ErrorReporter, EvaluationMode;
-
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
     show
         AllowedExperimentalFlags,
         ExperimentalFlag,
         defaultAllowedExperimentalFlags,
         isExperimentEnabled;
-
 import 'package:front_end/src/api_prototype/file_system.dart'
     show FileSystem, FileSystemEntity, FileSystemException;
-
 import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
     show IncrementalCompilerResult;
-
 import 'package:front_end/src/api_prototype/standard_file_system.dart'
     show StandardFileSystem;
-
+import 'package:front_end/src/base/command_line_options.dart';
+import 'package:front_end/src/base/nnbd_mode.dart' show NnbdMode;
 import 'package:front_end/src/base/processed_options.dart'
     show ProcessedOptions;
-
 import 'package:front_end/src/compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation, computePlatformDillName;
-
-import 'package:front_end/src/base/command_line_options.dart';
-
-import 'package:front_end/src/base/nnbd_mode.dart' show NnbdMode;
-
 import 'package:front_end/src/fasta/builder/library_builder.dart'
     show LibraryBuilder;
-
 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
 import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
-
 import 'package:front_end/src/fasta/incremental_compiler.dart'
     show IncrementalCompiler;
-
 import 'package:front_end/src/fasta/kernel/hierarchy/hierarchy_builder.dart'
     show ClassHierarchyBuilder;
-
 import 'package:front_end/src/fasta/kernel/hierarchy/hierarchy_node.dart'
     show ClassHierarchyNode;
-
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
-    show KernelTarget;
-
+    show BuildResult, KernelTarget;
 import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
-
-import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
-
-import 'package:front_end/src/fasta/ticker.dart' show Ticker;
-
-import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
-
 import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
-
+import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/ticker.dart' show Ticker;
+import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
 import 'package:front_end/src/fasta/util/parser_ast.dart'
     show ParserAstVisitor, getAST;
-
 import 'package:front_end/src/fasta/util/parser_ast_helper.dart';
-
 import 'package:kernel/ast.dart'
     show
         AwaitExpression,
@@ -111,24 +83,16 @@
         Version,
         Visitor,
         VisitorVoidMixin;
-
 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
-
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
 import 'package:kernel/core_types.dart' show CoreTypes;
-
 import 'package:kernel/kernel.dart'
     show RecursiveResultVisitor, loadComponentFromBytes;
-
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
-
 import 'package:kernel/target/changed_structure_notifier.dart'
     show ChangedStructureNotifier;
-
 import 'package:kernel/target/targets.dart'
     show
-        ConstantsBackend,
         DiagnosticReporter,
         NoneConstantsBackend,
         NoneTarget,
@@ -137,10 +101,8 @@
         TestTargetFlags,
         TestTargetMixin,
         TestTargetWrapper;
-
 import 'package:kernel/type_environment.dart'
     show StaticTypeContext, TypeEnvironment;
-
 import 'package:testing/testing.dart'
     show
         Chain,
@@ -151,11 +113,9 @@
         Step,
         TestDescription,
         StdioProcess;
-
 import 'package:vm/target/vm.dart' show VmTarget;
 
 import '../../testing_utils.dart' show checkEnvironment;
-
 import '../../utils/kernel_chain.dart'
     show
         ComponentResult,
@@ -165,7 +125,6 @@
         Print,
         TypeCheck,
         WriteDill;
-
 import '../../utils/validating_instrumentation.dart'
     show ValidatingInstrumentation;
 
@@ -901,12 +860,12 @@
   Future<Result<ComponentResult>> run(
       ComponentResult result, FastaContext context) {
     KernelTarget target = result.sourceTarget;
-    ConstantsBackend constantsBackend = target.backendTarget.constantsBackend;
     TypeEnvironment environment =
         new TypeEnvironment(target.loader.coreTypes, target.loader.hierarchy);
     StressConstantEvaluatorVisitor stressConstantEvaluatorVisitor =
         new StressConstantEvaluatorVisitor(
-      constantsBackend,
+      target.backendTarget,
+      result.component,
       result.options.environmentDefines,
       target.isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
       environment,
@@ -937,7 +896,8 @@
   List<String> output = [];
 
   StressConstantEvaluatorVisitor(
-      ConstantsBackend backend,
+      Target target,
+      Component component,
       Map<String, String>? environmentDefines,
       bool enableTripleShift,
       TypeEnvironment typeEnvironment,
@@ -945,12 +905,22 @@
       bool errorOnUnevaluatedConstant,
       EvaluationMode evaluationMode) {
     constantEvaluator = new ConstantEvaluator(
-        backend, environmentDefines, typeEnvironment, this,
+        target.dartLibrarySupport,
+        target.constantsBackend,
+        component,
+        environmentDefines,
+        typeEnvironment,
+        this,
         enableTripleShift: enableTripleShift,
         errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
         evaluationMode: evaluationMode);
     constantEvaluatorWithEmptyEnvironment = new ConstantEvaluator(
-        backend, {}, typeEnvironment, this,
+        target.dartLibrarySupport,
+        target.constantsBackend,
+        component,
+        {},
+        typeEnvironment,
+        this,
         enableTripleShift: enableTripleShift,
         errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
         evaluationMode: evaluationMode);
@@ -990,7 +960,7 @@
         }
       }
       if (!evaluate) return node;
-      if (constantEvaluator.environmentDefines != null) {
+      if (constantEvaluator.hasEnvironment) {
         throw "Unexpected UnevaluatedConstant "
             "when the environment is not null.";
       }
@@ -1010,7 +980,7 @@
     bool evaluatedWithEmptyEnvironment = false;
     if (x is UnevaluatedConstant && x.expression is! InvalidExpression) {
       // try with an environment
-      if (constantEvaluator.environmentDefines != null) {
+      if (constantEvaluator.hasEnvironment) {
         throw "Unexpected UnevaluatedConstant (with an InvalidExpression in "
             "it) when the environment is not null.";
       }
@@ -1760,6 +1730,8 @@
     forceConstructorTearOffLoweringForTesting:
         folderOptions.forceConstructorTearOffLowering,
     enableNullSafety: context.soundNullSafety,
+    supportedDartLibraries: {'_supported.by.target'},
+    unsupportedDartLibraries: {'unsupported.by.target'},
   );
   Target target;
   switch (folderOptions.target) {
@@ -1874,13 +1846,17 @@
         if (compilationSetup.testOptions.errors != null) {
           compilationSetup.errors.addAll(compilationSetup.testOptions.errors!);
         }
-        Component p = (await sourceTarget.buildOutlines())!;
+        BuildResult buildResult = await sourceTarget.buildOutlines();
+        Component p = buildResult.component!;
         if (compileMode == CompileMode.full) {
-          p = (await sourceTarget.buildComponent(
+          buildResult = await sourceTarget.buildComponent(
+              macroApplications: buildResult.macroApplications,
               verify: compilationSetup.folderOptions.noVerify
                   ? false
-                  : context.verify))!;
+                  : context.verify);
+          p = buildResult.component!;
         }
+        buildResult.macroApplications?.close();
 
         // To avoid possible crash in mixin transformation in the transformation
         // of the user of this linked dependency we have to transform this too.
@@ -1935,20 +1911,24 @@
           new ValidatingInstrumentation();
       await instrumentation.loadExpectations(description.uri);
       sourceTarget.loader.instrumentation = instrumentation;
-      Component p = (await sourceTarget.buildOutlines())!;
+      BuildResult buildResult = await sourceTarget.buildOutlines();
+      Component p = buildResult.component!;
       Set<Uri> userLibraries = createUserLibrariesImportUriSet(
           p, sourceTarget.uriTranslator,
           excludedLibraries: excludedLibraries);
       if (compileMode != CompileMode.outline) {
-        p = (await sourceTarget.buildComponent(
+        buildResult = await sourceTarget.buildComponent(
+            macroApplications: buildResult.macroApplications,
             verify: compilationSetup.folderOptions.noVerify
                 ? false
-                : context.verify))!;
+                : context.verify);
+        p = buildResult.component!;
         instrumentation.finish();
         if (instrumentation.hasProblems) {
           if (updateComments) {
             await instrumentation.fixSource(description.uri, false);
           } else {
+            buildResult.macroApplications?.close();
             return new Result<ComponentResult>(
                 new ComponentResult(description, p, userLibraries,
                     compilationSetup, sourceTarget),
@@ -1959,6 +1939,7 @@
           }
         }
       }
+      buildResult.macroApplications?.close();
       return pass(new ComponentResult(
           description, p, userLibraries, compilationSetup, sourceTarget));
     });
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 224378f..fc0b9b8 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -426,6 +426,10 @@
         typeParameters: 'T extends Object');
     isObliviousSubtype('T & Future<int?>', 'FutureOr<num>?',
         typeParameters: 'T extends Object');
+    isNotSubtype('FutureOr<T?>?', 'FutureOr<Never?>?',
+        typeParameters: 'T extends FutureOr<T?>?');
+    isSubtype('FutureOr<Never?>?', 'FutureOr<T?>?',
+        typeParameters: 'T extends FutureOr<T?>?');
 
     if (!skipFutureOrPromotion) {
       isSubtype('T & FutureOr<int*>*', 'FutureOr<num*>*', typeParameters: 'T');
diff --git a/pkg/front_end/test/id_testing/id_testing_test.dart b/pkg/front_end/test/id_testing/id_testing_test.dart
index e8f9f5f..676b6df 100644
--- a/pkg/front_end/test/id_testing/id_testing_test.dart
+++ b/pkg/front_end/test/id_testing/id_testing_test.dart
@@ -2,19 +2,20 @@
 // for details. 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 Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, StringDataInterpreter, runTests;
-import 'dart:io' show Directory, Platform;
 import 'package:front_end/src/fasta/messages.dart' show FormattedMessage;
 import 'package:front_end/src/testing/id_testing_helper.dart'
     show
         CfeDataExtractor,
-        InternalCompilerResult,
         DataComputer,
-        TestConfig,
-        defaultCfeConfig,
+        InternalCompilerResult,
+        TestResultData,
         createUriForFileName,
+        defaultCfeConfig,
         onFailure,
         runTestFor;
 import 'package:front_end/src/testing/id_testing_utils.dart';
@@ -40,33 +41,26 @@
   const IdTestingDataComputer();
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    member.accept(new IdTestingDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new IdTestingDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new IdTestingDataExtractor(compilerResult, actualMap).computeForClass(cls);
+    new IdTestingDataExtractor(testResultData.compilerResult, actualMap)
+        .computeForClass(cls);
   }
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new IdTestingDataExtractor(compilerResult, actualMap)
+    new IdTestingDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
@@ -74,8 +68,8 @@
   bool get supportsErrors => true;
 
   @override
-  String computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  String computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     return errorsToText(errors);
   }
 
diff --git a/pkg/front_end/test/id_tests/assigned_variables_test.dart b/pkg/front_end/test/id_tests/assigned_variables_test.dart
index 0f833c1..23a5b09 100644
--- a/pkg/front_end/test/id_tests/assigned_variables_test.dart
+++ b/pkg/front_end/test/id_tests/assigned_variables_test.dart
@@ -9,9 +9,8 @@
     show ActualData, Id, IdKind;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
-
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart' hide Variance;
@@ -39,20 +38,18 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<_Data>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
     AssignedVariablesForTesting<TreeNode, VariableDeclaration>?
         assignedVariables = memberBuilder
             .dataForTesting!.inferenceData.flowAnalysisResult.assignedVariables;
     if (assignedVariables == null) return;
     member.accept(new AssignedVariablesDataExtractor(
-        compilerResult, actualMap, assignedVariables));
+        testResultData.compilerResult, actualMap, assignedVariables));
   }
 }
 
diff --git a/pkg/front_end/test/id_tests/constant_test.dart b/pkg/front_end/test/id_tests/constant_test.dart
index bcee3af..2d48d62 100644
--- a/pkg/front_end/test/id_tests/constant_test.dart
+++ b/pkg/front_end/test/id_tests/constant_test.dart
@@ -9,10 +9,10 @@
 import 'package:front_end/src/testing/id_testing_helper.dart'
     show
         CfeDataExtractor,
-        InternalCompilerResult,
         DataComputer,
         FormattedMessage,
-        TestConfig,
+        InternalCompilerResult,
+        TestResultData,
         createUriForFileName,
         defaultCfeConfig,
         onFailure,
@@ -34,23 +34,19 @@
   const ConstantsDataComputer();
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    member.accept(new ConstantsDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new ConstantsDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new ConstantsDataExtractor(compilerResult, actualMap).computeForClass(cls);
+    new ConstantsDataExtractor(testResultData.compilerResult, actualMap)
+        .computeForClass(cls);
   }
 
   @override
@@ -58,8 +54,8 @@
 
   /// Returns data corresponding to [error].
   @override
-  String computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  String computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     return errorsToText(errors);
   }
 
diff --git a/pkg/front_end/test/id_tests/definite_assignment_test.dart b/pkg/front_end/test/id_tests/definite_assignment_test.dart
index 536f1e1..bc19b2b 100644
--- a/pkg/front_end/test/id_tests/definite_assignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_assignment_test.dart
@@ -3,12 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart' hide Variance;
 
@@ -34,15 +35,15 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
-    member.accept(new DefiniteAssignmentDataExtractor(compilerResult, actualMap,
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
+    member.accept(new DefiniteAssignmentDataExtractor(
+        testResultData.compilerResult,
+        actualMap,
         memberBuilder.dataForTesting!.inferenceData.flowAnalysisResult));
   }
 
diff --git a/pkg/front_end/test/id_tests/definite_unassignment_test.dart b/pkg/front_end/test/id_tests/definite_unassignment_test.dart
index 67ce244..3a26b89 100644
--- a/pkg/front_end/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_unassignment_test.dart
@@ -3,12 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart' hide Variance;
 
@@ -34,16 +35,14 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
     member.accept(new DefiniteUnassignmentDataExtractor(
-        compilerResult,
+        testResultData.compilerResult,
         actualMap,
         memberBuilder.dataForTesting!.inferenceData.flowAnalysisResult));
   }
diff --git a/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart b/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
index b4d3787..7e8b426 100644
--- a/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
+++ b/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
@@ -3,10 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
@@ -38,16 +39,14 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<List<DartType>>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
     member.accept(new InferredTypeArgumentDataExtractor(
-        compilerResult,
+        testResultData.compilerResult,
         memberBuilder.dataForTesting!.inferenceData.typeInferenceResult,
         actualMap));
   }
diff --git a/pkg/front_end/test/id_tests/inferred_variable_types_test.dart b/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
index 7205920..6882661 100644
--- a/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
+++ b/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
@@ -3,10 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
@@ -38,16 +39,14 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<DartType>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
     member.accept(new InferredTypeArgumentDataExtractor(
-        compilerResult,
+        testResultData.compilerResult,
         memberBuilder.dataForTesting!.inferenceData.typeInferenceResult,
         actualMap));
   }
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index 78f9bf5..b618894 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -49,24 +49,18 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new InheritanceDataExtractor(config, compilerResult, actualMap)
+    new InheritanceDataExtractor(testResultData, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new InheritanceDataExtractor(config, compilerResult, actualMap)
+    new InheritanceDataExtractor(testResultData, actualMap)
         .computeForClass(cls);
   }
 
@@ -74,8 +68,8 @@
   bool get supportsErrors => true;
 
   @override
-  String computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  String computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     return errorsToText(errors, useCodes: true);
   }
 
@@ -84,12 +78,15 @@
 }
 
 class InheritanceDataExtractor extends CfeDataExtractor<String> {
-  final TestConfig _config;
-  final InternalCompilerResult _compilerResult;
+  final TestResultData _testResultData;
 
   InheritanceDataExtractor(
-      this._config, this._compilerResult, Map<Id, ActualData<String>> actualMap)
-      : super(_compilerResult, actualMap);
+      this._testResultData, Map<Id, ActualData<String>> actualMap)
+      : super(_testResultData.compilerResult, actualMap);
+
+  TestConfig get _config => _testResultData.config;
+
+  InternalCompilerResult get _compilerResult => _testResultData.compilerResult;
 
   ClassHierarchy get _hierarchy => _compilerResult.classHierarchy!;
 
diff --git a/pkg/front_end/test/id_tests/nullability_test.dart b/pkg/front_end/test/id_tests/nullability_test.dart
index 0ffa7f2..e563f8d 100644
--- a/pkg/front_end/test/id_tests/nullability_test.dart
+++ b/pkg/front_end/test/id_tests/nullability_test.dart
@@ -29,13 +29,11 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    member.accept(new NullabilityDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new NullabilityDataExtractor(testResultData.compilerResult, actualMap));
   }
 }
 
diff --git a/pkg/front_end/test/id_tests/reachability_test.dart b/pkg/front_end/test/id_tests/reachability_test.dart
index 1362a08..6a043b4 100644
--- a/pkg/front_end/test/id_tests/reachability_test.dart
+++ b/pkg/front_end/test/id_tests/reachability_test.dart
@@ -3,13 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart' hide Variance;
 
@@ -36,15 +37,15 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<Set<_ReachabilityAssertion>>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
-    member.accept(new ReachabilityDataExtractor(compilerResult, actualMap,
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
+    member.accept(new ReachabilityDataExtractor(
+        testResultData.compilerResult,
+        actualMap,
         memberBuilder.dataForTesting!.inferenceData.flowAnalysisResult));
   }
 
diff --git a/pkg/front_end/test/id_tests/type_promotion_test.dart b/pkg/front_end/test/id_tests/type_promotion_test.dart
index 6aae1e8..59cc18e6 100644
--- a/pkg/front_end/test/id_tests/type_promotion_test.dart
+++ b/pkg/front_end/test/id_tests/type_promotion_test.dart
@@ -33,13 +33,11 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<DartType>> actualMap,
       {bool? verbose}) {
-    member.accept(new TypePromotionDataExtractor(compilerResult, actualMap));
+    member.accept(new TypePromotionDataExtractor(
+        testResultData.compilerResult, actualMap));
   }
 }
 
diff --git a/pkg/front_end/test/id_tests/why_not_promoted_test.dart b/pkg/front_end/test/id_tests/why_not_promoted_test.dart
index ca26b01..0d52a11 100644
--- a/pkg/front_end/test/id_tests/why_not_promoted_test.dart
+++ b/pkg/front_end/test/id_tests/why_not_promoted_test.dart
@@ -7,7 +7,7 @@
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
@@ -41,15 +41,15 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    MemberBuilderImpl memberBuilder =
-        lookupMemberBuilder(compilerResult, member) as MemberBuilderImpl;
-    member.accept(new WhyNotPromotedDataExtractor(compilerResult, actualMap,
+    SourceMemberBuilder memberBuilder =
+        lookupMemberBuilder(testResultData.compilerResult, member)
+            as SourceMemberBuilder;
+    member.accept(new WhyNotPromotedDataExtractor(
+        testResultData.compilerResult,
+        actualMap,
         memberBuilder.dataForTesting!.inferenceData.flowAnalysisResult));
   }
 }
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
new file mode 100644
index 0000000..581d63f
--- /dev/null
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -0,0 +1,305 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// 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:async';
+import 'dart:io';
+
+import "simple_stats.dart";
+import "vm_service_helper.dart" as vmService;
+
+const int limit = 10;
+
+Future<void> main(List<String> args) async {
+  LeakFinder heapHelper = new LeakFinder();
+
+  await heapHelper.start([
+    "--disable-dart-dev",
+    "--enable-asserts",
+    Platform.script.resolve("incremental_dart2js_tester.dart").toString(),
+    "--addDebugBreaks",
+    "--fast",
+    "--limit=$limit",
+  ]);
+}
+
+class LeakFinder extends vmService.LaunchingVMServiceHelper {
+  @override
+  Future<void> run() async {
+    vmService.VM vm = await serviceClient.getVM();
+    if (vm.isolates!.length != 1) {
+      throw "Expected 1 isolate, got ${vm.isolates!.length}";
+    }
+    vmService.IsolateRef isolateRef = vm.isolates!.single;
+    await waitUntilIsolateIsRunnable(isolateRef.id!);
+    await serviceClient.resume(isolateRef.id!);
+
+    Map<vmService.ClassRef, List<int>> instanceCounts =
+        new Map<vmService.ClassRef, List<int>>();
+    Map<vmService.ClassRef, vmService.Class> classInfo =
+        new Map<vmService.ClassRef, vmService.Class>();
+
+    Completer<String> cTimeout = new Completer();
+    Timer timer = new Timer(new Duration(minutes: 6), () {
+      cTimeout.complete("Timeout");
+      killProcess();
+    });
+
+    Completer<String> cRunDone = new Completer();
+    // ignore: unawaited_futures
+    runInternal(
+        isolateRef,
+        classInfo,
+        instanceCounts,
+        (int iteration) =>
+            // Subtract 2 as it's logically one ahead and asks _before_ the run.
+            (iteration - 2) > limit ||
+            cTimeout.isCompleted ||
+            cProcessExited.isCompleted).then((value) {
+      cRunDone.complete("Done");
+    });
+
+    await Future.any([cRunDone.future, cTimeout.future, cProcessExited.future]);
+    timer.cancel();
+
+    print("\n\n======================\n\n");
+
+    findPossibleLeaks(instanceCounts, classInfo);
+
+    // Make sure the process doesn't hang.
+    killProcess();
+  }
+
+  void findPossibleLeaks(Map<vmService.ClassRef, List<int>> instanceCounts,
+      Map<vmService.ClassRef, vmService.Class> classInfo) {
+    bool foundLeak = false;
+    for (vmService.ClassRef c in instanceCounts.keys) {
+      List<int> listOfInstanceCounts = instanceCounts[c]!;
+
+      // Ignore VM internal stuff like "PatchClass", "PcDescriptors" etc.
+      // (they don't have a url).
+      vmService.Class classDetails = classInfo[c]!;
+      String? uriString = classDetails.location?.script?.uri;
+      if (uriString == null) continue;
+
+      // For now ignore anything not in package:kernel or package:front_end.
+      if (ignoredClass(classDetails)) continue;
+
+      bool isStrictClass = strictClass(classDetails);
+
+      int expectedStrictClassNumber = -1;
+      if (isStrictClass) {
+        expectedStrictClassNumber = strictClassExpectedNumber(classDetails);
+      }
+
+      // If they're all equal there's nothing to talk about.
+      bool sameAndAsExpected = true;
+      for (int i = 0; i < listOfInstanceCounts.length; i++) {
+        if (expectedStrictClassNumber > -1 &&
+            expectedStrictClassNumber != listOfInstanceCounts[i]) {
+          sameAndAsExpected = false;
+          break;
+        }
+        if (listOfInstanceCounts[i] != listOfInstanceCounts[0]) {
+          sameAndAsExpected = false;
+          break;
+        }
+      }
+      if (sameAndAsExpected) continue;
+
+      int midPoint = listOfInstanceCounts.length ~/ 2;
+      List<int> firstHalf = listOfInstanceCounts.sublist(0, midPoint);
+      List<int> secondHalf = listOfInstanceCounts.sublist(midPoint);
+      TTestResult ttestResult = SimpleTTestStat.ttest(secondHalf, firstHalf);
+
+      if (!isStrictClass) {
+        if (!ttestResult.significant) continue;
+
+        // TODO(jensj): We could possibly also ignore if it's less (i.e. a
+        // negative change), or if the change is < 1%, or the change minus the
+        // confidence is < 1% etc.
+      }
+      if (expectedStrictClassNumber > -1) {
+        print("Differences on ${c.name} (${uriString}): "
+            "Expected exactly $expectedStrictClassNumber but found "
+            "$listOfInstanceCounts ($ttestResult)");
+      } else {
+        print("Differences on ${c.name} (${uriString}): "
+            "$listOfInstanceCounts ($ttestResult)");
+      }
+      foundLeak = true;
+    }
+
+    print("\n\n");
+
+    if (foundLeak) {
+      print("Possible leak(s) found.");
+      print("(Note that this doesn't guarantee that there are any!)");
+      exitCode = 1;
+    } else {
+      print("Didn't identify any leaks.");
+      print("(Note that this doesn't guarantee that there are none!)");
+      exitCode = 0;
+    }
+  }
+
+  Future<void> runInternal(
+      vmService.IsolateRef isolateRef,
+      Map<vmService.ClassRef, vmService.Class> classInfo,
+      Map<vmService.ClassRef, List<int>> instanceCounts,
+      bool Function(int iteration) shouldBail) async {
+    int iterationNumber = 1;
+    try {
+      while (true) {
+        if (shouldBail(iterationNumber)) break;
+        if (!await waitUntilPaused(isolateRef.id!)) break;
+        print("\n\n====================\n\nIteration #$iterationNumber");
+        iterationNumber++;
+        vmService.AllocationProfile allocationProfile =
+            await forceGC(isolateRef.id!);
+        for (vmService.ClassHeapStats member in allocationProfile.members!) {
+          if (!classInfo.containsKey(member.classRef)) {
+            vmService.Class c = (await serviceClient.getObject(
+                isolateRef.id!, member.classRef!.id!)) as vmService.Class;
+            classInfo[member.classRef!] = c;
+          }
+          List<int>? listOfInstanceCounts = instanceCounts[member.classRef];
+          if (listOfInstanceCounts == null) {
+            listOfInstanceCounts = instanceCounts[member.classRef!] = <int>[];
+          }
+          while (listOfInstanceCounts.length < iterationNumber - 2) {
+            listOfInstanceCounts.add(0);
+          }
+          listOfInstanceCounts.add(member.instancesCurrent!);
+          if (listOfInstanceCounts.length != iterationNumber - 1) {
+            throw "Unexpected length";
+          }
+        }
+        await serviceClient.resume(isolateRef.id!);
+      }
+    } catch (e) {
+      print("Got error: $e");
+    }
+  }
+
+  Completer<String> cProcessExited = new Completer();
+  @override
+  void processExited(int exitCode) {
+    cProcessExited.complete("Exit");
+  }
+
+  bool ignoredClass(vmService.Class classDetails) {
+    String? uriString = classDetails.location?.script?.uri;
+    if (uriString == null) return true;
+    if (uriString.startsWith("package:front_end/")) {
+      // Classes used for lazy initialization will naturally fluctuate.
+      if (classDetails.name == "DillClassBuilder") return true;
+      if (classDetails.name == "DillExtensionBuilder") return true;
+      if (classDetails.name == "DillExtensionMemberBuilder") return true;
+      if (classDetails.name == "DillMemberBuilder") return true;
+      if (classDetails.name == "DillTypeAliasBuilder") return true;
+
+      // These classes have proved to fluctuate, although the reason is less
+      // clear.
+      if (classDetails.name == "InheritedImplementationInterfaceConflict") {
+        return true;
+      }
+      if (classDetails.name == "AbstractMemberOverridingImplementation") {
+        return true;
+      }
+      if (classDetails.name == "VoidTypeBuilder") return true;
+      if (classDetails.name == "NamedTypeBuilder") return true;
+      if (classDetails.name == "DillClassMember") return true;
+      if (classDetails.name == "Scope") return true;
+      if (classDetails.name == "ConstructorScope") return true;
+      if (classDetails.name == "ScopeBuilder") return true;
+      if (classDetails.name == "ConstructorScopeBuilder") return true;
+      if (classDetails.name == "NullTypeDeclarationBuilder") return true;
+      if (classDetails.name == "NullabilityBuilder") return true;
+
+      return false;
+    } else if (uriString.startsWith("package:kernel/")) {
+      // DirtifyingList is used for lazy stuff and naturally change in numbers.
+      if (classDetails.name == "DirtifyingList") return true;
+
+      // Constants are canonicalized in their compilation run and will thus
+      // naturally increase, e.g. we can get 2 more booleans every time (up to
+      // a maximum of 2 per library or however many would have been there if we
+      // didn't canonicalize at all).
+      if (classDetails.name!.endsWith("Constant")) return true;
+
+      // These classes have proved to fluctuate, although the reason is less
+      // clear.
+      if (classDetails.name == "InterfaceType") return true;
+
+      return false;
+    }
+    return true;
+  }
+
+  Map<String, int> frontEndStrictClasses = {
+    // The inner working of dills are created lazily:
+    // "DillClassBuilder",
+    // "DillExtensionBuilder",
+    // "DillExtensionMemberBuilder",
+    // "DillMemberBuilder",
+    // "DillTypeAliasBuilder",
+
+    "DillLibraryBuilder": -1 /* unknown amount */,
+    "DillLoader": 1,
+    "DillTarget": 1,
+
+    // We convert all source builders to dill builders so we expect none to
+    // exist after that.
+    "SourceClassBuilder": 0,
+    "SourceExtensionBuilder": 0,
+    "SourceLibraryBuilder": 0,
+
+    // We still expect exactly 1 source loader though.
+    "SourceLoader": 1,
+  };
+
+  Set<String> kernelAstStrictClasses = {
+    "Class",
+    "Constructor",
+    "Extension",
+    "Field",
+    "Library",
+    "Procedure",
+    "RedirectingFactory",
+    "Typedef",
+  };
+
+  bool strictClass(vmService.Class classDetails) {
+    if (!kernelAstStrictClasses.contains(classDetails.name) &&
+        !frontEndStrictClasses.containsKey(classDetails.name)) return false;
+
+    if (kernelAstStrictClasses.contains(classDetails.name) &&
+        classDetails.location?.script?.uri == "package:kernel/ast.dart") {
+      return true;
+    }
+    if (frontEndStrictClasses.containsKey(classDetails.name) &&
+        classDetails.location?.script?.uri?.startsWith("package:front_end/") ==
+            true) {
+      return true;
+    }
+
+    throw "$classDetails: ${classDetails.name} --- ${classDetails.location}";
+  }
+
+  int strictClassExpectedNumber(vmService.Class classDetails) {
+    if (!strictClass(classDetails)) return -1;
+    if (kernelAstStrictClasses.contains(classDetails.name) &&
+        classDetails.location?.script?.uri == "package:kernel/ast.dart") {
+      return -1;
+    }
+    int? result = frontEndStrictClasses[classDetails.name];
+    if (result != null &&
+        classDetails.location?.script?.uri?.startsWith("package:front_end/") ==
+            true) {
+      return result;
+    }
+
+    throw "$classDetails: ${classDetails.name} --- ${classDetails.location}";
+  }
+}
diff --git a/pkg/front_end/test/incremental_compiler_leak_tester.dart b/pkg/front_end/test/incremental_compiler_leak_tester.dart
deleted file mode 100644
index d05460b..0000000
--- a/pkg/front_end/test/incremental_compiler_leak_tester.dart
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// 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:async';
-import 'dart:io';
-
-import "simple_stats.dart";
-import "vm_service_helper.dart" as vmService;
-
-const int limit = 10;
-
-Future<void> main(List<String> args) async {
-  LeakFinder heapHelper = new LeakFinder();
-
-  await heapHelper.start([
-    "--disable-dart-dev",
-    "--enable-asserts",
-    Platform.script.resolve("incremental_dart2js_tester.dart").toString(),
-    "--addDebugBreaks",
-    "--fast",
-    "--limit=$limit",
-  ]);
-}
-
-class LeakFinder extends vmService.LaunchingVMServiceHelper {
-  @override
-  Future<void> run() async {
-    vmService.VM vm = await serviceClient.getVM();
-    if (vm.isolates!.length != 1) {
-      throw "Expected 1 isolate, got ${vm.isolates!.length}";
-    }
-    vmService.IsolateRef isolateRef = vm.isolates!.single;
-    await waitUntilIsolateIsRunnable(isolateRef.id!);
-    await serviceClient.resume(isolateRef.id!);
-
-    Map<vmService.ClassRef, List<int>> instanceCounts =
-        new Map<vmService.ClassRef, List<int>>();
-    Map<vmService.ClassRef, vmService.Class> classInfo =
-        new Map<vmService.ClassRef, vmService.Class>();
-
-    Completer<String> cTimeout = new Completer();
-    Timer timer = new Timer(new Duration(minutes: 6), () {
-      cTimeout.complete("Timeout");
-      killProcess();
-    });
-
-    Completer<String> cRunDone = new Completer();
-    // ignore: unawaited_futures
-    runInternal(
-        isolateRef,
-        classInfo,
-        instanceCounts,
-        (int iteration) =>
-            // Subtract 2 as it's logically one ahead and asks _before_ the run.
-            (iteration - 2) > limit ||
-            cTimeout.isCompleted ||
-            cProcessExited.isCompleted).then((value) {
-      cRunDone.complete("Done");
-    });
-
-    await Future.any([cRunDone.future, cTimeout.future, cProcessExited.future]);
-    timer.cancel();
-
-    print("\n\n======================\n\n");
-
-    findPossibleLeaks(instanceCounts, classInfo);
-
-    // Make sure the process doesn't hang.
-    killProcess();
-  }
-
-  void findPossibleLeaks(Map<vmService.ClassRef, List<int>> instanceCounts,
-      Map<vmService.ClassRef, vmService.Class> classInfo) {
-    bool foundLeak = false;
-    for (vmService.ClassRef c in instanceCounts.keys) {
-      List<int> listOfInstanceCounts = instanceCounts[c]!;
-
-      // Ignore VM internal stuff like "PatchClass", "PcDescriptors" etc.
-      // (they don't have a url).
-      vmService.Class classDetails = classInfo[c]!;
-      String? uriString = classDetails.location?.script?.uri;
-      if (uriString == null) continue;
-
-      // For now ignore anything not in package:kernel or package:front_end.
-      if (ignoredClass(classDetails)) continue;
-
-      // If they're all equal there's nothing to talk about.
-      bool same = true;
-      for (int i = 1; i < listOfInstanceCounts.length; i++) {
-        if (listOfInstanceCounts[i] != listOfInstanceCounts[0]) {
-          same = false;
-          break;
-        }
-      }
-      if (same) continue;
-
-      int midPoint = listOfInstanceCounts.length ~/ 2;
-      List<int> firstHalf = listOfInstanceCounts.sublist(0, midPoint);
-      List<int> secondHalf = listOfInstanceCounts.sublist(midPoint);
-      TTestResult ttestResult = SimpleTTestStat.ttest(secondHalf, firstHalf);
-
-      if (!strictClass(classDetails)) {
-        if (!ttestResult.significant) continue;
-
-        // TODO(jensj): We could possibly also ignore if it's less (i.e. a
-        // negative change), or if the change is < 1%, or the change minus the
-        // confidence is < 1% etc.
-      }
-      print("Differences on ${c.name} (${uriString}): "
-          "$listOfInstanceCounts ($ttestResult)");
-      foundLeak = true;
-    }
-
-    print("\n\n");
-
-    if (foundLeak) {
-      print("Possible leak(s) found.");
-      print("(Note that this doesn't guarantee that there are any!)");
-      exitCode = 1;
-    } else {
-      print("Didn't identify any leaks.");
-      print("(Note that this doesn't guarantee that there are none!)");
-      exitCode = 0;
-    }
-  }
-
-  Future<void> runInternal(
-      vmService.IsolateRef isolateRef,
-      Map<vmService.ClassRef, vmService.Class> classInfo,
-      Map<vmService.ClassRef, List<int>> instanceCounts,
-      bool Function(int iteration) shouldBail) async {
-    int iterationNumber = 1;
-    try {
-      while (true) {
-        if (shouldBail(iterationNumber)) break;
-        if (!await waitUntilPaused(isolateRef.id!)) break;
-        print("\n\n====================\n\nIteration #$iterationNumber");
-        iterationNumber++;
-        vmService.AllocationProfile allocationProfile =
-            await forceGC(isolateRef.id!);
-        for (vmService.ClassHeapStats member in allocationProfile.members!) {
-          if (!classInfo.containsKey(member.classRef)) {
-            vmService.Class c = (await serviceClient.getObject(
-                isolateRef.id!, member.classRef!.id!)) as vmService.Class;
-            classInfo[member.classRef!] = c;
-          }
-          List<int>? listOfInstanceCounts = instanceCounts[member.classRef];
-          if (listOfInstanceCounts == null) {
-            listOfInstanceCounts = instanceCounts[member.classRef!] = <int>[];
-          }
-          while (listOfInstanceCounts.length < iterationNumber - 2) {
-            listOfInstanceCounts.add(0);
-          }
-          listOfInstanceCounts.add(member.instancesCurrent!);
-          if (listOfInstanceCounts.length != iterationNumber - 1) {
-            throw "Unexpected length";
-          }
-        }
-        await serviceClient.resume(isolateRef.id!);
-      }
-    } catch (e) {
-      print("Got error: $e");
-    }
-  }
-
-  Completer<String> cProcessExited = new Completer();
-  @override
-  void processExited(int exitCode) {
-    cProcessExited.complete("Exit");
-  }
-
-  bool ignoredClass(vmService.Class classDetails) {
-    String? uriString = classDetails.location?.script?.uri;
-    if (uriString == null) return true;
-    if (uriString.startsWith("package:front_end/")) {
-      // Classes used for lazy initialization will naturally fluctuate.
-      if (classDetails.name == "DillClassBuilder") return true;
-      if (classDetails.name == "DillExtensionBuilder") return true;
-      if (classDetails.name == "DillExtensionMemberBuilder") return true;
-      if (classDetails.name == "DillMemberBuilder") return true;
-      if (classDetails.name == "DillTypeAliasBuilder") return true;
-
-      // These classes have proved to fluctuate, although the reason is less
-      // clear.
-      if (classDetails.name == "InheritedImplementationInterfaceConflict") {
-        return true;
-      }
-      if (classDetails.name == "AbstractMemberOverridingImplementation") {
-        return true;
-      }
-      if (classDetails.name == "VoidTypeBuilder") return true;
-      if (classDetails.name == "NamedTypeBuilder") return true;
-      if (classDetails.name == "DillClassMember") return true;
-      if (classDetails.name == "Scope") return true;
-      if (classDetails.name == "ConstructorScope") return true;
-      if (classDetails.name == "ScopeBuilder") return true;
-      if (classDetails.name == "ConstructorScopeBuilder") return true;
-      if (classDetails.name == "NullTypeDeclarationBuilder") return true;
-      if (classDetails.name == "NullabilityBuilder") return true;
-
-      return false;
-    } else if (uriString.startsWith("package:kernel/")) {
-      // DirtifyingList is used for lazy stuff and naturally change in numbers.
-      if (classDetails.name == "DirtifyingList") return true;
-
-      // Constants are canonicalized in their compilation run and will thus
-      // naturally increase, e.g. we can get 2 more booleans every time (up to
-      // a maximum of 2 per library or however many would have been there if we
-      // didn't canonicalize at all).
-      if (classDetails.name!.endsWith("Constant")) return true;
-
-      // These classes have proved to fluctuate, although the reason is less
-      // clear.
-      if (classDetails.name == "InterfaceType") return true;
-
-      return false;
-    }
-    return true;
-  }
-
-  // I have commented out the lazy ones below.
-  Set<String> frontEndStrictClasses = {
-    // "DillClassBuilder",
-    // "DillExtensionBuilder",
-    // "DillExtensionMemberBuilder",
-    "DillLibraryBuilder",
-    "DillLoader",
-    // "DillMemberBuilder",
-    "DillTarget",
-    // "DillTypeAliasBuilder",
-    "SourceClassBuilder",
-    "SourceExtensionBuilder",
-    "SourceLibraryBuilder",
-    "SourceLoader",
-  };
-
-  Set<String> kernelAstStrictClasses = {
-    "Class",
-    "Constructor",
-    "Extension",
-    "Field",
-    "Library",
-    "Procedure",
-    "RedirectingFactory",
-    "Typedef",
-  };
-
-  bool strictClass(vmService.Class classDetails) {
-    if (!kernelAstStrictClasses.contains(classDetails.name) &&
-        !frontEndStrictClasses.contains(classDetails.name)) return false;
-
-    if (kernelAstStrictClasses.contains(classDetails.name) &&
-        classDetails.location?.script?.uri == "package:kernel/ast.dart") {
-      return true;
-    }
-    if (frontEndStrictClasses.contains(classDetails.name) &&
-        classDetails.location?.script?.uri?.startsWith("package:front_end/") ==
-            true) {
-      return true;
-    }
-
-    throw "$classDetails: ${classDetails.name} --- ${classDetails.location}";
-  }
-}
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index 7c07a6a..20ed53a 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -349,7 +349,6 @@
     options.sdkSummary = sdkSummaryUri;
     options.omitPlatform = true;
     options.onDiagnostic = (DiagnosticMessage message) {
-      if (getMessageCodeObject(message)?.name == "InferredPackageUri") return;
       throw message.ansiFormatted;
     };
     if (packagesUri != null) {
@@ -357,10 +356,11 @@
     }
     TestIncrementalCompiler compiler = new TestIncrementalCompiler(
         options, moduleSources.first, /* initializeFrom = */ null, outlineOnly);
-    IncrementalCompilerResult compilerResult = await compiler.computeDelta(
+    IncrementalCompilerResult? compilerResult = await compiler.computeDelta(
         entryPoints: moduleSources,
         trackNeededDillLibraries: trackNeededDillLibraries);
     Component c = compilerResult.component;
+    compilerResult = null;
     c.computeCanonicalNames();
     List<Library> wantedLibs = <Library>[];
     for (Library lib in c.libraries) {
@@ -669,13 +669,15 @@
       }
 
       Stopwatch stopwatch = new Stopwatch()..start();
-      IncrementalCompilerResult compilerResult = await compiler!.computeDelta(
+      IncrementalCompilerResult? compilerResult = await compiler!.computeDelta(
           entryPoints: entries,
           fullComponent:
               brandNewWorld ? false : (noFullComponent ? false : true),
           trackNeededDillLibraries: modulesToUse != null,
           simulateTransformer: world["simulateTransformer"]);
       component = compilerResult.component;
+      // compilerResult is null'ed out at the end to avoid any
+      // "artificial memory leak" on that account.
       if (outlineOnly && !skipOutlineBodyCheck) {
         for (Library lib in component!.libraries) {
           for (Class c in lib.classes) {
@@ -942,11 +944,13 @@
 
       if (!noFullComponent) {
         clearPrevErrorsEtc();
-        IncrementalCompilerResult compilerResult2 = await compiler.computeDelta(
-            entryPoints: entries,
-            fullComponent: true,
-            simulateTransformer: world["simulateTransformer"]);
+        IncrementalCompilerResult? compilerResult2 =
+            await compiler.computeDelta(
+                entryPoints: entries,
+                fullComponent: true,
+                simulateTransformer: world["simulateTransformer"]);
         component2 = compilerResult2.component;
+        compilerResult2 = null;
         Result<TestData>? result = performErrorAndWarningCheck(world, data,
             gotError, formattedErrors, gotWarning, formattedWarnings);
         if (result != null) return result;
@@ -1055,12 +1059,13 @@
         }
 
         Stopwatch stopwatch = new Stopwatch()..start();
-        IncrementalCompilerResult compilerResult3 =
+        IncrementalCompilerResult? compilerResult3 =
             await compilerFromScratch.computeDelta(
                 entryPoints: entries,
                 trackNeededDillLibraries: modulesToUse != null,
                 simulateTransformer: world["simulateTransformer"]);
         component3 = compilerResult3.component;
+        compilerResult3 = null;
         compilerFromScratch = null;
         Result<TestData>? result = performErrorAndWarningCheck(world, data,
             gotError, formattedErrors, gotWarning, formattedWarnings);
@@ -1112,6 +1117,7 @@
       }
 
       component = null;
+      compilerResult = null;
       component2 = null;
       component3 = null;
       // Dummy tree nodes can (currently) leak though the parent pointer.
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index 221ce79..5e88669 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -17,6 +17,7 @@
         DataComputer,
         InternalCompilerResult,
         TestConfig,
+        TestResultData,
         createUriForFileName,
         onFailure,
         runTestFor;
@@ -42,16 +43,13 @@
       ]);
 }
 
-// Ugly hack.
-late CompilerOptions stashedOptions;
-
 class TestConfigWithLanguageVersion extends TestConfig {
   TestConfigWithLanguageVersion(String marker, String name)
       : super(marker, name);
 
   @override
-  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
-    stashedOptions = options;
+  CompilerOptions customizeCompilerOptions(
+      CompilerOptions options, TestData testData) {
     options.currentSdkVersion = "2.8";
 
     File f = new File.fromUri(testData.testFileUri.resolve("test.options"));
@@ -69,6 +67,7 @@
         }
       }
     }
+    return options;
   }
 }
 
@@ -82,15 +81,15 @@
   const LanguageVersioningDataComputer();
 
   @override
-  Future<void> inspectComponent(Component component) async {
+  Future<void> inspectTestResultData(TestResultData testResultData) async {
+    CompilerOptions options = testResultData.customData;
+    Component component = testResultData.compilerResult.component!;
     for (Library library in component.libraries) {
       if (library.importUri.scheme == "dart") continue;
       Version lvFile =
-          (await lv.languageVersionForUri(library.fileUri, stashedOptions))
-              .version;
+          (await lv.languageVersionForUri(library.fileUri, options)).version;
       Version lvImportUri =
-          (await lv.languageVersionForUri(library.importUri, stashedOptions))
-              .version;
+          (await lv.languageVersionForUri(library.importUri, options)).version;
       if ((lvFile != lvImportUri || lvFile != library.languageVersion)) {
         throw """
 Language version disagreement:
@@ -103,13 +102,11 @@
   }
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new LanguageVersioningDataExtractor(compilerResult, actualMap)
+    new LanguageVersioningDataExtractor(
+            testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
@@ -117,8 +114,8 @@
   bool get supportsErrors => true;
 
   @override
-  Features computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  Features computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     Features features = new Features();
     features[Tags.errors] = errors.map((m) => m.code.name).join(',');
     return features;
diff --git a/pkg/front_end/test/lint_suite.dart b/pkg/front_end/test/lint_suite.dart
index cd16042..d61759d 100644
--- a/pkg/front_end/test/lint_suite.dart
+++ b/pkg/front_end/test/lint_suite.dart
@@ -296,7 +296,14 @@
 }
 
 class ImportsTwiceLintListener extends LintListener {
-  Set<Uri> seenImports = new Set<Uri>();
+  Map<Uri, Set<String?>> seenImports = {};
+
+  Token? seenAsKeyword;
+
+  @override
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
+    seenAsKeyword = asKeyword;
+  }
 
   @override
   void endImport(Token importKeyword, Token? semicolon) {
@@ -313,9 +320,16 @@
         resolved = description.cache.packages!.resolve(resolved)!;
       }
     }
-    if (!seenImports.add(resolved)) {
-      onProblem(importUriToken.offset, importUriToken.lexeme.length,
-          "Uri '$resolved' already imported once.");
+    String? asName = seenAsKeyword?.lexeme;
+    Set<String?> asNames = seenImports[resolved] ??= {};
+    if (!asNames.add(asName)) {
+      if (asName != null) {
+        onProblem(importUriToken.offset, importUriToken.lexeme.length,
+            "Uri '$resolved' already imported once as '${asName}'.");
+      } else {
+        onProblem(importUriToken.offset, importUriToken.lexeme.length,
+            "Uri '$resolved' already imported once.");
+      }
     }
   }
 }
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index 9f581ba..c74d14d 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -3,12 +3,7 @@
 # BSD-style license that can be found in the LICENSE.md file.
 
 _fe_analyzer_shared/lib/src/parser/parser/Exports: Fail
-_fe_analyzer_shared/lib/src/scanner/abstract_scanner/ImportsTwice: Fail
 _fe_analyzer_shared/lib/src/scanner/scanner/Exports: Fail
-_fe_analyzer_shared/lib/src/scanner/string_scanner/ImportsTwice: Fail
-_fe_analyzer_shared/lib/src/scanner/token_impl/ImportsTwice: Fail
-_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner/ImportsTwice: Fail
-front_end/lib/src/api_prototype/compiler_options/ImportsTwice: Fail
 front_end/lib/src/api_prototype/compiler_options/Exports: Fail
 front_end/lib/src/api_prototype/constant_evaluator/Exports: Fail
 front_end/lib/src/api_prototype/front_end/Exports: Fail
@@ -17,11 +12,7 @@
 front_end/lib/src/api_prototype/lowering_predicates/Exports: Fail
 front_end/lib/src/api_prototype/terminal_color_support/Exports: Fail
 front_end/lib/src/fasta/fasta_codes/Exports: Fail
-front_end/lib/src/fasta/incremental_compiler/ImportsTwice: Fail
-front_end/lib/src/fasta/kernel/body_builder/ImportsTwice: Fail
 front_end/lib/src/fasta/messages/Exports: Fail
-front_end/lib/src/fasta/source/value_kinds/ImportsTwice: Fail
 front_end/lib/src/testing/id_testing_helper/Exports: Fail
 kernel/lib/ast/Exports: Fail
 kernel/lib/kernel/Exports: Fail
-kernel/lib/testing/type_parser_environment/ImportsTwice: Fail
diff --git a/pkg/front_end/test/macro_application/data/package_config.json b/pkg/front_end/test/macro_application/data/package_config.json
new file mode 100644
index 0000000..fbfd870
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/package_config.json
@@ -0,0 +1,18 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "macro",
+      "rootUri": "pkgs/macro/lib/"
+    },
+    {
+      "name": "meta",
+      "rootUri": "../../../../meta/",
+      "packageUri": "lib/"
+    },
+    {
+      "name": "_fe_analyzer_shared",
+      "rootUri": "../../../../_fe_analyzer_shared/lib/"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
new file mode 100644
index 0000000..4979c76
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class FunctionDefinitionMacro1 implements FunctionDefinitionMacro {
+  const FunctionDefinitionMacro1();
+
+  FutureOr<void> buildDefinitionForFunction(
+      FunctionDeclaration function, FunctionDefinitionBuilder builder) {
+      builder.augment(new FunctionBodyCode.fromString('''{
+  return 42;
+}'''));
+  }
+}
+
+macro class FunctionDefinitionMacro2 implements FunctionDefinitionMacro {
+  const FunctionDefinitionMacro2();
+
+  FutureOr<void> buildDefinitionForFunction(
+      FunctionDeclaration function, FunctionDefinitionBuilder builder) async {
+    if (function.positionalParameters.isEmpty) {
+      return;
+    }
+    StaticType returnType = await builder.instantiateType(function.returnType);
+    StaticType parameterType =
+        await builder.instantiateType(function.positionalParameters.first.type);
+    builder.augment(new FunctionBodyCode.fromString('''{
+  print('isExactly=${await returnType.isExactly(parameterType)}');
+  print('isSubtype=${await returnType.isSubtypeOf(parameterType)}');
+}'''));
+  }
+}
+
+
+macro class FunctionTypesMacro1 implements FunctionTypesMacro {
+  const FunctionTypesMacro1();
+
+  FutureOr<void> buildTypesForFunction(
+      FunctionDeclaration function, TypeBuilder builder) {
+    builder.declareType(new DeclarationCode.fromString('''
+class ${function.identifier.name}GeneratedClass {}
+'''));
+  }
+}
+
+macro class FunctionDeclarationsMacro1 implements FunctionDeclarationsMacro {
+  const FunctionDeclarationsMacro1();
+
+  FutureOr<void> buildDeclarationsForFunction(
+      FunctionDeclaration function, DeclarationBuilder builder) {
+    builder.declareInLibrary(new DeclarationCode.fromString('''
+void ${function.identifier.name}GeneratedMethod() {}
+'''));
+  }
+}
diff --git a/pkg/front_end/test/macro_application/data/tests/declarations.dart b/pkg/front_end/test/macro_application/data/tests/declarations.dart
new file mode 100644
index 0000000..a992685
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/declarations.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:macro/macro.dart';
+
+/*member: topLevelFunction1:
+void topLevelFunction1GeneratedMethod() {}
+*/
+@FunctionDeclarationsMacro1()
+void topLevelFunction1() {}
+
+@FunctionDeclarationsMacro1()
+/*member: topLevelFunction2:
+void topLevelFunction2GeneratedMethod() {}
+*/
+void topLevelFunction2() {}
diff --git a/pkg/front_end/test/macro_application/data/tests/marker.options b/pkg/front_end/test/macro_application/data/tests/marker.options
new file mode 100644
index 0000000..578e904
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/marker.options
@@ -0,0 +1 @@
+cfe=pkg/front_end/test/macro_application/macro_application_test.dart
diff --git a/pkg/front_end/test/macro_application/data/tests/parameters.dart b/pkg/front_end/test/macro_application/data/tests/parameters.dart
new file mode 100644
index 0000000..bb606bb
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/parameters.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:macro/macro.dart';
+
+/*member: topLevelFunction1:
+augment void topLevelFunction1(int a, ) {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction1(int a);
+
+/*member: topLevelFunction2:
+augment void topLevelFunction2(int a, int b, ) {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction2(int a, int b);
+
+/*member: topLevelFunction3:
+augment void topLevelFunction3(int a, [int? b, ]) {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction3(int a, [int? b]);
+
+/*member: topLevelFunction4:
+augment void topLevelFunction4(int a, {int? b, int? c, }) {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction4(int a, {int? b, int? c});
diff --git a/pkg/front_end/test/macro_application/data/tests/subtypes.dart b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
new file mode 100644
index 0000000..245908a
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/subtypes.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:macro/macro.dart';
+
+class A {}
+
+class B1 {}
+
+class B2 extends B1 {}
+
+class C1 extends C2 {}
+
+class C2 {}
+
+class D1 {}
+
+class D2 {}
+
+/*member: topLevelFunction1:
+augment A topLevelFunction1(A a, ) {
+  print('isExactly=true');
+  print('isSubtype=true');
+}*/
+@FunctionDefinitionMacro2()
+external A topLevelFunction1(A a);
+
+/*member: topLevelFunction2:
+augment B2 topLevelFunction2(B1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=true');
+}*/
+@FunctionDefinitionMacro2()
+external B2 topLevelFunction2(B1 a);
+
+/*member: topLevelFunction3:
+augment C2 topLevelFunction3(C1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=false');
+}*/
+@FunctionDefinitionMacro2()
+external C2 topLevelFunction3(C1 a);
+
+/*member: topLevelFunction4:
+augment D2 topLevelFunction4(D1 a, ) {
+  print('isExactly=false');
+  print('isSubtype=false');
+}*/
+@FunctionDefinitionMacro2()
+external D2 topLevelFunction4(D1 a);
diff --git a/pkg/front_end/test/macro_application/data/tests/type_annotations.dart b/pkg/front_end/test/macro_application/data/tests/type_annotations.dart
new file mode 100644
index 0000000..b6a4cd8
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/type_annotations.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. 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:math' as math;
+
+import 'package:macro/macro.dart';
+
+/*member: topLevelFunction1:
+augment void topLevelFunction1() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external void topLevelFunction1();
+
+/*member: topLevelFunction2:
+augment dynamic topLevelFunction2() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external dynamic topLevelFunction2();
+
+/*member: topLevelFunction3:
+augment int topLevelFunction3() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external int topLevelFunction3();
+
+/*member: topLevelFunction4:
+augment dynamic topLevelFunction4() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external topLevelFunction4();
+
+/*member: topLevelFunction5:
+augment math.Random topLevelFunction5() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external math.Random topLevelFunction5();
+
+/*member: topLevelFunction6:
+augment List<int> topLevelFunction6() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external List<int> topLevelFunction6();
+
+/*member: topLevelFunction7:
+augment Map<math.Random, List<int>> topLevelFunction7() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external Map<math.Random, List<int>> topLevelFunction7();
+
+/*member: topLevelFunction8:
+augment Map<int?, String>? topLevelFunction8() {
+  return 42;
+}*/
+@FunctionDefinitionMacro1()
+external Map<int?, String>? topLevelFunction8();
diff --git a/pkg/front_end/test/macro_application/data/tests/types.dart b/pkg/front_end/test/macro_application/data/tests/types.dart
new file mode 100644
index 0000000..c10a353
--- /dev/null
+++ b/pkg/front_end/test/macro_application/data/tests/types.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:macro/macro.dart';
+
+@FunctionTypesMacro1()
+/*member: topLevelFunction1:
+class topLevelFunction1GeneratedClass {}
+*/
+void topLevelFunction1() {}
+
+@FunctionTypesMacro1()
+/*member: topLevelFunction2:
+class topLevelFunction2GeneratedClass {}
+*/
+void topLevelFunction2() {}
diff --git a/pkg/front_end/test/macro_application/macro_application_test.dart b/pkg/front_end/test/macro_application/macro_application_test.dart
new file mode 100644
index 0000000..0ad035b
--- /dev/null
+++ b/pkg/front_end/test/macro_application/macro_application_test.dart
@@ -0,0 +1,164 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 Directory, Platform;
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
+    as isolatedExecutor;
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/kernel/macro.dart';
+import 'package:front_end/src/fasta/kernel/utils.dart';
+import 'package:front_end/src/testing/compiler_common.dart';
+import 'package:front_end/src/testing/id_extractor.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:kernel/ast.dart' hide Arguments;
+import 'package:kernel/kernel.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:vm/target/vm.dart';
+
+const Map<String, Map<String, List<String>>> macroDeclarations = {
+  'package:macro/macro.dart': {
+    'FunctionDefinitionMacro1': [''],
+    'FunctionDefinitionMacro2': [''],
+    'FunctionTypesMacro1': [''],
+    'FunctionDeclarationsMacro1': [''],
+  }
+};
+
+Future<Uri> compileMacros(Directory directory) async {
+  CompilerOptions options = new CompilerOptions();
+  options.target = new VmTarget(new TargetFlags());
+  options.explicitExperimentalFlags[ExperimentalFlag.macros] = true;
+  options.environmentDefines = {};
+  options.packagesFileUri = Platform.script.resolve('data/package_config.json');
+
+  CompilerResult? compilerResult = await compileScript(
+      {'main.dart': bootstrapMacroIsolate(macroDeclarations)},
+      options: options, requireMain: false);
+  Uri uri = directory.absolute.uri.resolve('macros.dill');
+  await writeComponentToFile(compilerResult!.component!, uri);
+  return uri;
+}
+
+Future<void> main(List<String> args) async {
+  enableMacros = true;
+
+  Directory tempDirectory =
+      await Directory.systemTemp.createTemp('macro_application');
+
+  Uri macrosUri = await compileMacros(tempDirectory);
+  Map<MacroClass, Uri> precompiledMacroUris = {};
+  macroDeclarations
+      .forEach((String macroUri, Map<String, List<String>> macroClasses) {
+    macroClasses.forEach((String macroClass, List<String> constructorNames) {
+      precompiledMacroUris[new MacroClass(Uri.parse(macroUri), macroClass)] =
+          macrosUri;
+    });
+  });
+
+  Directory dataDir =
+      new Directory.fromUri(Platform.script.resolve('data/tests'));
+  await runTests<String>(dataDir,
+      args: args,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const MacroDataComputer(),
+          [new MacroTestConfig(precompiledMacroUris)]),
+      preserveWhitespaceInAnnotations: true);
+}
+
+class MacroTestConfig extends TestConfig {
+  final Map<MacroClass, Uri> precompiledMacroUris;
+
+  MacroTestConfig(this.precompiledMacroUris)
+      : super(cfeMarker, 'cfe',
+            explicitExperimentalFlags: {ExperimentalFlag.macros: true},
+            packageConfigUri:
+                Platform.script.resolve('data/package_config.json'));
+
+  @override
+  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
+    options.macroExecutorProvider = () async {
+      return await isolatedExecutor.start();
+    };
+    options.precompiledMacroUris = precompiledMacroUris;
+  }
+}
+
+class MacroDataComputer extends DataComputer<String> {
+  const MacroDataComputer();
+
+  @override
+  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+
+  @override
+  void computeMemberData(TestResultData testResultData, Member member,
+      Map<Id, ActualData<String>> actualMap,
+      {bool? verbose}) {
+    CfeDataRegistry<String> registry =
+        new CfeDataRegistry(testResultData.compilerResult, actualMap);
+    MacroApplicationDataForTesting macroApplicationData = testResultData
+        .compilerResult
+        .kernelTargetForTesting!
+        .loader
+        .dataForTesting!
+        .macroApplicationData;
+    StringBuffer sb = new StringBuffer();
+    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
+        in macroApplicationData.memberTypesResults.entries) {
+      if (entry.key.member == member) {
+        for (MacroExecutionResult result in entry.value) {
+          sb.write('\n${codeToString(result.augmentations.first)}');
+        }
+      }
+    }
+    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
+        in macroApplicationData.memberDeclarationsResults.entries) {
+      if (entry.key.member == member) {
+        for (MacroExecutionResult result in entry.value) {
+          sb.write('\n${codeToString(result.augmentations.first)}');
+        }
+      }
+    }
+    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
+        in macroApplicationData.memberDefinitionsResults.entries) {
+      if (entry.key.member == member) {
+        for (MacroExecutionResult result in entry.value) {
+          sb.write('\n${codeToString(result.augmentations.first)}');
+        }
+      }
+    }
+    if (sb.isNotEmpty) {
+      Id id = computeMemberId(member);
+      registry.registerValue(
+          member.fileUri, member.fileOffset, id, sb.toString(), member);
+    }
+  }
+}
+
+void _codeToString(StringBuffer sb, Code code) {
+  for (Object part in code.parts) {
+    if (part is Code) {
+      _codeToString(sb, part);
+    } else if (part is Identifier) {
+      sb.write(part.name);
+    } else {
+      sb.write(part);
+    }
+  }
+}
+
+String codeToString(Code code) {
+  StringBuffer sb = new StringBuffer();
+  _codeToString(sb, code);
+  return sb.toString();
+}
diff --git a/pkg/front_end/test/macros/data/package_config.json b/pkg/front_end/test/macros/data/package_config.json
index 97031ce..f176d49 100644
--- a/pkg/front_end/test/macros/data/package_config.json
+++ b/pkg/front_end/test/macros/data/package_config.json
@@ -6,8 +6,12 @@
       "rootUri": "pkgs/macro/lib/"
     },
     {
-      "name": "macro_builder",
-      "rootUri": "pkgs/macro_builder/lib/"
+      "name": "precompiled_macro",
+      "rootUri": "pkgs/precompiled_macro/lib/"
+    },
+    {
+      "name": "_fe_analyzer_shared",
+      "rootUri": "../../../../_fe_analyzer_shared/lib/"
     }
   ]
 }
\ No newline at end of file
diff --git a/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
index f79b175..c7fc7d5 100644
--- a/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macros/data/pkgs/macro/lib/macro.dart
@@ -2,18 +2,24 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Macro1 implements Macro {
   const Macro1();
+
+  const Macro1.named();
 }
 
 macro class Macro2 implements Macro {
   const Macro2();
+
+  const Macro2.named();
 }
 
-macro class Macro3 implements Macro {
+macro class Macro3<T> implements Macro {
   const Macro3();
+
+  const Macro3.named();
 }
 
 class NonMacro {
diff --git a/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/macro_builder.dart b/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/macro_builder.dart
deleted file mode 100644
index 14354da..0000000
--- a/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/macro_builder.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-export 'src/macro.dart';
diff --git a/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/src/macro.dart b/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/src/macro.dart
deleted file mode 100644
index 434331b..0000000
--- a/pkg/front_end/test/macros/data/pkgs/macro_builder/lib/src/macro.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for 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 Macro {}
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
new file mode 100644
index 0000000..8d112ca
--- /dev/null
+++ b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/precompiled_macro.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+import 'src/macro_base.dart';
+
+macro class PrecompiledMacro extends MacroBase implements Macro {
+  const PrecompiledMacro();
+}
diff --git a/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart
new file mode 100644
index 0000000..e503d1b
--- /dev/null
+++ b/pkg/front_end/test/macros/data/pkgs/precompiled_macro/lib/src/macro_base.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 MacroBase {
+  const MacroBase();
+}
diff --git a/pkg/front_end/test/macros/data/tests/all_precompiled.dart b/pkg/front_end/test/macros/data/tests/all_precompiled.dart
new file mode 100644
index 0000000..9310930
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/all_precompiled.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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: 
+ macroClassIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
+ macroInstanceIds=[package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
+ macrosAreApplied,
+ macrosAreAvailable
+*/
+
+import 'package:precompiled_macro/precompiled_macro.dart';
+
+/*member: main:appliedMacros=[PrecompiledMacro.new]*/
+@PrecompiledMacro()
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/applications.dart b/pkg/front_end/test/macros/data/tests/applications.dart
new file mode 100644
index 0000000..6adb8dc
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/applications.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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: 
+ compilationSequence=[
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
+  main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:macro/macro.dart/Macro2,
+  package:macro/macro.dart/Macro3],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/named(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro2/named(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/named(),
+  package:macro/macro.dart/Macro3/named()],
+ macrosAreApplied,
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
+*/
+
+import 'package:macro/macro.dart';
+import 'package:macro/macro.dart' as prefix;
+
+/*class: Class:
+ appliedMacros=[
+  Macro1.new,
+  Macro2.named,
+  Macro2.new,
+  Macro3.named],
+ macrosAreApplied
+*/
+@Macro2.named()
+@prefix.Macro2()
+@prefix.Macro3.named()
+@Macro1()
+class Class {
+  /*member: Class.:appliedMacros=[
+    Macro1.named,
+    Macro1.new,
+    Macro2.named,
+    Macro3.new]*/
+  @Macro1.named()
+  @prefix.Macro1()
+  @prefix.Macro2.named()
+  @Macro3()
+  Class();
+
+  /*member: Class.method:appliedMacros=[Macro3.named]*/
+  @Macro3.named()
+  void method() {}
+
+  /*member: Class.field:appliedMacros=[Macro3.new]*/
+  @prefix.Macro3()
+  var field;
+}
+
+/*member: method:appliedMacros=[Macro2.named]*/
+@Macro2.named()
+void method() {}
+
+@Macro3()
+/*member: field:appliedMacros=[Macro3.new]*/
+var field;
+
+main() {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_macro.dart b/pkg/front_end/test/macros/data/tests/declare_macro.dart
index e6d329e..65611e1 100644
--- a/pkg/front_end/test/macros/data/tests/declare_macro.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_macro.dart
@@ -3,14 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
- compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  main.dart|package:macro_builder/macro_builder.dart],
+ compilationSequence=[main.dart|package:_fe_analyzer_shared/src/macros/api.dart],
  declaredMacros=[MyMacro],
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class MyMacro implements Macro {}
 
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
index f4e6484..fc6ae56 100644
--- a/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/apply_lib.dart
@@ -10,9 +10,9 @@
 import 'macro_lib.dart';
 import 'apply_lib_dep.dart';
 
-@Macro1()
 /*class: Class:
- appliedMacros=[Macro1],
+ appliedMacros=[Macro1.new],
  macrosAreApplied
 */
+@Macro1()
 class Class extends Super {}
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
index f1aac83..6deb22b 100644
--- a/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/macro_lib.dart
@@ -7,7 +7,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'macro_lib_dep.dart';
 
 macro class Macro1 extends MacroBase implements Macro {
diff --git a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
index 868f08d..09e50a9 100644
--- a/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
+++ b/pkg/front_end/test/macros/data/tests/declare_vs_apply/main.dart
@@ -4,10 +4,12 @@
 
 /*library: 
  compilationSequence=[
-  apply_lib_dep.dart|macro_lib_dep.dart|main_lib_dep.dart|package:macro_builder/src/macro.dart,
-  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  apply_lib_dep.dart|macro_lib.dart|macro_lib_dep.dart|main_lib_dep.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   apply_lib.dart|main.dart],
- macrosAreAvailable
+ macroClassIds=[macro_lib.dart/Macro1],
+ macroInstanceIds=[macro_lib.dart/Macro1/()],
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)]
 */
 
 import 'apply_lib.dart';
diff --git a/pkg/front_end/test/macros/data/tests/direct_import.dart b/pkg/front_end/test/macros/data/tests/direct_import.dart
index f3484cd..793a5f4 100644
--- a/pkg/front_end/test/macros/data/tests/direct_import.dart
+++ b/pkg/front_end/test/macros/data/tests/direct_import.dart
@@ -2,14 +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.
 
-/*library: 
- compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  main.dart],
- macrosAreAvailable
-*/
+/*library: macrosAreAvailable*/
 
 // ignore: unused_import
-import 'package:macro_builder/src/macro.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
index dca3012..793a5f4 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_builder.dart
@@ -2,14 +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.
 
-/*library: 
- compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  main.dart|package:macro_builder/macro_builder.dart],
- macrosAreAvailable
-*/
+/*library: macrosAreAvailable*/
 
 // ignore: unused_import
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_package.dart b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
index 1fabb48..64d7efc 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_package.dart
@@ -4,10 +4,10 @@
 
 /*library: 
  compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
   main.dart],
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
 */
 
 // ignore: unused_import
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart b/pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart
index c08cbcd..536ad16 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_source/macro_lib.dart
@@ -7,7 +7,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Macro1 implements Macro {
   const Macro1();
diff --git a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
index 5b109f4..d94aeaa 100644
--- a/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/import_macro_source/main.dart
@@ -4,10 +4,10 @@
 
 /*library: 
  compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   main.dart],
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)]
 */
 
 // ignore: unused_import
diff --git a/pkg/front_end/test/macros/data/tests/macro_declarations.dart b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
index f5f5a5f..c780d61 100644
--- a/pkg/front_end/test/macros/data/tests/macro_declarations.dart
+++ b/pkg/front_end/test/macros/data/tests/macro_declarations.dart
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
- compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  main.dart|package:macro_builder/macro_builder.dart],
+ compilationSequence=[main.dart|package:_fe_analyzer_shared/src/macros/api.dart],
  declaredMacros=[
   Extends,
   ExtendsAlias,
@@ -18,7 +16,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Extends extends Macro {}
 
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
index c08cbcd..536ad16 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib1.dart
@@ -7,7 +7,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Macro1 implements Macro {
   const Macro1();
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
index 729e7f1..fc0d199 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2a.dart
@@ -7,7 +7,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Macro2a implements Macro {
   const Macro2a();
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
index df143f5..3aa757c 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/macro_lib2b.dart
@@ -8,14 +8,14 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'macro_lib2a.dart';
 
-@Macro2a()
 /*class: Macro2b:
- appliedMacros=[Macro2a],
+ appliedMacros=[Macro2a.new],
  macrosAreApplied
 */
+@Macro2a()
 macro class Macro2b implements Macro {
   const Macro2b();
 }
diff --git a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
index 9dee592..103c1ed 100644
--- a/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
+++ b/pkg/front_end/test/macros/data/tests/multiple_macros/main.dart
@@ -4,23 +4,32 @@
 
 /*library: 
  compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  macro_lib1.dart|macro_lib2a.dart|package:macro_builder/macro_builder.dart,
+  macro_lib1.dart|macro_lib2a.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   macro_lib2b.dart,
   main.dart],
+ macroClassIds=[
+  macro_lib1.dart/Macro1,
+  macro_lib2a.dart/Macro2a,
+  macro_lib2b.dart/Macro2b],
+ macroInstanceIds=[
+  macro_lib1.dart/Macro1/(),
+  macro_lib2a.dart/Macro2a/(),
+  macro_lib2a.dart/Macro2a/(),
+  macro_lib2b.dart/Macro2b/()],
  macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib1.dart=Macro1(new)macro_lib2a.dart=Macro2a(new)]
 */
 
 import 'macro_lib1.dart';
 import 'macro_lib2a.dart';
 import 'macro_lib2b.dart';
 
+/*member: main:appliedMacros=[
+  Macro1.new,
+  Macro2a.new,
+  Macro2b.new]*/
 @Macro1()
 @Macro2a()
 @Macro2b()
-/*member: main:appliedMacros=[
-  Macro1,
-  Macro2a,
-  Macro2b]*/
 void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/precompiled.dart b/pkg/front_end/test/macros/data/tests/precompiled.dart
new file mode 100644
index 0000000..16171a8
--- /dev/null
+++ b/pkg/front_end/test/macros/data/tests/precompiled.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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: 
+ compilationSequence=[
+  package:macro/macro.dart,
+  main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:precompiled_macro/precompiled_macro.dart/PrecompiledMacro/()],
+ macrosAreApplied,
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
+*/
+
+import 'package:precompiled_macro/precompiled_macro.dart';
+import 'package:macro/macro.dart';
+
+/*member: main:appliedMacros=[
+  Macro1.new,
+  PrecompiledMacro.new]*/
+@PrecompiledMacro()
+@Macro1()
+void main() {}
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_package.dart b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
index 74f18ff..9fea835 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_package.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_package.dart
@@ -3,34 +3,48 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /*library: 
- appliedMacros=[Macro3],
  compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  package:macro/macro.dart|package:macro_builder/macro_builder.dart,
+  package:_fe_analyzer_shared/src/macros/api.dart|package:macro/macro.dart,
   main.dart],
+ macroClassIds=[
+  package:macro/macro.dart/Macro1,
+  package:macro/macro.dart/Macro2,
+  package:macro/macro.dart/Macro3],
+ macroInstanceIds=[
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro1/(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro2/(),
+  package:macro/macro.dart/Macro3/(),
+  package:macro/macro.dart/Macro3/()],
  macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[package:macro/macro.dart=Macro1(named/new)|Macro2(named/new)|Macro3(named/new)]
 */
-@Macro3()
 library use_macro_package;
 
 import 'package:macro/macro.dart';
 
+/*member: main:appliedMacros=[Macro1.new]*/
 @Macro1()
-/*member: main:appliedMacros=[Macro1]*/
 void main() {}
 
-@Macro2()
 /*class: Class1:
- appliedMacros=[Macro2],
+ appliedMacros=[Macro2.new],
  macrosAreApplied
 */
+@Macro2()
 class Class1 {
+  /*member: Class1.:appliedMacros=[Macro3.new]*/
+  @Macro3()
+  Class1();
+
+  /*member: Class1.method:appliedMacros=[
+    Macro1.new,
+    Macro2.new]*/
   @Macro1()
   @Macro2()
-  /*member: Class1.method:appliedMacros=[
-    Macro1,
-    Macro2]*/
   void method() {}
 }
 
@@ -39,8 +53,8 @@
 
 /*class: Class3:macrosAreApplied*/
 class Class3 {
+  /*member: Class3.field:appliedMacros=[Macro3.new]*/
   @Macro3()
-  /*member: Class3.field:appliedMacros=[Macro3]*/
   var field;
 }
 
@@ -48,3 +62,21 @@
   @NonMacro()
   var field;
 }
+
+/*member: field:appliedMacros=[Macro1.new]*/
+@Macro1()
+var field;
+
+extension Extension on int {
+  /*member: Extension|field:*/
+  @Macro1()
+  static var field;
+
+  /*member: Extension|method:*/
+  @Macro2()
+  void method() {}
+
+  /*member: Extension|staticMethod:*/
+  @Macro3()
+  static void staticMethod() {}
+}
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart b/pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart
index f3767a5..9369d7d 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_source/macro_lib.dart
@@ -9,7 +9,7 @@
  macrosAreAvailable
 */
 
-import 'package:macro_builder/macro_builder.dart';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
 
 macro class Macro1 implements Macro {
   const Macro1();
diff --git a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
index 930eb5c..475694d 100644
--- a/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
+++ b/pkg/front_end/test/macros/data/tests/use_macro_source/main.dart
@@ -4,30 +4,39 @@
 
 /*library: 
  compilationSequence=[
-  package:macro_builder/src/macro.dart,
-  macro_lib.dart|package:macro_builder/macro_builder.dart,
+  macro_lib.dart|package:_fe_analyzer_shared/src/macros/api.dart,
   main.dart],
+ macroClassIds=[
+  macro_lib.dart/Macro1,
+  macro_lib.dart/Macro2],
+ macroInstanceIds=[
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro1/(),
+  macro_lib.dart/Macro2/(),
+  macro_lib.dart/Macro2/()],
  macrosAreApplied,
- macrosAreAvailable
+ macrosAreAvailable,
+ neededPrecompilations=[macro_lib.dart=Macro1(new)|Macro2(new)]
 */
 
 import 'macro_lib.dart';
 
+/*member: main:appliedMacros=[Macro1.new]*/
 @Macro1()
-/*member: main:appliedMacros=[Macro1]*/
 void main() {}
 
-@Macro2()
 /*class: Class1:
- appliedMacros=[Macro2],
+ appliedMacros=[Macro2.new],
  macrosAreApplied
 */
+@Macro2()
 class Class1 {
+  /*member: Class1.method:appliedMacros=[
+    Macro1.new,
+    Macro2.new]*/
   @Macro1()
   @Macro2()
-  /*member: Class1.method:appliedMacros=[
-    Macro1,
-    Macro2]*/
   void method() {}
 }
 
@@ -36,8 +45,8 @@
 
 /*class: Class3:macrosAreApplied*/
 class Class3 {
+  /*member: Class3.field:appliedMacros=[Macro1.new]*/
   @Macro1()
-  /*member: Class3.field:appliedMacros=[Macro1]*/
   var field;
 }
 
diff --git a/pkg/front_end/test/macros/macro_test.dart b/pkg/front_end/test/macros/macro_test.dart
index c1aa33e..47c4300 100644
--- a/pkg/front_end/test/macros/macro_test.dart
+++ b/pkg/front_end/test/macros/macro_test.dart
@@ -4,14 +4,20 @@
 
 import 'dart:io' show Directory, Platform;
 
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/fasta/builder/class_builder.dart';
+import 'package:front_end/src/fasta/builder/library_builder.dart';
+import 'package:front_end/src/fasta/builder/member_builder.dart';
 import 'package:front_end/src/fasta/kernel/macro.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' hide Arguments;
 
 Future<void> main(List<String> args) async {
   enableMacros = true;
@@ -22,45 +28,52 @@
       args: args,
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
-      runTest: runTestFor(const MacroDataComputer(), [
-        new TestConfig(cfeMarker, 'cfe',
+      runTest: runTestFor(const MacroDataComputer(), [new MacroTestConfig()]));
+}
+
+class MacroTestConfig extends TestConfig {
+  MacroTestConfig()
+      : super(cfeMarker, 'cfe',
             explicitExperimentalFlags: {ExperimentalFlag.macros: true},
             packageConfigUri:
-                Platform.script.resolve('data/package_config.json'))
-      ]));
+                Platform.script.resolve('data/package_config.json'));
+
+  @override
+  TestMacroExecutor customizeCompilerOptions(
+      CompilerOptions options, TestData testData) {
+    TestMacroExecutor macroExecutor = new TestMacroExecutor();
+    options.macroExecutorProvider = () async => macroExecutor;
+    Uri precompiledPackage =
+        Uri.parse('package:precompiled_macro/precompiled_macro.dart');
+    options.precompiledMacroUris = {
+      new MacroClass(precompiledPackage, 'PrecompiledMacro'): dummyUri,
+    };
+    return macroExecutor;
+  }
 }
 
 class MacroDataComputer extends DataComputer<Features> {
   const MacroDataComputer();
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    member.accept(new MacroDataExtractor(compilerResult, actualMap));
+    member.accept(new MacroDataExtractor(testResultData, actualMap));
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new MacroDataExtractor(compilerResult, actualMap).computeForClass(cls);
+    new MacroDataExtractor(testResultData, actualMap).computeForClass(cls);
   }
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new MacroDataExtractor(compilerResult, actualMap)
+    new MacroDataExtractor(testResultData, actualMap)
         .computeForLibrary(library);
   }
 
@@ -73,8 +86,15 @@
   static const String macrosAreAvailable = 'macrosAreAvailable';
   static const String macrosAreApplied = 'macrosAreApplied';
   static const String compilationSequence = 'compilationSequence';
+  static const String neededPrecompilations = 'neededPrecompilations';
   static const String declaredMacros = 'declaredMacros';
   static const String appliedMacros = 'appliedMacros';
+  static const String macroClassIds = 'macroClassIds';
+  static const String macroInstanceIds = 'macroInstanceIds';
+}
+
+String constructorNameToString(String constructorName) {
+  return constructorName == '' ? 'new' : constructorName;
 }
 
 String importUriToString(Uri importUri) {
@@ -96,55 +116,82 @@
 }
 
 class MacroDataExtractor extends CfeDataExtractor<Features> {
-  late final MacroDeclarationData macroDeclarationData;
-  late final MacroApplicationData macroApplicationData;
+  final TestResultData testResultData;
 
-  MacroDataExtractor(InternalCompilerResult compilerResult,
-      Map<Id, ActualData<Features>> actualMap)
-      : super(compilerResult, actualMap) {
-    macroDeclarationData = compilerResult
-        .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
-    macroApplicationData = compilerResult
-        .kernelTargetForTesting!.loader.dataForTesting!.macroApplicationData;
-  }
+  MacroDataExtractor(
+      this.testResultData, Map<Id, ActualData<Features>> actualMap)
+      : super(testResultData.compilerResult, actualMap);
+
+  TestMacroExecutor get macroExecutor => testResultData.customData;
+
+  MacroDeclarationData get macroDeclarationData => testResultData.compilerResult
+      .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
+  MacroApplicationDataForTesting get macroApplicationData => testResultData
+      .compilerResult
+      .kernelTargetForTesting!
+      .loader
+      .dataForTesting!
+      .macroApplicationData;
 
   LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
-    return macroApplicationData.libraryData[library];
-  }
-
-  MacroApplications? getLibraryMacroApplications(Library library) {
-    return getLibraryMacroApplicationData(library)?.libraryApplications;
+    for (MapEntry<LibraryBuilder, LibraryMacroApplicationData> entry
+        in macroApplicationData.libraryData.entries) {
+      if (entry.key.library == library) {
+        return entry.value;
+      }
+    }
+    return null;
   }
 
   ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
     LibraryMacroApplicationData? applicationData =
         getLibraryMacroApplicationData(cls.enclosingLibrary);
     if (applicationData != null) {
-      return applicationData.classData[cls];
+      for (MapEntry<ClassBuilder, ClassMacroApplicationData> entry
+          in applicationData.classData.entries) {
+        if (entry.key.cls == cls) {
+          return entry.value;
+        }
+      }
     }
     return null;
   }
 
-  MacroApplications? getClassMacroApplications(Class cls) {
+  List<MacroApplication>? getClassMacroApplications(Class cls) {
     return getClassMacroApplicationData(cls)?.classApplications;
   }
 
-  MacroApplications? getMemberMacroApplications(Member member) {
+  List<MacroApplication>? getMemberMacroApplications(Member member) {
     Class? enclosingClass = member.enclosingClass;
+    Map<MemberBuilder, List<MacroApplication>>? memberApplications;
     if (enclosingClass != null) {
-      return getClassMacroApplicationData(enclosingClass)
-          ?.memberApplications[member];
+      memberApplications =
+          getClassMacroApplicationData(enclosingClass)?.memberApplications;
     } else {
-      return getLibraryMacroApplicationData(member.enclosingLibrary)
-          ?.memberApplications[member];
+      memberApplications =
+          getLibraryMacroApplicationData(member.enclosingLibrary)
+              ?.memberApplications;
     }
+    if (memberApplications != null) {
+      for (MapEntry<MemberBuilder, List<MacroApplication>> entry
+          in memberApplications.entries) {
+        if (entry.key.member == member) {
+          return entry.value;
+        }
+      }
+    }
+    return null;
   }
 
   void registerMacroApplications(
-      Features features, MacroApplications? macroApplications) {
+      Features features, List<MacroApplication>? macroApplications) {
     if (macroApplications != null) {
-      for (Class cls in macroApplications.macros) {
-        features.addElement(Tags.appliedMacros, cls.name);
+      for (MacroApplication application in macroApplications) {
+        String className = application.classBuilder.name;
+        String constructorName =
+            constructorNameToString(application.constructorName);
+        features.addElement(
+            Tags.appliedMacros, '${className}.${constructorName}');
       }
     }
   }
@@ -173,6 +220,38 @@
               Tags.compilationSequence, strongComponentToString(component));
         }
       }
+      for (Map<Uri, Map<String, List<String>>> precompilation
+          in macroDeclarationData.neededPrecompilations) {
+        Map<String, Map<String, List<String>>> converted =
+            new Map.fromIterables(precompilation.keys.map(importUriToString),
+                precompilation.values);
+        List<String> uris = converted.keys.toList()..sort();
+        StringBuffer sb = new StringBuffer();
+        for (String uri in uris) {
+          sb.write(uri);
+          sb.write('=');
+          Map<String, List<String>> macros = converted[uri]!;
+          List<String> classes = macros.keys.toList()..sort();
+          String delimiter = '';
+          for (String cls in classes) {
+            List<String> constructorNames =
+                macros[cls]!.map(constructorNameToString).toList()..sort();
+            sb.write(delimiter);
+            sb.write(cls);
+            sb.write('(');
+            sb.write(constructorNames.join('/'));
+            sb.write(')');
+            delimiter = '|';
+          }
+        }
+        features.addElement(Tags.neededPrecompilations, sb.toString());
+      }
+      for (_MacroClassIdentifier id in macroExecutor.macroClasses) {
+        features.addElement(Tags.macroClassIds, id.toText());
+      }
+      for (_MacroInstanceIdentifier id in macroExecutor.macroInstances) {
+        features.addElement(Tags.macroInstanceIds, id.toText());
+      }
     }
     List<String>? macroClasses =
         macroDeclarationData.macroDeclarations[node.importUri];
@@ -184,7 +263,7 @@
     if (getLibraryMacroApplicationData(node) != null) {
       features.add(Tags.macrosAreApplied);
     }
-    registerMacroApplications(features, getLibraryMacroApplications(node));
+
     return features;
   }
 
@@ -195,3 +274,120 @@
     return features;
   }
 }
+
+class TestMacroExecutor implements MacroExecutor {
+  List<_MacroClassIdentifier> macroClasses = [];
+  List<_MacroInstanceIdentifier> macroInstances = [];
+
+  @override
+  Future<String> buildAugmentationLibrary(
+      Iterable<MacroExecutionResult> macroResults) {
+    // TODO: implement buildAugmentationLibrary
+    throw UnimplementedError();
+  }
+
+  @override
+  void close() {
+    // TODO: implement close
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDeclarationsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector) async {
+    return new _MacroExecutionResult();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeDefinitionsPhase(
+      MacroInstanceIdentifier macro,
+      Declaration declaration,
+      TypeResolver typeResolver,
+      ClassIntrospector classIntrospector,
+      TypeDeclarationResolver typeDeclarationResolver) async {
+    return new _MacroExecutionResult();
+  }
+
+  @override
+  Future<MacroExecutionResult> executeTypesPhase(
+      MacroInstanceIdentifier macro, Declaration declaration) async {
+    return new _MacroExecutionResult();
+  }
+
+  @override
+  Future<MacroInstanceIdentifier> instantiateMacro(
+      MacroClassIdentifier macroClass,
+      String constructor,
+      Arguments arguments) async {
+    _MacroInstanceIdentifier id = new _MacroInstanceIdentifier(
+        macroClass as _MacroClassIdentifier, constructor, arguments);
+    macroInstances.add(id);
+    return id;
+  }
+
+  @override
+  Future<MacroClassIdentifier> loadMacro(Uri library, String name,
+      {Uri? precompiledKernelUri}) async {
+    _MacroClassIdentifier id = new _MacroClassIdentifier(library, name);
+    macroClasses.add(id);
+    return id;
+  }
+}
+
+class _MacroClassIdentifier implements MacroClassIdentifier {
+  final Uri uri;
+  final String className;
+
+  _MacroClassIdentifier(this.uri, this.className);
+
+  String toText() => '${importUriToString(uri)}/${className}';
+
+  @override
+  int get hashCode => uri.hashCode * 13 + className.hashCode * 17;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is _MacroClassIdentifier &&
+        uri == other.uri &&
+        className == other.className;
+  }
+
+  @override
+  String toString() => 'MacroClassIdentifier($uri,$className)';
+
+  @override
+  void serialize(Serializer serializer) => throw UnimplementedError();
+}
+
+class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
+  final _MacroClassIdentifier macroClass;
+  final String constructor;
+  final Arguments arguments;
+
+  _MacroInstanceIdentifier(this.macroClass, this.constructor, this.arguments);
+
+  String toText() => '${macroClass.toText()}/${constructor}()';
+
+  @override
+  void serialize(Serializer serializer) => throw UnimplementedError();
+
+  @override
+  bool shouldExecute(DeclarationKind declarationKind, Phase phase) => false;
+
+  @override
+  bool supportsDeclarationKind(DeclarationKind declarationKind) => false;
+}
+
+class _MacroExecutionResult implements MacroExecutionResult {
+  @override
+  Iterable<DeclarationCode> augmentations = const [];
+
+  @override
+  Iterable<DeclarationCode> imports = const [];
+
+  @override
+  void serialize(Serializer serializer) {}
+}
diff --git a/pkg/front_end/test/outline_extractor_suite.dart b/pkg/front_end/test/outline_extractor_suite.dart
index f022e0c..80754c7 100644
--- a/pkg/front_end/test/outline_extractor_suite.dart
+++ b/pkg/front_end/test/outline_extractor_suite.dart
@@ -150,7 +150,6 @@
         await extractOutline([description.uri], packages: packages);
 
     void onDiagnostic(DiagnosticMessage message) {
-      if (message.codeName == "InferredPackageUri") return;
       if (message.severity == Severity.error ||
           message.severity == Severity.warning) {
         throw ("Unexpected error: ${message.plainTextFormatted.join('\n')}");
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 60129e5..9828fd4 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -4,15 +4,15 @@
 
 import 'dart:io' show Directory, Platform;
 
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
 import 'package:front_end/src/fasta/builder/builder.dart';
-import 'package:front_end/src/fasta/builder/class_builder.dart';
 import 'package:front_end/src/fasta/builder/member_builder.dart';
-
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:front_end/src/fasta/source/source_class_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart';
@@ -65,33 +65,26 @@
   const PatchingDataComputer();
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    member.accept(new PatchingDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new PatchingDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
-  void computeClassData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Class cls,
+  void computeClassData(TestResultData testResultData, Class cls,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new PatchingDataExtractor(compilerResult, actualMap).computeForClass(cls);
+    new PatchingDataExtractor(testResultData.compilerResult, actualMap)
+        .computeForClass(cls);
   }
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new PatchingDataExtractor(compilerResult, actualMap)
+    new PatchingDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
@@ -99,8 +92,8 @@
   bool get supportsErrors => true;
 
   @override
-  Features computeErrorData(TestConfig config, InternalCompilerResult compiler,
-      Id id, List<FormattedMessage> errors) {
+  Features computeErrorData(
+      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
     Features features = new Features();
     features[Tags.error] = errorsToText(errors);
     return features;
@@ -135,7 +128,8 @@
 
   @override
   Features computeClassValue(Id id, Class cls) {
-    ClassBuilder clsBuilder = lookupClassBuilder(compilerResult, cls)!;
+    SourceClassBuilder clsBuilder =
+        lookupClassBuilder(compilerResult, cls) as SourceClassBuilder;
 
     Features features = new Features();
     if (cls.isAbstract) {
@@ -174,9 +168,9 @@
         features.addElement(Tags.initializers, desc);
       }
     }
-    MemberBuilderImpl? memberBuilder =
+    SourceMemberBuilder? memberBuilder =
         lookupMemberBuilder(compilerResult, member, required: false)
-            as MemberBuilderImpl?;
+            as SourceMemberBuilder?;
     MemberBuilder? patchMember = memberBuilder?.dataForTesting?.patchForTesting;
     if (patchMember != null) {
       features.add(Tags.patch);
diff --git a/pkg/front_end/test/predicates/predicate_test.dart b/pkg/front_end/test/predicates/predicate_test.dart
index 5866119..2ffdc45 100644
--- a/pkg/front_end/test/predicates/predicate_test.dart
+++ b/pkg/front_end/test/predicates/predicate_test.dart
@@ -78,24 +78,19 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    new PredicateDataExtractor(compilerResult, actualMap)
+    new PredicateDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<Features>> actualMap,
       {bool? verbose}) {
-    member.accept(new PredicateDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new PredicateDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
diff --git a/pkg/front_end/test/simple_stats.dart b/pkg/front_end/test/simple_stats.dart
index 6a94bbe..ac2e12e 100644
--- a/pkg/front_end/test/simple_stats.dart
+++ b/pkg/front_end/test/simple_stats.dart
@@ -34,6 +34,11 @@
     }
   }
 
+  static double average<E extends num>(List<E> data) {
+    E sum = data.reduce((value, element) => (value + element) as E);
+    return sum / data.length;
+  }
+
   static double variance<E extends num>(List<E> data) {
     E sum = data.reduce((value, element) => (value + element) as E);
     int count = data.length;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 81e6368..19431ef 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -45,6 +45,7 @@
 ansi
 answering
 anyone
+aot
 ap
 api
 apis
@@ -53,7 +54,6 @@
 applicable
 arg
 args
-argument1
 arise
 arising
 arity
@@ -86,17 +86,6 @@
 awaiting
 awaits
 b
-b0i
-b0m
-b0n
-b1a
-b1i
-b1m
-b1n
-b23d3b125e9d246e07a2b43b61740759a0dace
-b2i
-b2m
-b2n
 backlog
 backping
 backstop
@@ -125,8 +114,6 @@
 binder
 binders
 binds
-bit1
-bit2
 bj
 bk
 blindly
@@ -140,6 +127,7 @@
 bof
 bom
 bones
+bootstrap
 bother
 boundness
 boxed
@@ -200,18 +188,6 @@
 clarification
 clashes
 class's
-class2a
-class2b
-class3a
-class3b
-class3c
-class4a
-class4b
-class4c
-class4d
-class4e
-class6a
-class6b
 clazz
 cli
 client's
@@ -230,7 +206,6 @@
 com
 combinations
 combinator
-combine2
 combiner
 communication
 compared
@@ -292,14 +267,12 @@
 cwd
 cyclically
 d
-d11e
-d7c
+dace
 dag
 dangerous
 dangling
 danrubel
 daringfireball
-dart2native
 dartbug
 dartdoc
 dartfix
@@ -308,8 +281,8 @@
 dashes
 dc
 ddc
+ddfea
 ddk
-dea112b090073317d
 debuggable
 dec
 decl
@@ -321,10 +294,10 @@
 deeply
 def
 defaulting
-definitions
 degrades
 degree
 del
+delegated
 delimit
 delimiting
 demands
@@ -332,7 +305,6 @@
 demangled
 dep
 deps
-dereferenced
 dereferencing
 deregister
 descent
@@ -350,6 +322,7 @@
 deterministic
 dev
 device
+dictates
 diff
 differs
 diffs
@@ -374,6 +347,7 @@
 dmitryas
 doc
 docs
+doesn\'t
 dom
 dont
 doubles
@@ -390,6 +364,7 @@
 dynamically
 e
 easy
+eb
 ecma
 ecosystem
 ed
@@ -418,6 +393,7 @@
 engineered
 enhanced
 enters
+entrypoint
 entrypointish
 enumerates
 env
@@ -426,7 +402,6 @@
 equation
 equivalences
 erased
-erasure
 es
 establish
 established
@@ -434,6 +409,7 @@
 eval
 execute
 executor
+executors
 exhausted
 existence
 existentially
@@ -470,12 +446,10 @@
 fff
 ffff
 fffff
+ffffff
+fffffff
 ffffffff
 ffi
-field1
-field1a
-field1b
-field2
 fieldformal
 file's
 filenames
@@ -488,12 +462,6 @@
 fits
 fixnum
 fleshed
-float32
-float32x
-float32x4
-float64
-float64x
-float64x2
 floitsch
 flowed
 flushed
@@ -529,8 +497,6 @@
 getable
 getables
 gets
-getter1a
-getter1b
 getting
 gft
 git
@@ -585,7 +551,6 @@
 human
 i
 i'll
-i2b
 ic
 id
 ideal
@@ -601,6 +566,7 @@
 impl
 impl+
 implementers
+impls
 imply
 implying
 importantly
@@ -612,6 +578,7 @@
 inconsistency
 increased
 incremented
+incrementing
 independently
 indexer
 indexing
@@ -637,12 +604,6 @@
 inst
 instanceof
 instantiator
-int16
-int32
-int32x
-int32x4
-int64
-int8
 integrate
 intends
 intentionally
@@ -663,9 +624,9 @@
 ints
 invariants
 io
-is64
 isolate
 isolated
+isolates
 issuecomment
 issuing
 iterables
@@ -679,6 +640,7 @@
 java
 jenkins
 jensj
+jit
 job
 johnniwinther
 js
@@ -690,7 +652,6 @@
 k
 kallentu
 kernel's
-kernel2kernel
 kill
 klass
 kmillikin
@@ -725,6 +686,7 @@
 lhs
 lib
 libs
+lifetime
 lifted
 lifter
 limiting
@@ -766,6 +728,7 @@
 masking
 masks
 master
+mature
 mb
 mc
 md
@@ -775,32 +738,6 @@
 meta
 metadata's
 metadatum
-method10a
-method10b
-method1a
-method1b
-method1c
-method2a
-method2b
-method2c
-method3a
-method3b
-method3c
-method4a
-method4b
-method4c
-method5a
-method5b
-method5c
-method6a
-method6b
-method6c
-method7a
-method7b
-method8a
-method8b
-method9a
-method9b
 mi
 migrated
 migration
@@ -837,6 +774,7 @@
 newest
 nextnext
 ni
+nil
 nine
 nj
 nk
@@ -855,9 +793,6 @@
 nt
 nth
 nullabilities
-nullable1
-nullable2
-nullable3
 nullary
 nullification
 nullify
@@ -874,7 +809,6 @@
 occupied
 occurences
 offending
-offs
 ogham
 oked
 op
@@ -882,8 +816,6 @@
 opt
 optimizations
 opting
-option1
-option2
 opts
 ordered
 orders
@@ -906,16 +838,6 @@
 overwriting
 ownership
 p
-p0i
-p0k
-p1
-p1i
-p1k
-p1l
-p2
-p2i
-p2k
-p2q
 par
 parallel
 param
@@ -964,9 +886,15 @@
 pow
 pragma
 pre
+prebuild
 prebuilt
+precompilation
+precompilations
+precompile
+precompiled
 preexisted
 preexisting
+prefixing
 premark
 preorder
 prepares
@@ -994,6 +922,7 @@
 proto
 protobuf
 protocol
+provider
 ps
 pulled
 pure
@@ -1017,10 +946,6 @@
 r'\t
 r'\u
 r'\v
-r0i
-r0j
-r1i
-r2i
 ra
 radix
 raises
@@ -1059,6 +984,7 @@
 recompiling
 recompute
 recomputed
+reconstruct
 recorder
 recoveries
 recreate
@@ -1071,6 +997,7 @@
 redo
 reexports
 ref
+refactoring
 reflect
 reflectee
 reflective
@@ -1087,11 +1014,13 @@
 relax
 relaxes
 released
+reliably
 relink
 reload
 reloading
 remapped
 remedy
+remotely
 removal
 remover
 renames
@@ -1175,7 +1104,7 @@
 setables
 setaf
 sh
-sha1hash
+sha
 shadowed
 shallow
 shas
@@ -1221,11 +1150,13 @@
 spaced
 sparse
 spawn
+spawned
 spawns
 spec
 spec'ed
 specialization
 specially
+specifications
 specifics
 speeding
 spend
@@ -1359,6 +1290,7 @@
 topological
 tops
 tput
+traced
 tracker
 traditional
 transformers
@@ -1368,30 +1300,17 @@
 traverse
 trees
 tricky
+triggering
 trips
 trivially
 ts
 tty
 tuple
-tuple2
-tuple3
-tuple4
-tuple5
-tuple6
-tuple7
-tuple8
-type1
-type2
 typeref
 u
-u001b
 ufeff
 ui
 uint
-uint16
-uint32
-uint64
-uint8
 umbrella
 un
 unaffected
@@ -1425,14 +1344,12 @@
 uninstantiable
 uninstantiated
 unintentionally
-unions
 uniqueness
 unittest
 universally
 unlinked
 unlower
 unmark
-unmodifiable
 unneeded
 unordered
 unpaired
@@ -1444,14 +1361,12 @@
 unshadowed
 unsortable
 unsound
-unsoundness
 untouched
 unwrapper
 unwraps
 unwritten
 unzip
 upcast
-update2018
 ur
 uri's
 url
@@ -1460,8 +1375,6 @@
 usr
 usual
 usually
-utf16
-utf8
 util
 utils
 v
@@ -1478,6 +1391,7 @@
 vegorov
 verbosity
 versa
+versus
 viable
 vice
 video
@@ -1515,41 +1429,17 @@
 wind
 wise
 wiser
-with1
 wn
 worthwhile
 worthy
 woven
+wrappers
 writeln
 wrongfully
 wrt
 wtf
 www
 x
-x0
-x00
-x00003fff
-x0007ffff
-x03ffffff
-x10
-x10ffff
-x180
-x1b
-x1f
-x1ff
-x1fffffff
-x2
-x200
-x202
-x205
-x3
-x3f
-x3fffffff
-x5
-x7
-x7fff
-x90
-x9ddfea08eb
 xb
 xbb
 xbf
@@ -1585,6 +1475,7 @@
 yields
 yn
 ynon
+yourself
 ypotentially
 ys
 yss
@@ -1596,3 +1487,4 @@
 zn
 zone
 zoned
+zones
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 39c9d6c..d69db07 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -475,6 +475,7 @@
 clone
 cloned
 cloner
+cloners
 clones
 cloning
 close
@@ -586,6 +587,7 @@
 conformed
 confuse
 confused
+confusion
 conjunction
 connect
 connected
@@ -1027,6 +1029,7 @@
 entries
 entry
 enum
+enum's
 enumerated
 enumeration
 enumerations
@@ -1515,6 +1518,7 @@
 information
 informational
 informs
+inherent
 inherently
 inherit
 inheritable
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index 30bf90d..3230d25 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -31,7 +31,6 @@
 dartbug.com
 dname
 e.g
-enum's
 f
 ffi
 flutter_runner
@@ -75,6 +74,7 @@
 struct<#name
 structs
 super.namedconstructor
+superinterface
 supermixin
 team
 this.namedconstructor
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index ea9623a..bea0c4d 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -9,21 +9,15 @@
 # Comments on a line by itself will be considered a header of the file and
 # automatic tools might move it to the top of the file.
 
-a0x
-a1x
-a2i
-a2x
-a3i
-a4i
 aa
 aaa
-abc
 abcompile
 adapter
 adaptor
 adopted
 advantages
 albeit
+aligns
 allocations
 allowlist
 allowlisting
@@ -32,12 +26,12 @@
 amended
 amortized
 analyses
+andahalf
 animal
 animated
 annoying
 anon
 aoo
-aot
 applier
 approval
 approximation
@@ -51,10 +45,9 @@
 authority
 autobianchi
 automatic
+averaged
+averages
 axis
-b0x
-b1x
-b2x
 ba
 baba
 backed
@@ -62,12 +55,8 @@
 bail
 bailing
 bailout
-bar1a
-bar1b
-bar2a
-bar2b
-bar3a
-bar3b
+bar'baz
+bar\'baz
 barbar
 bash
 bat
@@ -82,12 +71,9 @@
 bkonyi
 bla
 blah
-blindly
-blocked
 blorp
 bold
 boo
-bootstrap
 bots
 boundarykey
 bowtie
@@ -97,56 +83,13 @@
 brave
 brown
 bt
-bt3a
-bt3b
-bt4a
-bt4b
 btw
 builddir
-bulk2
 bulkcompile
 busy
 busywait
 bye
 c's
-c1a
-c1b
-c1c
-c1d
-c1e
-c1f
-c2a
-c2b
-c2c
-c2d
-c2e
-c3a
-c3b
-c3c
-c3d
-c3e
-c3f
-c4a
-c4b
-c4c
-c4d
-c4e
-c4f
-c4g
-c4h
-c59cdee365b94ce066344840f9e3412d642019b
-c5a
-c5b
-c5c
-c5d
-c6a
-c6b
-c6c
-c7a
-c8a
-c8b
-c8c
-c8d
 ca
 cafebabe
 calloc
@@ -157,7 +100,7 @@
 cb
 cc
 ccc
-cell
+cdee
 certificate
 cf
 characteristics
@@ -167,22 +110,6 @@
 chunked
 cipd
 circular
-class1a
-class1b
-class2c
-class2d
-class2e
-class2f
-class3d
-class4int
-class5a
-class5b
-class5c
-class5d
-class7a
-class7b
-class8a
-class8b
 cloneable
 cm
 cmd
@@ -195,14 +122,11 @@
 commented
 commit
 commits
-communication
 companion
 comparative
 comparer
-compilations
 compiler's
 complement
-completers
 complicated
 concurrently
 confidence
@@ -210,33 +134,24 @@
 confirm
 consecutive
 considering
-consist
 constr
 constrains
 consts
 contract
-conversion
 conversions
 coo
 corge
 corners
-costly
 cov
-coverage
 coverages
 cp
 csi
-ct3a
-ct3b
-ct4a
-ct4b
+ct
 ctrl
 cumulative
 cursor
 cuts
 cx
-d1a
-d1b
 da
 dacoharkes
 dadd
@@ -251,7 +166,8 @@
 dartfmt
 darttest
 dash
-dashes
+datatype
+datatypes
 day
 days
 db
@@ -262,8 +178,6 @@
 decrease
 decrements
 dectcem
-deduplication
-defaulting
 defintions
 deleting
 denylist
@@ -272,16 +186,13 @@
 desc
 descending
 descriptors
-detector
 deviation
 dfast
 di
 diagnosticable
 dictionaries
 dictionary
-differences
 differentiate
-differs
 dijkstra
 dijkstras
 dillfile
@@ -289,7 +200,6 @@
 dirname
 disagree
 disagreement
-disallowed
 disconnect
 discovering
 discrepancies
@@ -306,32 +216,30 @@
 doo
 downstream
 draw
+dry
 dsemi
 dumping
 dumps
 dupe
 durations
 dw
-dyn
 e's
-e2e
+ea
 ease
 ec
 echo
 edits
+ei
 einst
 elapse
 elegantly
 ell
 emethod
-enters
-entrypoint
 entrypoints
 eoo
 epoch
-equivalences
+equally
 erase
-erased
 err
 esc
 estat
@@ -341,72 +249,21 @@
 exceed
 excess
 exe
-execute
 exercised
 exercises
-existence
 exitcode
 exiting
 expanded
 expansive
 explainer
 extern
-f1
-f1a
-f1b
-f1c
-f1d
-f1e
-f1f
-f1g
-f1h
-f1i
-f2
-f2a
-f2b
-f2c
-f2d
-f2e
-f2f
-f2g
-f2h
-f2i
-f3
-f3a
-f3b
-f3c
-f3d
-f3e
-f3f
-f4
-f4a
-f4b
-f4c
-f4d
-f4e
-f4f
-f5a
-f5b
-f6a
-f6b
-f7a
-f8a
-f8b
+f\u
 fac
 faking
 falling
 favors
 fi
 fibonacci
-field1c
-field2a
-field2b
-field2c
-field3a
-field3b
-field3c
-field4a
-field4b
 filesystem
 filler
 filters
@@ -414,38 +271,7 @@
 five
 floor
 fluctuate
-foo"bar"baz
 foo'bar'baz
-foo1
-foo10
-foo12
-foo13
-foo14
-foo15
-foo1a
-foo1b
-foo2
-foo2a
-foo2b
-foo3a
-foo3b
-foo4
-foo4a
-foo4b
-foo5
-foo5a
-foo5b
-foo6
-foo6a
-foo6b
-foo7
-foo7a
-foo7b
-foo8
-foo9
-foo\"bar'baz
-foo\"bar\"baz
-foo\"bar\'baz
 foos
 forbidden
 forces
@@ -454,6 +280,7 @@
 forty
 foundation
 fox
+frequency
 frozen
 fulfill
 func
@@ -463,23 +290,14 @@
 fuzzed
 fuzzing
 fx
-g1a
-g1b
-g1c
-g2a
-g2b
-g2c
-g3a
-g3b
 gallery
 gamma
 gave
 gc
 gcd
 gesture
-getter1c
-getter1d
-getter1e
+gi
+gm
 goo
 google
 graphic
@@ -488,28 +306,14 @@
 gtgt
 gulp
 gunk
-h1a
-h1b
-h1c
-h2a
-h2b
-h2c
-h3a
-h3b
-h4a
-h4b
-h5a
-h5b
-h6a
-h6b
 hackish
 hardly
-helper2
 hest
 heuristics
 hi
 hints
 hits
+hkt
 home
 hoo
 hook
@@ -520,11 +324,7 @@
 hunk
 hurray
 i'm
-i2a
-i3a
-i3b
 ia
-ideal
 identification
 idle
 ikg
@@ -534,57 +334,27 @@
 implementor
 implementors
 imprecision
-in1
-in2
 inclosure
 inconsistencies
-increased
+increasing
 incrementally
 increments
 indents
 ing
-initializer2
 inlinable
 inlineable
-inlines
 insights
-instance2
 instrument
 insufficient
 intdiv
 interactive
 interchangeable
-interested
 internet
 interpolate
 introducer
 inv
-invocation1a
-invocation1b
-invocation2a
-invocation2b
-invocation3a
-invocation3b
-invocation4a
-invocation4b
-invocation5a
-invocation5b
-invocation6a
-invocation6b
-invocation7a
-invocation7b
-invocation7c
-invocation7d
-invocation7e
 ioo
 ish
-isolate
-isolates
-issue41210b
-issue41436c
-issue41496b
-issue41498b
-issue41499b
 it'll
 italic
 iter
@@ -592,73 +362,36 @@
 joo
 jumped
 kernels
-kill
 kitty
 ko
 koo
 la
 launch
 launching
-layered
-layers
+law
 le
 legs
 lengths
-lib2a
-lib2b
 lightly
 likewise
 lily
 linebreaks
 lints
-linux
 listening
 listing
-literal2
 ln
-local1a
-local1b
-local1c
-local1d
-local1e
-local1f
-local1g
-local1h
-local1i
-local2a
-local2b
-local2c
-local2d
-local2e
-local2f
-local2g
-local2h
-local3a
-local3b
-local3c
-local3d
-local3e
-local3f
-local3g
-local3h
 logd
 logs
 loo
 lookahead
 loopback
 mac
-macro
-macro2a
-macro2b
-macros
 maker
 matters
 mds
 meaningless
 measured
-method1d
-metric
-metrics
+measurement
 mf
 mfs
 micro
@@ -668,6 +401,7 @@
 minst
 mintty
 minutes
+mis
 mismatched
 misnamed
 miss
@@ -675,8 +409,6 @@
 misspelled
 mistake
 mistakes
-mixin1
-mixin2
 mmethod
 mod
 modelled
@@ -688,22 +420,19 @@
 mx
 mxn
 mysdk
-n1a
-n1b
 naively
 naturally
 negatable
 newworld
-nil
 ninja
 noisy
 nominal
-nominality
 nondefault
 nonexisting
 noo
 noted
 nottest
+null'ed
 numerator
 ob
 obool
@@ -723,10 +452,8 @@
 ops
 optimal
 oracle
-out1
-out2
 outbound
-outlined
+outliers
 overhead
 overlay
 overly
@@ -736,6 +463,7 @@
 paint
 parallax
 parameterized
+partfoo
 party
 pause
 paused
@@ -748,7 +476,6 @@
 placement
 planned
 plug
-pointed
 policy
 pooled
 population
@@ -758,24 +485,15 @@
 prematurely
 press
 pretends
+printouts
 processes
 processors
 producer
 profile
 profiler
-propagated
-property2a
-property2b
-property4a
-property4b
-property5a
-property5b
-property8a
-property8b
 proportional
 protected
 proved
-provider
 proxy
 pseudocode
 pubspec
@@ -788,38 +506,22 @@
 quot
 quux
 quuz
-qux
-qux1
-qux3x
-qux4x
-r"
-r"\s
-r"k
-r"tools
-rd
-reachability
 reality
-recompile
 recompiles
-recorder
 redir
 redirections
 rediscover
 reducer
 reenable
 referential
-referring
-reflectee
 refusing
 regards
 regenerate
 regressions
 reify
 reject
-reload
 remap
 remaps
-renames
 rendition
 reorder
 reordering
@@ -827,13 +529,9 @@
 repro
 reproduce
 reproduction
-response
-result1
-result2
 resuming
 retaining
 retainingpath
-retains
 rev
 revealed
 risky
@@ -842,10 +540,10 @@
 rows
 runtimes
 rv
-sandboxed
 sanitize
 saves
 scans
+scenarios
 scheduler
 screen
 scripts
@@ -853,18 +551,13 @@
 sdkroot
 sdks
 secondary
-secondtest12part1usage
+secondtest
 segment
 selection
 semifuzz
 sensitive
-serves
+series
 services
-setter1a
-setter1b
-setter1c
-setter1d
-setter1e
 setups
 severe
 sheets
@@ -873,7 +566,6 @@
 shot
 sidebar
 sigint
-signaling
 signalled
 sigwinch
 slashes
@@ -884,7 +576,6 @@
 somehow
 sorter
 spans
-spawn
 spell
 spellcheck
 spelled
@@ -904,7 +595,6 @@
 stay
 std
 stress
-string2
 stringy
 strip
 strongest
@@ -915,41 +605,18 @@
 subfolder
 subtool
 subtools
-subtyping1a
-subtyping1b
-subtyping2a
-subtyping2b
 successes
-suite
 summarization
 summarized
 sup
 supermixin
 supplement
 suspension
-symbolic
-t3a
-t3b
-t4a
-t4b
 t\b\f\u
-t\u0008\f\u
+t\u
+ta
 tails
-talk
 templates
-test10
-test12
-test12part1usage
-test13
-test13andahalf
-test15thing
-test16
-test16toplevel
-test3a
-test3b
-test3partfoo
-test8
-test9
 theoretically
 thereof
 thread
@@ -971,15 +638,16 @@
 trimming
 tripped
 tripping
-trivially
 truncated
 tt
+tta
 ttest
+ttta
+tttta
 txt
 typeargs
 typeparam
 typeparambounds
-u250c
 ugly
 unassignment
 unawaited
@@ -1000,33 +668,23 @@
 unversioned
 upload
 upward
-usages
-uses8
 uuid
-v1
-v2
 val
-vars
 verbatim
 versioned
 vf
-visitor0
-visitor1
 vp
 vt
 vte
 waited
-waiting
 waits
 walt
-wants
 warmup
 week
 weekly
 wherever
 whiskers
 wins
-wise
 wording
 workflow
 worlds
@@ -1043,5 +701,6 @@
 year
 yxxx
 yy
+zipf's
 zyx
 zz
diff --git a/pkg/front_end/test/spell_checking_utils.dart b/pkg/front_end/test/spell_checking_utils.dart
index 19347ef..072a3f2 100644
--- a/pkg/front_end/test/spell_checking_utils.dart
+++ b/pkg/front_end/test/spell_checking_utils.dart
@@ -188,9 +188,10 @@
   String regExpStringInner = r"\s-=\|\/,";
   if (splitAsCode) {
     // If splitting as code also split by "_", ":", ".", "(", ")", "<", ">",
-    // "[", "]", "{", "}", "@", "&", "#", "?", "%", "`".
+    // "[", "]", "{", "}", "@", "&", "#", "?", "%", "`", '"', and numbers.
     // (As well as doing stuff to camel casing further below).
-    regExpStringInner = "${regExpStringInner}_:\\.\\(\\)<>\\[\\]\{\}@&#\\?%`";
+    regExpStringInner =
+        "${regExpStringInner}_:\\.\\(\\)<>\\[\\]\{\}@&#\\?%`\"0123456789";
   }
   // Match one or more of the characters specified above.
   String regExp = "[$regExpStringInner]+";
diff --git a/pkg/front_end/test/spell_checking_utils_test.dart b/pkg/front_end/test/spell_checking_utils_test.dart
index b91ed891..c4aa4dc 100644
--- a/pkg/front_end/test/spell_checking_utils_test.dart
+++ b/pkg/front_end/test/spell_checking_utils_test.dart
@@ -57,7 +57,7 @@
       ["Platform", "environment", "TERM"], [0, 9, 22]);
 
   expectSplit("DART2JS_PLATFORM", false, ["DART2JS_PLATFORM"], [0]);
-  expectSplit("DART2JS_PLATFORM", true, ["DART2JS", "PLATFORM"], [0, 8]);
+  expectSplit("DART2JS_PLATFORM", true, ["DART", "JS", "PLATFORM"], [0, 5, 8]);
 
   expectSplit("Foo\\n", false, ["Foo\\n"], [0]);
   expectSplit("Foo\\n", true, ["Foo"], [0]);
@@ -80,6 +80,12 @@
   expectSplit("foo%bar", false, ["foo%bar"], [0]);
   expectSplit("foo%bar", true, ["foo", "bar"], [0, 4]);
 
+  expectSplit("foo42bar", false, ["foo42bar"], [0]);
+  expectSplit("foo42bar", true, ["foo", "bar"], [0, 5]);
+
+  expectSplit('foo"bar', false, ['foo"bar'], [0]);
+  expectSplit('foo"bar', true, ["foo", "bar"], [0, 4]);
+
   expectAlternative(
       "explicitley", ["explicitly"], {"foo", "explicitly", "bar"});
   expectAlternative("explicitlqqqqy", null, {"foo", "explicitly", "bar"});
diff --git a/pkg/front_end/test/static_types/static_type_test.dart b/pkg/front_end/test/static_types/static_type_test.dart
index cf4d5c3..80a339d 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -39,24 +39,19 @@
   ///
   /// Fills [actualMap] with the data.
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new StaticTypeDataExtractor(compilerResult, actualMap)
+    new StaticTypeDataExtractor(testResultData.compilerResult, actualMap)
         .computeForLibrary(library);
   }
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    member.accept(new StaticTypeDataExtractor(compilerResult, actualMap));
+    member.accept(
+        new StaticTypeDataExtractor(testResultData.compilerResult, actualMap));
   }
 
   @override
diff --git a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
index 4fd6fa1..b5fffb7 100644
--- a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
@@ -2,11 +2,24 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/util/libraries_specification.dart';
 import 'package:expect/expect.dart';
+import 'package:front_end/src/base/processed_options.dart';
+import 'package:front_end/src/fasta/builder/type_alias_builder.dart';
+import 'package:front_end/src/fasta/compiler_context.dart';
+import 'package:front_end/src/fasta/dill/dill_library_builder.dart';
+import 'package:front_end/src/fasta/dill/dill_loader.dart';
+import 'package:front_end/src/fasta/dill/dill_target.dart';
+import 'package:front_end/src/fasta/dill/dill_type_alias_builder.dart';
 import 'package:front_end/src/fasta/kernel/collections.dart';
 import 'package:front_end/src/fasta/kernel/forest.dart';
 import 'package:front_end/src/fasta/kernel/internal_ast.dart';
+import 'package:front_end/src/fasta/ticker.dart';
+import 'package:front_end/src/fasta/uri_translator.dart';
 import 'package:kernel/ast.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:package_config/package_config.dart';
+
 import 'text_representation_test.dart';
 
 void testStatement(Statement node, String normal,
@@ -32,66 +45,71 @@
 final Uri dummyUri = Uri.parse('test:dummy');
 
 void main() {
-  _testVariableDeclarations();
-  _testTryStatement();
-  _testForInStatementWithSynthesizedVariable();
-  _testSwitchCaseImpl();
-  _testBreakStatementImpl();
-  _testCascade();
-  _testDeferredCheck();
-  _testFactoryConstructorInvocationJudgment();
-  _testFunctionDeclarationImpl();
-  _testIfNullExpression();
-  _testIntLiterals();
-  _testInternalMethodInvocation();
-  _testInternalPropertyGet();
-  _testInternalPropertySet();
-  _testExpressionInvocation();
-  _testNamedFunctionExpressionJudgment();
-  _testNullAwareMethodInvocation();
-  _testNullAwarePropertyGet();
-  _testNullAwarePropertySet();
-  _testReturnStatementImpl();
-  _testVariableDeclarationImpl();
-  _testVariableGetImpl();
-  _testLoadLibraryImpl();
-  _testLoadLibraryTearOff();
-  _testIfNullPropertySet();
-  _testIfNullSet();
-  _testCompoundExtensionSet();
-  _testCompoundPropertySet();
-  _testPropertyPostIncDec();
-  _testLocalPostIncDec();
-  _testStaticPostIncDec();
-  _testSuperPostIncDec();
-  _testIndexGet();
-  _testIndexSet();
-  _testSuperIndexSet();
-  _testExtensionIndexSet();
-  _testIfNullIndexSet();
-  _testIfNullSuperIndexSet();
-  _testIfNullExtensionIndexSet();
-  _testCompoundIndexSet();
-  _testNullAwareCompoundSet();
-  _testNullAwareIfNullSet();
-  _testCompoundSuperIndexSet();
-  _testCompoundExtensionIndexSet();
-  _testExtensionSet();
-  _testNullAwareExtension();
-  _testPropertySetImpl();
-  _testExtensionTearOff();
-  _testEqualsExpression();
-  _testBinaryExpression();
-  _testUnaryExpression();
-  _testParenthesizedExpression();
-  _testSpreadElement();
-  _testIfElement();
-  _testForElement();
-  _testForInElement();
-  _testSpreadMapEntry();
-  _testIfMapEntry();
-  _testForMapEntry();
-  _testForInMapEntry();
+  CompilerContext.runWithOptions(new ProcessedOptions(inputs: [dummyUri]),
+      (_) async {
+    _testVariableDeclarations();
+    _testTryStatement();
+    _testForInStatementWithSynthesizedVariable();
+    _testSwitchCaseImpl();
+    _testBreakStatementImpl();
+    _testCascade();
+    _testDeferredCheck();
+    _testFactoryConstructorInvocationJudgment();
+    _testTypeAliasedConstructorInvocation();
+    _testTypeAliasedFactoryInvocation();
+    _testFunctionDeclarationImpl();
+    _testIfNullExpression();
+    _testIntLiterals();
+    _testInternalMethodInvocation();
+    _testInternalPropertyGet();
+    _testInternalPropertySet();
+    _testExpressionInvocation();
+    _testNamedFunctionExpressionJudgment();
+    _testNullAwareMethodInvocation();
+    _testNullAwarePropertyGet();
+    _testNullAwarePropertySet();
+    _testReturnStatementImpl();
+    _testVariableDeclarationImpl();
+    _testVariableGetImpl();
+    _testLoadLibraryImpl();
+    _testLoadLibraryTearOff();
+    _testIfNullPropertySet();
+    _testIfNullSet();
+    _testCompoundExtensionSet();
+    _testCompoundPropertySet();
+    _testPropertyPostIncDec();
+    _testLocalPostIncDec();
+    _testStaticPostIncDec();
+    _testSuperPostIncDec();
+    _testIndexGet();
+    _testIndexSet();
+    _testSuperIndexSet();
+    _testExtensionIndexSet();
+    _testIfNullIndexSet();
+    _testIfNullSuperIndexSet();
+    _testIfNullExtensionIndexSet();
+    _testCompoundIndexSet();
+    _testNullAwareCompoundSet();
+    _testNullAwareIfNullSet();
+    _testCompoundSuperIndexSet();
+    _testCompoundExtensionIndexSet();
+    _testExtensionSet();
+    _testNullAwareExtension();
+    _testPropertySetImpl();
+    _testExtensionTearOff();
+    _testEqualsExpression();
+    _testBinaryExpression();
+    _testUnaryExpression();
+    _testParenthesizedExpression();
+    _testSpreadElement();
+    _testIfElement();
+    _testForElement();
+    _testForInElement();
+    _testSpreadMapEntry();
+    _testIfMapEntry();
+    _testForMapEntry();
+    _testForInMapEntry();
+  });
 }
 
 void _testVariableDeclarations() {
@@ -355,6 +373,147 @@
 new library test:dummy::Class<void>.foo(0, bar: 1)''');
 }
 
+void _testTypeAliasedConstructorInvocation() {
+  DillTarget dillTarget = new DillTarget(
+      new Ticker(),
+      new UriTranslator(
+          new TargetLibrariesSpecification('dummy'), new PackageConfig([])),
+      new NoneTarget(new TargetFlags()));
+  DillLoader dillLoader = new DillLoader(dillTarget);
+  Library library = new Library(dummyUri, fileUri: dummyUri);
+  Class cls = new Class(name: 'Class', fileUri: dummyUri);
+  library.addClass(cls);
+  Constructor constructor = new Constructor(new FunctionNode(null),
+      name: new Name(''), fileUri: dummyUri);
+  cls.addConstructor(constructor);
+  DillLibraryBuilder libraryBuilder =
+      new DillLibraryBuilder(library, dillLoader);
+  Typedef typedef = new Typedef(
+      'Typedef', new InterfaceType(cls, Nullability.nonNullable),
+      fileUri: dummyUri);
+  library.addTypedef(typedef);
+  TypeAliasBuilder typeAliasBuilder =
+      new DillTypeAliasBuilder(typedef, null, libraryBuilder);
+
+  testExpression(
+      new TypeAliasedConstructorInvocation(
+          typeAliasBuilder, constructor, new ArgumentsImpl([])),
+      '''
+new Typedef()''',
+      verbose: '''
+new library test:dummy::Typedef()''');
+
+  testExpression(
+      new TypeAliasedConstructorInvocation(
+          typeAliasBuilder,
+          constructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))])),
+      '''
+new Typedef<void>(0, bar: 1)''',
+      verbose: '''
+new library test:dummy::Typedef<void>(0, bar: 1)''');
+
+  constructor.name = new Name('foo');
+  testExpression(
+      new TypeAliasedConstructorInvocation(
+          typeAliasBuilder,
+          constructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))])),
+      '''
+new Typedef<void>.foo(0, bar: 1)''',
+      verbose: '''
+new library test:dummy::Typedef<void>.foo(0, bar: 1)''');
+
+  constructor.name = new Name('foo');
+  testExpression(
+      new TypeAliasedConstructorInvocation(
+          typeAliasBuilder,
+          constructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))]),
+          isConst: true),
+      '''
+const Typedef<void>.foo(0, bar: 1)''',
+      verbose: '''
+const library test:dummy::Typedef<void>.foo(0, bar: 1)''');
+}
+
+void _testTypeAliasedFactoryInvocation() {
+  DillTarget dillTarget = new DillTarget(
+      new Ticker(),
+      new UriTranslator(
+          new TargetLibrariesSpecification('dummy'), new PackageConfig([])),
+      new NoneTarget(new TargetFlags()));
+  DillLoader dillLoader = new DillLoader(dillTarget);
+  Library library = new Library(dummyUri, fileUri: dummyUri);
+  Class cls = new Class(name: 'Class', fileUri: dummyUri);
+  library.addClass(cls);
+  Procedure factoryConstructor = new Procedure(
+      new Name(''), ProcedureKind.Factory, new FunctionNode(null),
+      fileUri: dummyUri);
+  cls.addProcedure(factoryConstructor);
+  DillLibraryBuilder libraryBuilder =
+      new DillLibraryBuilder(library, dillLoader);
+  Typedef typedef = new Typedef(
+      'Typedef', new InterfaceType(cls, Nullability.nonNullable),
+      fileUri: dummyUri);
+  library.addTypedef(typedef);
+  TypeAliasBuilder typeAliasBuilder =
+      new DillTypeAliasBuilder(typedef, null, libraryBuilder);
+
+  testExpression(
+      new TypeAliasedFactoryInvocation(
+          typeAliasBuilder, factoryConstructor, new ArgumentsImpl([])),
+      '''
+new Typedef()''',
+      verbose: '''
+new library test:dummy::Typedef()''');
+
+  testExpression(
+      new TypeAliasedFactoryInvocation(
+          typeAliasBuilder,
+          factoryConstructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))])),
+      '''
+new Typedef<void>(0, bar: 1)''',
+      verbose: '''
+new library test:dummy::Typedef<void>(0, bar: 1)''');
+
+  factoryConstructor.name = new Name('foo');
+  testExpression(
+      new TypeAliasedFactoryInvocation(
+          typeAliasBuilder,
+          factoryConstructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))])),
+      '''
+new Typedef<void>.foo(0, bar: 1)''',
+      verbose: '''
+new library test:dummy::Typedef<void>.foo(0, bar: 1)''');
+
+  factoryConstructor.name = new Name('foo');
+  testExpression(
+      new TypeAliasedFactoryInvocation(
+          typeAliasBuilder,
+          factoryConstructor,
+          new ArgumentsImpl([new IntLiteral(0)],
+              types: [const VoidType()],
+              named: [new NamedExpression('bar', new IntLiteral(1))]),
+          isConst: true),
+      '''
+const Typedef<void>.foo(0, bar: 1)''',
+      verbose: '''
+const library test:dummy::Typedef<void>.foo(0, bar: 1)''');
+}
+
 void _testFunctionDeclarationImpl() {
   testStatement(
       new FunctionDeclarationImpl(new VariableDeclarationImpl('foo', 0),
diff --git a/pkg/front_end/test/text_representation/text_representation_test.dart b/pkg/front_end/test/text_representation/text_representation_test.dart
index b29f7ac..24e5246 100644
--- a/pkg/front_end/test/text_representation/text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/text_representation_test.dart
@@ -96,26 +96,22 @@
   const TextRepresentationDataComputer();
 
   @override
-  void computeLibraryData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Library library,
+  void computeLibraryData(TestResultData testResultData, Library library,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
-    new TextRepresentationDataExtractor(
-            compilerResult, actualMap, getStrategy(config.marker))
+    new TextRepresentationDataExtractor(testResultData.compilerResult,
+            actualMap, getStrategy(testResultData.config.marker))
         .computeForLibrary(library);
   }
 
   @override
-  void computeMemberData(
-      TestConfig config,
-      InternalCompilerResult compilerResult,
-      Member member,
+  void computeMemberData(TestResultData testResultData, Member member,
       Map<Id, ActualData<String>> actualMap,
       {bool? verbose}) {
     member.accept(new TextRepresentationDataExtractor(
-        compilerResult, actualMap, getStrategy(config.marker)));
+        testResultData.compilerResult,
+        actualMap,
+        getStrategy(testResultData.config.marker)));
   }
 
   @override
diff --git a/pkg/front_end/test/tool/reload.dart b/pkg/front_end/test/tool/reload.dart
index 887ed3b..15142ec 100644
--- a/pkg/front_end/test/tool/reload.dart
+++ b/pkg/front_end/test/tool/reload.dart
@@ -55,14 +55,26 @@
 
   /// Retrieves the ID of the main isolate using the service protocol.
   Future<String> _computeMainId() async {
-    var vm = await rpc.sendRequest('getVM');
+    var completer = new Completer<String>();
+    rpc.registerMethod('streamNotify', (response) {
+      if (response['streamId'] == 'Isolate') return;
+      var event = response['event'];
+      if (event['kind'] != 'IsolateStart') return;
+      var isolate = event['isolate'];
+      completer.complete(isolate['id']);
+    });
+    await rpc.sendRequest('streamListen', {'streamId': 'Isolate'});
+    var vm = await rpc.sendRequest('getVM', {});
     var isolates = vm['isolates'];
     for (var isolate in isolates) {
       if (isolate['name'].contains(r'$main')) {
         return isolate['id'];
       }
     }
-    return isolates.first['id'];
+    for (var isolate in isolates) {
+      return isolate['id'];
+    }
+    return completer.future;
   }
 
   /// Send a request to the VM to reload sources from [entryUri].
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/named_mixin_application.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/named_mixin_application.dart.weak.outline.expect
index 37b4b1f..dfa0d03 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/named_mixin_application.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/named_mixin_application.dart.weak.outline.expect
@@ -34,7 +34,7 @@
 abstract class Mixin<S extends core::Object? = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
 class NamedMixinApplication<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::Class<self::NamedMixinApplication::T%> with self::Mixin<self::NamedMixinApplication::S%> {
-  synthetic constructor •([core::int field]) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
+  synthetic constructor •([core::int field = 0]) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
     : super self::Class::•(field)
     ;
   synthetic constructor named(core::int field) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
@@ -51,7 +51,7 @@
     return new self::NamedMixinApplication::redirectingGenerative<self::NamedMixinApplication::_#redirectingGenerative#tearOff::T%, self::NamedMixinApplication::_#redirectingGenerative#tearOff::S%>(field);
 }
 abstract class AbstractNamedMixinApplication<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::Class<self::AbstractNamedMixinApplication::T%> with self::Mixin<self::AbstractNamedMixinApplication::S%> {
-  synthetic constructor •([core::int field]) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
+  synthetic constructor •([core::int field = 0]) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
     : super self::Class::•(field)
     ;
   synthetic constructor named(core::int field) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
diff --git a/pkg/front_end/testcases/constructor_tearoffs/named_mixin_application.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/named_mixin_application.dart.weak.outline.expect
index c282d10..16c614a 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/named_mixin_application.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/named_mixin_application.dart.weak.outline.expect
@@ -24,7 +24,7 @@
 abstract class Mixin<S extends core::Object? = dynamic> extends core::Object /*isMixinDeclaration*/  {
 }
 class NamedMixinApplication<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::Class<self::NamedMixinApplication::T%> with self::Mixin<self::NamedMixinApplication::S%> {
-  synthetic constructor •([core::int field]) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
+  synthetic constructor •([core::int field = 0]) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
     : super self::Class::•(field)
     ;
   synthetic constructor named(core::int field) → self::NamedMixinApplication<self::NamedMixinApplication::T%, self::NamedMixinApplication::S%>
@@ -35,7 +35,7 @@
     ;
 }
 abstract class AbstractNamedMixinApplication<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::Class<self::AbstractNamedMixinApplication::T%> with self::Mixin<self::AbstractNamedMixinApplication::S%> {
-  synthetic constructor •([core::int field]) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
+  synthetic constructor •([core::int field = 0]) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
     : super self::Class::•(field)
     ;
   synthetic constructor named(core::int field) → self::AbstractNamedMixinApplication<self::AbstractNamedMixinApplication::T%, self::AbstractNamedMixinApplication::S%>
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart b/pkg/front_end/testcases/dart2js/conditional_import.dart
index 6122451..58ccbe7 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart
@@ -8,7 +8,11 @@
     if (dart.library.html) "dart:html" as a;
 
 // All three libraries have an HttpRequest class.
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
@@ -20,6 +24,13 @@
 }
 
 testB(b.HttpRequest request) {
+  request.certificate; // error (from dart:io)
+  request.response; // ok (from dart:io and dart:html)
+  request.readyState; // ok (from dart:html)
+  request.hashCode; // ok
+}
+
+testC(c.HttpRequest request) {
   request.certificate; // error
   request.response; // error
   request.readyState; // error
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.expect
index 5f33ec1..560176d 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,12 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
+import "dart:_interceptors" as _in;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +48,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
-  request.{core::Object::hashCode}{core::int};
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +88,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +98,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.transformed.expect
index 5f33ec1..560176d 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.strong.transformed.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,12 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
+import "dart:_interceptors" as _in;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +48,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
-  request.{core::Object::hashCode}{core::int};
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +88,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +98,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline.expect
index dc10727..a62da80 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline.expect
@@ -1,11 +1,15 @@
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline_modelled.expect
index 6e90f3d..7af9c6f 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.textual_outline_modelled.expect
@@ -1,4 +1,7 @@
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
@@ -8,4 +11,5 @@
 expect(expected, actual) {}
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.expect
index 5f33ec1..560176d 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,12 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
+import "dart:_interceptors" as _in;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +48,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
-  request.{core::Object::hashCode}{core::int};
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +88,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +98,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.modular.expect
index 5f33ec1..560176d 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.modular.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,12 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
+import "dart:_interceptors" as _in;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +48,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
-  request.{core::Object::hashCode}{core::int};
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +88,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +98,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.outline.expect
index 8e7ea0f..b5be69a 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.outline.expect
@@ -1,10 +1,11 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -12,9 +13,11 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic
+static method testA(html::HttpRequest request) → dynamic
   ;
-static method testB(self::HttpRequest request) → dynamic
+static method testB(html::HttpRequest request) → dynamic
+  ;
+static method testC(self::HttpRequest request) → dynamic
   ;
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.transformed.expect
index 5f33ec1..560176d 100644
--- a/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/conditional_import.dart.weak.transformed.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,12 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
+import "dart:_interceptors" as _in;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +48,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
-  request.{core::Object::hashCode}{core::int};
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{_in::Interceptor::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dart2js/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dart2js/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +88,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +98,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dart2js/mixin_default_values/main.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/mixin_default_values/main.dart.weak.outline.expect
index 2950126..60cff2d 100644
--- a/pkg/front_end/testcases/dart2js/mixin_default_values/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dart2js/mixin_default_values/main.dart.weak.outline.expect
@@ -18,10 +18,10 @@
 import "org-dartlang-testcase:///m_lib.dart";
 
 abstract class _B&A&M = a_l::A with m_l::M /*isAnonymousMixin*/  {
-  synthetic constructor •({core::double d, (core::String) → core::String s}) → self2::_B&A&M
+  synthetic constructor •({core::double d = #C1, (core::String) → core::String s = #C2}) → self2::_B&A&M
     : super a_l::A::•(d: d, s: s)
     ;
-  synthetic constructor factoryConstructor({core::double d, (core::String) → core::String s}) → self2::_B&A&M
+  synthetic constructor factoryConstructor({core::double d = #C1, (core::String) → core::String s = #C2}) → self2::_B&A&M
     : super a_l::A::factoryConstructor(d: d, s: s)
     ;
   mixin-super-stub method m1() → dynamic
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart b/pkg/front_end/testcases/dartdevc/conditional_import.dart
index 6122451..58ccbe7 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart
@@ -8,7 +8,11 @@
     if (dart.library.html) "dart:html" as a;
 
 // All three libraries have an HttpRequest class.
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
@@ -20,6 +24,13 @@
 }
 
 testB(b.HttpRequest request) {
+  request.certificate; // error (from dart:io)
+  request.response; // ok (from dart:io and dart:html)
+  request.readyState; // ok (from dart:html)
+  request.hashCode; // ok
+}
+
+testC(c.HttpRequest request) {
   request.certificate; // error
   request.response; // error
   request.readyState; // error
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.expect
index 3b668f7..efcac9a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,11 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +47,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +87,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +97,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.transformed.expect
index 3b668f7..efcac9a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.strong.transformed.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,11 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +47,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +87,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +97,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline.expect
index dc10727..a62da80 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline.expect
@@ -1,11 +1,15 @@
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline_modelled.expect
index 6e90f3d..7af9c6f 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.textual_outline_modelled.expect
@@ -1,4 +1,7 @@
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
@@ -8,4 +11,5 @@
 expect(expected, actual) {}
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.expect
index 3b668f7..efcac9a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,11 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +47,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +87,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +97,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.modular.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.modular.expect
index 3b668f7..efcac9a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.modular.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,11 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +47,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +87,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +97,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.outline.expect
index 8e7ea0f..b5be69a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.outline.expect
@@ -1,10 +1,11 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -12,9 +13,11 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic
+static method testA(html::HttpRequest request) → dynamic
   ;
-static method testB(self::HttpRequest request) → dynamic
+static method testB(html::HttpRequest request) → dynamic
+  ;
+static method testC(self::HttpRequest request) → dynamic
   ;
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.transformed.expect
index 3b668f7..efcac9a 100644
--- a/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/conditional_import.dart.weak.transformed.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
-//  - 'HttpRequest' is from 'dart:_http'.
-// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-//   request.readyState; // ok (from dart:html)
-//           ^^^^^^^^^^
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:html'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+//   request.certificate; // error (from dart:io)
+//           ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -28,11 +34,11 @@
 //
 import self as self;
 import "dart:core" as core;
-import "dart:_http" as _ht;
-import "dart:io" as io;
+import "dart:html" as html;
 
-import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:html" as a;
+import "dart:html" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -41,28 +47,38 @@
   static method _#new#tearOff() → self::HttpRequest
     return new self::HttpRequest::•();
 }
-static method testA(_ht::HttpRequest request) → dynamic {
-  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
-  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
- - 'HttpRequest' is from 'dart:_http'.
-Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
-  request.readyState; // ok (from dart:html)
-          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+static method testA(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:20:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(html::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:27:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:html'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
+  request.certificate; // error (from dart:io)
+          ^^^^^^^^^^^" in request{<unresolved>}.certificate;
+  request.{html::HttpRequest::response}{dynamic};
+  request.{html::HttpRequest::readyState}{core::int};
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/dartdevc/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/dartdevc/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -71,7 +87,7 @@
 }
 static method main() → void {
   self::expect(false, #C1);
-  self::expect(true, #C1);
+  self::expect(true, #C2);
   self::expect(false, #C1);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -81,4 +97,5 @@
 
 constants  {
   #C1 = false
+  #C2 = true
 }
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart
index a645a364..bf5caf0 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart
@@ -5,7 +5,8 @@
 enum E<X, Y> {
   one<int, String>(),
   two<double, num>(),
-  three<int, int>.named(42);
+  three<int, int>.named(42),
+  four<num, bool>; // Error.
 
   const E();
   const E.named(int value);
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.expect
index b4016d7..7321935 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = #C10;
-  static const field self::E one = #C3;
-  static const field self::E two = #C6;
-  static const field self::E three = #C9;
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = #C13;
+  static const field self::E<core::int, core::String> one = #C3;
+  static const field self::E<core::double, core::num> two = #C6;
+  static const field self::E<core::int, core::int> three = #C9;
+  static const field self::E<dynamic, dynamic> four = #C12;
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,19 +29,23 @@
 constants  {
   #C1 = 0
   #C2 = "one"
-  #C3 = self::E {index:#C1, _name:#C2}
+  #C3 = self::E<core::int, core::String> {index:#C1, _name:#C2}
   #C4 = 1
   #C5 = "two"
-  #C6 = self::E {index:#C4, _name:#C5}
+  #C6 = self::E<core::double, core::num> {index:#C4, _name:#C5}
   #C7 = 2
   #C8 = "three"
-  #C9 = self::E {index:#C7, _name:#C8}
-  #C10 = <self::E>[#C3, #C6, #C9]
+  #C9 = self::E<core::int, core::int> {index:#C7, _name:#C8}
+  #C10 = 3
+  #C11 = "four"
+  #C12 = self::E<core::num, core::bool> {index:#C10, _name:#C11}
+  #C13 = <self::E<dynamic, dynamic>>[#C3, #C6, #C9, #C12]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///entries_with_type_arguments.dart:
-- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:5:6)
+- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:11:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E.named (from org-dartlang-testcase:///entries_with_type_arguments.dart:12:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.transformed.expect
index b4016d7..7321935 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.strong.transformed.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = #C10;
-  static const field self::E one = #C3;
-  static const field self::E two = #C6;
-  static const field self::E three = #C9;
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = #C13;
+  static const field self::E<core::int, core::String> one = #C3;
+  static const field self::E<core::double, core::num> two = #C6;
+  static const field self::E<core::int, core::int> three = #C9;
+  static const field self::E<dynamic, dynamic> four = #C12;
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,19 +29,23 @@
 constants  {
   #C1 = 0
   #C2 = "one"
-  #C3 = self::E {index:#C1, _name:#C2}
+  #C3 = self::E<core::int, core::String> {index:#C1, _name:#C2}
   #C4 = 1
   #C5 = "two"
-  #C6 = self::E {index:#C4, _name:#C5}
+  #C6 = self::E<core::double, core::num> {index:#C4, _name:#C5}
   #C7 = 2
   #C8 = "three"
-  #C9 = self::E {index:#C7, _name:#C8}
-  #C10 = <self::E>[#C3, #C6, #C9]
+  #C9 = self::E<core::int, core::int> {index:#C7, _name:#C8}
+  #C10 = 3
+  #C11 = "four"
+  #C12 = self::E<core::num, core::bool> {index:#C10, _name:#C11}
+  #C13 = <self::E<dynamic, dynamic>>[#C3, #C6, #C9, #C12]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///entries_with_type_arguments.dart:
-- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:5:6)
+- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:11:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E.named (from org-dartlang-testcase:///entries_with_type_arguments.dart:12:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.textual_outline.expect
index 4fa6f4d..c2d1e7f 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.textual_outline.expect
@@ -1,2 +1,2 @@
-enum E<X, Y> { one<int, String>(), two<double, num>(), three<int, int>.named(42); const E(); const E.named(int value); }
+enum E<X, Y> { one<int, String>(), two<double, num>(), three<int, int>.named(42), four<num, bool>; const E(); const E.named(int value); }
 main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.expect
index a7d67d3..5598791 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = #C10;
-  static const field self::E one = #C3;
-  static const field self::E two = #C6;
-  static const field self::E three = #C9;
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = #C13;
+  static const field self::E<core::int, core::String> one = #C3;
+  static const field self::E<core::double, core::num> two = #C6;
+  static const field self::E<core::int, core::int> three = #C9;
+  static const field self::E<dynamic, dynamic> four = #C12;
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,19 +29,23 @@
 constants  {
   #C1 = 0
   #C2 = "one"
-  #C3 = self::E {index:#C1, _name:#C2}
+  #C3 = self::E<core::int*, core::String*> {index:#C1, _name:#C2}
   #C4 = 1
   #C5 = "two"
-  #C6 = self::E {index:#C4, _name:#C5}
+  #C6 = self::E<core::double*, core::num*> {index:#C4, _name:#C5}
   #C7 = 2
   #C8 = "three"
-  #C9 = self::E {index:#C7, _name:#C8}
-  #C10 = <self::E*>[#C3, #C6, #C9]
+  #C9 = self::E<core::int*, core::int*> {index:#C7, _name:#C8}
+  #C10 = 3
+  #C11 = "four"
+  #C12 = self::E<core::num*, core::bool*> {index:#C10, _name:#C11}
+  #C13 = <self::E<dynamic, dynamic>*>[#C3, #C6, #C9, #C12]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///entries_with_type_arguments.dart:
-- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:5:6)
+- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:11:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E.named (from org-dartlang-testcase:///entries_with_type_arguments.dart:12:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.modular.expect
index a7d67d3..5598791 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.modular.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = #C10;
-  static const field self::E one = #C3;
-  static const field self::E two = #C6;
-  static const field self::E three = #C9;
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = #C13;
+  static const field self::E<core::int, core::String> one = #C3;
+  static const field self::E<core::double, core::num> two = #C6;
+  static const field self::E<core::int, core::int> three = #C9;
+  static const field self::E<dynamic, dynamic> four = #C12;
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,19 +29,23 @@
 constants  {
   #C1 = 0
   #C2 = "one"
-  #C3 = self::E {index:#C1, _name:#C2}
+  #C3 = self::E<core::int*, core::String*> {index:#C1, _name:#C2}
   #C4 = 1
   #C5 = "two"
-  #C6 = self::E {index:#C4, _name:#C5}
+  #C6 = self::E<core::double*, core::num*> {index:#C4, _name:#C5}
   #C7 = 2
   #C8 = "three"
-  #C9 = self::E {index:#C7, _name:#C8}
-  #C10 = <self::E*>[#C3, #C6, #C9]
+  #C9 = self::E<core::int*, core::int*> {index:#C7, _name:#C8}
+  #C10 = 3
+  #C11 = "four"
+  #C12 = self::E<core::num*, core::bool*> {index:#C10, _name:#C11}
+  #C13 = <self::E<dynamic, dynamic>*>[#C3, #C6, #C9, #C12]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///entries_with_type_arguments.dart:
-- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:5:6)
+- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:11:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E.named (from org-dartlang-testcase:///entries_with_type_arguments.dart:12:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.outline.expect
index 61d174a..c39aa4b 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.outline.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = const <self::E>[self::E::one, self::E::two, self::E::three];
-  static const field self::E one = const self::E::•(0, "one");
-  static const field self::E two = const self::E::•(1, "two");
-  static const field self::E three = const self::E::•(2, "three");
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = const <self::E<dynamic, dynamic>>[self::E::one, self::E::two, self::E::three, self::E::four];
+  static const field self::E<core::int, core::String> one = const self::E::•<core::int, core::String>(0, "one");
+  static const field self::E<core::double, core::num> two = const self::E::•<core::double, core::num>(1, "two");
+  static const field self::E<core::int, core::int> three = const self::E::named<core::int, core::int>(2, "three", 42);
+  static const field self::E<dynamic, dynamic> four = const self::E::•<core::num, core::bool>(3, "four");
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,8 +29,9 @@
 
 
 Extra constant evaluation status:
-Evaluated: ListLiteral @ org-dartlang-testcase:///entries_with_type_arguments.dart:5:6 -> ListConstant(const <E*>[const E{_Enum.index: 0, _Enum._name: "one"}, const E{_Enum.index: 1, _Enum._name: "two"}, const E{_Enum.index: 2, _Enum._name: "three"}])
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:6:3 -> InstanceConstant(const E{_Enum.index: 0, _Enum._name: "one"})
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:7:3 -> InstanceConstant(const E{_Enum.index: 1, _Enum._name: "two"})
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:8:3 -> InstanceConstant(const E{_Enum.index: 2, _Enum._name: "three"})
-Extra constant evaluation: evaluated: 9, effectively constant: 4
+Evaluated: ListLiteral @ org-dartlang-testcase:///entries_with_type_arguments.dart:5:6 -> ListConstant(const <E<dynamic, dynamic>*>[const E<int*, String*>{_Enum.index: 0, _Enum._name: "one"}, const E<double*, num*>{_Enum.index: 1, _Enum._name: "two"}, const E<int*, int*>{_Enum.index: 2, _Enum._name: "three"}, const E<num*, bool*>{_Enum.index: 3, _Enum._name: "four"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:6:3 -> InstanceConstant(const E<int*, String*>{_Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:7:3 -> InstanceConstant(const E<double*, num*>{_Enum.index: 1, _Enum._name: "two"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:8:3 -> InstanceConstant(const E<int*, int*>{_Enum.index: 2, _Enum._name: "three"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///entries_with_type_arguments.dart:9:3 -> InstanceConstant(const E<num*, bool*>{_Enum.index: 3, _Enum._name: "four"})
+Extra constant evaluation: evaluated: 12, effectively constant: 5
diff --git a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.transformed.expect
index a7d67d3..5598791 100644
--- a/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart.weak.transformed.expect
@@ -1,13 +1,24 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/entries_with_type_arguments.dart:9:3: Error: Missing arguments in enum constructor invocation.
+//   four<num, bool>; // Error.
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
-class E extends core::_Enum /*isEnum*/  {
-  static const field core::List<self::E> values = #C10;
-  static const field self::E one = #C3;
-  static const field self::E two = #C6;
-  static const field self::E three = #C9;
-  const constructor •(core::int index, core::String name) → self::E
+class E<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic, dynamic>> values = #C13;
+  static const field self::E<core::int, core::String> one = #C3;
+  static const field self::E<core::double, core::num> two = #C6;
+  static const field self::E<core::int, core::int> three = #C9;
+  static const field self::E<dynamic, dynamic> four = #C12;
+  const constructor •(core::int index, core::String name) → self::E<self::E::X%, self::E::Y%>
+    : super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E<self::E::X%, self::E::Y%>
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -18,19 +29,23 @@
 constants  {
   #C1 = 0
   #C2 = "one"
-  #C3 = self::E {index:#C1, _name:#C2}
+  #C3 = self::E<core::int*, core::String*> {index:#C1, _name:#C2}
   #C4 = 1
   #C5 = "two"
-  #C6 = self::E {index:#C4, _name:#C5}
+  #C6 = self::E<core::double*, core::num*> {index:#C4, _name:#C5}
   #C7 = 2
   #C8 = "three"
-  #C9 = self::E {index:#C7, _name:#C8}
-  #C10 = <self::E*>[#C3, #C6, #C9]
+  #C9 = self::E<core::int*, core::int*> {index:#C7, _name:#C8}
+  #C10 = 3
+  #C11 = "four"
+  #C12 = self::E<core::num*, core::bool*> {index:#C10, _name:#C11}
+  #C13 = <self::E<dynamic, dynamic>*>[#C3, #C6, #C9, #C12]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///entries_with_type_arguments.dart:
-- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:5:6)
+- E. (from org-dartlang-testcase:///entries_with_type_arguments.dart:11:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E.named (from org-dartlang-testcase:///entries_with_type_arguments.dart:12:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart
new file mode 100644
index 0000000..ddee41a
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A extends Enum { // Ok.
+  int get foo => index;
+}
+
+enum EA with A { element }
+
+abstract class B implements Enum { // Ok.
+  int get foo => index;
+}
+
+enum EB with B { element }
+
+mixin M on Enum { // Ok.
+  int get foo => index;
+}
+
+enum EM with M { element }
+
+mixin N implements Enum { // Ok.
+  int get foo => index;
+}
+
+enum EN with N { element }
+
+expectEquals(x, y) {
+  if (x != y) {
+    throw "Expected '$x' to be equal to '$y'.";
+  }
+}
+
+main() {
+  expectEquals(EA.element.foo, EA.element.index);
+  expectEquals(EB.element.foo, EB.element.index);
+  expectEquals(EM.element.foo, EM.element.index);
+  expectEquals(EN.element.foo, EN.element.index);
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.expect
new file mode 100644
index 0000000..95879d2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.expect
@@ -0,0 +1,128 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EA&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::A::foo};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = #C4;
+  static const field self::EA element = #C3;
+  const constructor •(core::int index, core::String name) → self::EA
+    : super self::_EA&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EB&_Enum&B = core::_Enum with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::B::foo};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = #C6;
+  static const field self::EB element = #C5;
+  const constructor •(core::int index, core::String name) → self::EB
+    : super self::_EB&_Enum&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EM&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::M::foo};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = #C8;
+  static const field self::EM element = #C7;
+  const constructor •(core::int index, core::String name) → self::EM
+    : super self::_EM&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EN&_Enum&N = core::_Enum with self::N /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::N::foo};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = #C10;
+  static const field self::EN element = #C9;
+  const constructor •(core::int index, core::String name) → self::EN
+    : super self::_EN&_Enum&N::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' to be equal to '${y}'.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_EA&_Enum&A::foo}{core::int}, #C3.{core::_Enum::index}{core::int});
+  self::expectEquals(#C5.{self::_EB&_Enum&B::foo}{core::int}, #C5.{core::_Enum::index}{core::int});
+  self::expectEquals(#C7.{self::_EM&_Enum&M::foo}{core::int}, #C7.{core::_Enum::index}{core::int});
+  self::expectEquals(#C9.{self::_EN&_Enum&N::foo}{core::int}, #C9.{core::_Enum::index}{core::int});
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::EA {index:#C1, _name:#C2}
+  #C4 = <self::EA>[#C3]
+  #C5 = self::EB {index:#C1, _name:#C2}
+  #C6 = <self::EB>[#C5]
+  #C7 = self::EM {index:#C1, _name:#C2}
+  #C8 = <self::EM>[#C7]
+  #C9 = self::EN {index:#C1, _name:#C2}
+  #C10 = <self::EN>[#C9]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum_as_supertype.dart:
+- EA. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _EA&_Enum&A. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- EB. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- _EB&_Enum&B. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- EM. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- _EM&_Enum&M. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- EN. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
+- _EN&_Enum&N. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.transformed.expect
new file mode 100644
index 0000000..d680f8a
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.strong.transformed.expect
@@ -0,0 +1,128 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EA&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = #C4;
+  static const field self::EA element = #C3;
+  const constructor •(core::int index, core::String name) → self::EA
+    : super self::_EA&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EB&_Enum&B extends core::_Enum implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = #C6;
+  static const field self::EB element = #C5;
+  const constructor •(core::int index, core::String name) → self::EB
+    : super self::_EB&_Enum&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EM&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = #C8;
+  static const field self::EM element = #C7;
+  const constructor •(core::int index, core::String name) → self::EM
+    : super self::_EM&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EN&_Enum&N extends core::_Enum implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = #C10;
+  static const field self::EN element = #C9;
+  const constructor •(core::int index, core::String name) → self::EN
+    : super self::_EN&_Enum&N::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' to be equal to '${y}'.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_EA&_Enum&A::foo}{core::int}, #C3.{core::_Enum::index}{core::int});
+  self::expectEquals(#C5.{self::_EB&_Enum&B::foo}{core::int}, #C5.{core::_Enum::index}{core::int});
+  self::expectEquals(#C7.{self::_EM&_Enum&M::foo}{core::int}, #C7.{core::_Enum::index}{core::int});
+  self::expectEquals(#C9.{self::_EN&_Enum&N::foo}{core::int}, #C9.{core::_Enum::index}{core::int});
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::EA {index:#C1, _name:#C2}
+  #C4 = <self::EA>[#C3]
+  #C5 = self::EB {index:#C1, _name:#C2}
+  #C6 = <self::EB>[#C5]
+  #C7 = self::EM {index:#C1, _name:#C2}
+  #C8 = <self::EM>[#C7]
+  #C9 = self::EN {index:#C1, _name:#C2}
+  #C10 = <self::EN>[#C9]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum_as_supertype.dart:
+- EA. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _EA&_Enum&A. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- EB. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- _EB&_Enum&B. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- EM. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- _EM&_Enum&M. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- EN. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
+- _EN&_Enum&N. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.textual_outline.expect
new file mode 100644
index 0000000..4344750
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+abstract class A extends Enum {
+  int get foo => index;
+}
+enum EA with A { element }
+abstract class B implements Enum {
+  int get foo => index;
+}
+enum EB with B { element }
+mixin M on Enum {
+  int get foo => index;
+}
+enum EM with M { element }
+mixin N implements Enum {
+  int get foo => index;
+}
+enum EN with N { element }
+expectEquals(x, y) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.expect
new file mode 100644
index 0000000..f8907f3
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.expect
@@ -0,0 +1,128 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EA&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::A::foo};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = #C4;
+  static const field self::EA element = #C3;
+  const constructor •(core::int index, core::String name) → self::EA
+    : super self::_EA&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EB&_Enum&B = core::_Enum with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::B::foo};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = #C6;
+  static const field self::EB element = #C5;
+  const constructor •(core::int index, core::String name) → self::EB
+    : super self::_EB&_Enum&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EM&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::M::foo};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = #C8;
+  static const field self::EM element = #C7;
+  const constructor •(core::int index, core::String name) → self::EM
+    : super self::_EM&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EN&_Enum&N = core::_Enum with self::N /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::N::foo};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = #C10;
+  static const field self::EN element = #C9;
+  const constructor •(core::int index, core::String name) → self::EN
+    : super self::_EN&_Enum&N::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' to be equal to '${y}'.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_EA&_Enum&A::foo}{core::int}, #C3.{core::_Enum::index}{core::int});
+  self::expectEquals(#C5.{self::_EB&_Enum&B::foo}{core::int}, #C5.{core::_Enum::index}{core::int});
+  self::expectEquals(#C7.{self::_EM&_Enum&M::foo}{core::int}, #C7.{core::_Enum::index}{core::int});
+  self::expectEquals(#C9.{self::_EN&_Enum&N::foo}{core::int}, #C9.{core::_Enum::index}{core::int});
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::EA {index:#C1, _name:#C2}
+  #C4 = <self::EA*>[#C3]
+  #C5 = self::EB {index:#C1, _name:#C2}
+  #C6 = <self::EB*>[#C5]
+  #C7 = self::EM {index:#C1, _name:#C2}
+  #C8 = <self::EM*>[#C7]
+  #C9 = self::EN {index:#C1, _name:#C2}
+  #C10 = <self::EN*>[#C9]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum_as_supertype.dart:
+- EA. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _EA&_Enum&A. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- EB. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- _EB&_Enum&B. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- EM. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- _EM&_Enum&M. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- EN. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
+- _EN&_Enum&N. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.modular.expect
new file mode 100644
index 0000000..f8907f3
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.modular.expect
@@ -0,0 +1,128 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EA&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::A::foo};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = #C4;
+  static const field self::EA element = #C3;
+  const constructor •(core::int index, core::String name) → self::EA
+    : super self::_EA&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EB&_Enum&B = core::_Enum with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::B::foo};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = #C6;
+  static const field self::EB element = #C5;
+  const constructor •(core::int index, core::String name) → self::EB
+    : super self::_EB&_Enum&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EM&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::M::foo};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = #C8;
+  static const field self::EM element = #C7;
+  const constructor •(core::int index, core::String name) → self::EM
+    : super self::_EM&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EN&_Enum&N = core::_Enum with self::N /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::N::foo};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = #C10;
+  static const field self::EN element = #C9;
+  const constructor •(core::int index, core::String name) → self::EN
+    : super self::_EN&_Enum&N::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' to be equal to '${y}'.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_EA&_Enum&A::foo}{core::int}, #C3.{core::_Enum::index}{core::int});
+  self::expectEquals(#C5.{self::_EB&_Enum&B::foo}{core::int}, #C5.{core::_Enum::index}{core::int});
+  self::expectEquals(#C7.{self::_EM&_Enum&M::foo}{core::int}, #C7.{core::_Enum::index}{core::int});
+  self::expectEquals(#C9.{self::_EN&_Enum&N::foo}{core::int}, #C9.{core::_Enum::index}{core::int});
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::EA {index:#C1, _name:#C2}
+  #C4 = <self::EA*>[#C3]
+  #C5 = self::EB {index:#C1, _name:#C2}
+  #C6 = <self::EB*>[#C5]
+  #C7 = self::EM {index:#C1, _name:#C2}
+  #C8 = <self::EM*>[#C7]
+  #C9 = self::EN {index:#C1, _name:#C2}
+  #C10 = <self::EN*>[#C9]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum_as_supertype.dart:
+- EA. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _EA&_Enum&A. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- EB. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- _EB&_Enum&B. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- EM. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- _EM&_Enum&M. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- EN. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
+- _EN&_Enum&N. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.outline.expect
new file mode 100644
index 0000000..dbfdd01
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.outline.expect
@@ -0,0 +1,100 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    ;
+  get foo() → core::int
+    ;
+}
+abstract class _EA&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::A::foo};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = const <self::EA>[self::EA::element];
+  static const field self::EA element = const self::EA::•(0, "element");
+  const constructor •(core::int index, core::String name) → self::EA
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    ;
+  get foo() → core::int
+    ;
+}
+abstract class _EB&_Enum&B = core::_Enum with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::B::foo};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = const <self::EB>[self::EB::element];
+  static const field self::EB element = const self::EB::•(0, "element");
+  const constructor •(core::int index, core::String name) → self::EB
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    ;
+}
+abstract class _EM&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::M::foo};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = const <self::EM>[self::EM::element];
+  static const field self::EM element = const self::EM::•(0, "element");
+  const constructor •(core::int index, core::String name) → self::EM
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    ;
+}
+abstract class _EN&_Enum&N = core::_Enum with self::N /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::int
+    return super.{self::N::foo};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = const <self::EN>[self::EN::element];
+  static const field self::EN element = const self::EN::•(0, "element");
+  const constructor •(core::int index, core::String name) → self::EN
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///enum_as_supertype.dart:9:6 -> ListConstant(const <EA*>[const EA{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum_as_supertype.dart:9:18 -> InstanceConstant(const EA{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///enum_as_supertype.dart:15:6 -> ListConstant(const <EB*>[const EB{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum_as_supertype.dart:15:18 -> InstanceConstant(const EB{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///enum_as_supertype.dart:21:6 -> ListConstant(const <EM*>[const EM{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum_as_supertype.dart:21:18 -> InstanceConstant(const EM{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///enum_as_supertype.dart:27:6 -> ListConstant(const <EN*>[const EN{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum_as_supertype.dart:27:18 -> InstanceConstant(const EN{})
+Extra constant evaluation: evaluated: 20, effectively constant: 8
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.transformed.expect
new file mode 100644
index 0000000..4417c2a
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype.dart.weak.transformed.expect
@@ -0,0 +1,128 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EA&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EA&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EA extends self::_EA&_Enum&A /*isEnum*/  {
+  static const field core::List<self::EA> values = #C4;
+  static const field self::EA element = #C3;
+  const constructor •(core::int index, core::String name) → self::EA
+    : super self::_EA&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EB&_Enum&B extends core::_Enum implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EB&_Enum&B
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EB extends self::_EB&_Enum&B /*isEnum*/  {
+  static const field core::List<self::EB> values = #C6;
+  static const field self::EB element = #C5;
+  const constructor •(core::int index, core::String name) → self::EB
+    : super self::_EB&_Enum&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class M extends core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EM&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EM&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EM extends self::_EM&_Enum&M /*isEnum*/  {
+  static const field core::List<self::EM> values = #C8;
+  static const field self::EM element = #C7;
+  const constructor •(core::int index, core::String name) → self::EM
+    : super self::_EM&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class N extends core::Object implements core::Enum /*isMixinDeclaration*/  {
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+abstract class _EN&_Enum&N extends core::_Enum implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_EN&_Enum&N
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+}
+class EN extends self::_EN&_Enum&N /*isEnum*/  {
+  static const field core::List<self::EN> values = #C10;
+  static const field self::EN element = #C9;
+  const constructor •(core::int index, core::String name) → self::EN
+    : super self::_EN&_Enum&N::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' to be equal to '${y}'.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_EA&_Enum&A::foo}{core::int}, #C3.{core::_Enum::index}{core::int});
+  self::expectEquals(#C5.{self::_EB&_Enum&B::foo}{core::int}, #C5.{core::_Enum::index}{core::int});
+  self::expectEquals(#C7.{self::_EM&_Enum&M::foo}{core::int}, #C7.{core::_Enum::index}{core::int});
+  self::expectEquals(#C9.{self::_EN&_Enum&N::foo}{core::int}, #C9.{core::_Enum::index}{core::int});
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::EA {index:#C1, _name:#C2}
+  #C4 = <self::EA*>[#C3]
+  #C5 = self::EB {index:#C1, _name:#C2}
+  #C6 = <self::EB*>[#C5]
+  #C7 = self::EM {index:#C1, _name:#C2}
+  #C8 = <self::EM*>[#C7]
+  #C9 = self::EN {index:#C1, _name:#C2}
+  #C10 = <self::EN*>[#C9]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum_as_supertype.dart:
+- EA. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _EA&_Enum&A. (from org-dartlang-testcase:///enum_as_supertype.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- EB. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- _EB&_Enum&B. (from org-dartlang-testcase:///enum_as_supertype.dart:15:6)
+- EM. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- _EM&_Enum&M. (from org-dartlang-testcase:///enum_as_supertype.dart:21:6)
+- EN. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
+- _EN&_Enum&N. (from org-dartlang-testcase:///enum_as_supertype.dart:27:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart
new file mode 100644
index 0000000..8889a45
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 extends Enum { // Error.
+  int get foo => index;
+}
+
+class B implements Enum { // Error.
+  int get foo => index;
+}
+
+abstract class EnumInterface implements Enum {}
+
+class EnumClass extends EnumInterface { // Error.
+  int get index => 0;
+}
+
+abstract class AbstractEnumClass extends EnumInterface {}
+
+class EnumClass2 extends AbstractEnumClass {} // Error.
+
+mixin EnumMixin on Enum {}
+
+abstract class AbstractEnumClass2 with EnumMixin {}
+
+class EnumClass3 extends AbstractEnumClass2 {} // Error.
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.expect
new file mode 100644
index 0000000..99bdbbb
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.expect
@@ -0,0 +1,161 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    : super core::Object::•()
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    : super self::EnumInterface::•()
+    ;
+  get index() → core::int
+    return 0;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    : super self::EnumInterface::•()
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    : super self::AbstractEnumClass::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin = core::Object with self::EnumMixin /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    : super self::_AbstractEnumClass2&Object&EnumMixin::•()
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    : super self::AbstractEnumClass2::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///enum_as_supertype_error.dart::_name
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.transformed.expect
new file mode 100644
index 0000000..9f0c21d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.strong.transformed.expect
@@ -0,0 +1,161 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    : super core::Object::•()
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    : super self::EnumInterface::•()
+    ;
+  get index() → core::int
+    return 0;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    : super self::EnumInterface::•()
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    : super self::AbstractEnumClass::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin extends core::Object implements self::EnumMixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    : super self::_AbstractEnumClass2&Object&EnumMixin::•()
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    : super self::AbstractEnumClass2::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///enum_as_supertype_error.dart::_name
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline.expect
new file mode 100644
index 0000000..91bd71d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class A extends Enum {
+  int get foo => index;
+}
+
+class B implements Enum {
+  int get foo => index;
+}
+
+abstract class EnumInterface implements Enum {}
+
+class EnumClass extends EnumInterface {
+  int get index => 0;
+}
+
+abstract class AbstractEnumClass extends EnumInterface {}
+
+class EnumClass2 extends AbstractEnumClass {}
+
+mixin EnumMixin on Enum {}
+
+abstract class AbstractEnumClass2 with EnumMixin {}
+
+class EnumClass3 extends AbstractEnumClass2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b8f73e5
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+abstract class AbstractEnumClass extends EnumInterface {}
+
+abstract class AbstractEnumClass2 with EnumMixin {}
+
+abstract class EnumInterface implements Enum {}
+
+class A extends Enum {
+  int get foo => index;
+}
+
+class B implements Enum {
+  int get foo => index;
+}
+
+class EnumClass extends EnumInterface {
+  int get index => 0;
+}
+
+class EnumClass2 extends AbstractEnumClass {}
+
+class EnumClass3 extends AbstractEnumClass2 {}
+
+main() {}
+mixin EnumMixin on Enum {}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.expect
new file mode 100644
index 0000000..99bdbbb
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.expect
@@ -0,0 +1,161 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    : super core::Object::•()
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    : super self::EnumInterface::•()
+    ;
+  get index() → core::int
+    return 0;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    : super self::EnumInterface::•()
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    : super self::AbstractEnumClass::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin = core::Object with self::EnumMixin /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    : super self::_AbstractEnumClass2&Object&EnumMixin::•()
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    : super self::AbstractEnumClass2::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///enum_as_supertype_error.dart::_name
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.modular.expect
new file mode 100644
index 0000000..99bdbbb
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.modular.expect
@@ -0,0 +1,161 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    : super core::Object::•()
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    : super self::EnumInterface::•()
+    ;
+  get index() → core::int
+    return 0;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    : super self::EnumInterface::•()
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    : super self::AbstractEnumClass::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin = core::Object with self::EnumMixin /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    : super self::_AbstractEnumClass2&Object&EnumMixin::•()
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    : super self::AbstractEnumClass2::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///enum_as_supertype_error.dart::_name
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.outline.expect
new file mode 100644
index 0000000..75296a2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.outline.expect
@@ -0,0 +1,171 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    ;
+  get foo() → core::int
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#_name, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    ;
+  get foo() → core::int
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#_name, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    ;
+  get index() → core::int
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#_name, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#_name, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin = core::Object with self::EnumMixin /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#_name, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> SymbolConstant(#_name)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> SymbolConstant(#_name)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> SymbolConstant(#_name)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> SymbolConstant(#_name)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> SymbolConstant(#_name)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/core/enum.dart:47:14 -> MapConstant(const <Symbol*, dynamic>{})
+Extra constant evaluation: evaluated: 45, effectively constant: 20
diff --git a/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.transformed.expect
new file mode 100644
index 0000000..9f0c21d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart.weak.transformed.expect
@@ -0,0 +1,161 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: Non-abstract class 'A' has 'Enum' as a superinterface.
+// class A extends Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: Non-abstract class 'B' has 'Enum' as a superinterface.
+// class B implements Enum { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:15:7: Error: Non-abstract class 'EnumClass' has 'Enum' as a superinterface.
+// class EnumClass extends EnumInterface { // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: Non-abstract class 'EnumClass2' has 'Enum' as a superinterface.
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: Non-abstract class 'EnumClass3' has 'Enum' as a superinterface.
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:5:7: Error: The non-abstract class 'A' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A extends Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:9:7: Error: The non-abstract class 'B' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B implements Enum { // Error.
+//       ^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:21:7: Error: The non-abstract class 'EnumClass2' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass2 extends AbstractEnumClass {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:27:7: Error: The non-abstract class 'EnumClass3' is missing implementations for these members:
+//  - Enum.index
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class EnumClass3 extends AbstractEnumClass2 {} // Error.
+//       ^^^^^^^^^^
+// sdk/lib/core/enum.dart:22:11: Context: 'Enum.index' is defined here.
+//   int get index;
+//           ^^^^^
+//
+// pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart:25:16: Error: 'Object' doesn't implement 'Enum' so it can't be used with 'EnumMixin'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Enum' is from 'dart:core'.
+//  - 'EnumMixin' is from 'pkg/front_end/testcases/enhanced_enums/enum_as_supertype_error.dart'.
+// abstract class AbstractEnumClass2 with EnumMixin {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Enum {
+  synthetic constructor •() → self::A
+    : super core::Enum::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+class B extends core::Object implements core::Enum {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get foo() → core::int
+    return this.{core::Enum::index}{core::int};
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumInterface extends core::Object implements core::Enum {
+  synthetic constructor •() → self::EnumInterface
+    : super core::Object::•()
+    ;
+}
+class EnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::EnumClass
+    : super self::EnumInterface::•()
+    ;
+  get index() → core::int
+    return 0;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class AbstractEnumClass extends self::EnumInterface {
+  synthetic constructor •() → self::AbstractEnumClass
+    : super self::EnumInterface::•()
+    ;
+}
+class EnumClass2 extends self::AbstractEnumClass {
+  synthetic constructor •() → self::EnumClass2
+    : super self::AbstractEnumClass::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+abstract class EnumMixin extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class _AbstractEnumClass2&Object&EnumMixin extends core::Object implements self::EnumMixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_AbstractEnumClass2&Object&EnumMixin
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractEnumClass2 extends self::_AbstractEnumClass2&Object&EnumMixin {
+  synthetic constructor •() → self::AbstractEnumClass2
+    : super self::_AbstractEnumClass2&Object&EnumMixin::•()
+    ;
+}
+class EnumClass3 extends self::AbstractEnumClass2 {
+  synthetic constructor •() → self::EnumClass3
+    : super self::AbstractEnumClass2::•()
+    ;
+  no-such-method-forwarder get /* from org-dartlang-sdk:///sdk/lib/core/enum.dart */ _name() → core::String
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = #org-dartlang-testcase:///enum_as_supertype_error.dart::_name
+  #C2 = <core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart
new file mode 100644
index 0000000..1197e8e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+X foo<X>(X x) => x;
+
+enum E1 {
+  bar(foo);
+
+  const E1(int Function(int) f);
+}
+
+enum E2<X> {
+  bar(foo);
+
+  const E2(X f);
+}
+
+enum E3<X extends num, Y extends String, Z extends Function(X, Y)> {
+  element
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.expect
new file mode 100644
index 0000000..494cf2f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 bar = #C3;
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C6;
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = #C5;
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  return x;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "bar"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1>[#C3]
+  #C5 = self::E2<<X extends core::Object? = dynamic>(X%) → X%> {index:#C1, _name:#C2}
+  #C6 = <self::E2<dynamic>>[#C5]
+  #C7 = "element"
+  #C8 = self::E3<core::num, core::String, (core::num, core::String) → dynamic> {index:#C1, _name:#C7}
+  #C9 = <self::E3<dynamic, dynamic, dynamic>>[#C8]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inference_in_constructor_parameters.dart:
+- E1. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:10:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
+- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.transformed.expect
new file mode 100644
index 0000000..494cf2f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.transformed.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 bar = #C3;
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C6;
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = #C5;
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  return x;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "bar"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1>[#C3]
+  #C5 = self::E2<<X extends core::Object? = dynamic>(X%) → X%> {index:#C1, _name:#C2}
+  #C6 = <self::E2<dynamic>>[#C5]
+  #C7 = "element"
+  #C8 = self::E3<core::num, core::String, (core::num, core::String) → dynamic> {index:#C1, _name:#C7}
+  #C9 = <self::E3<dynamic, dynamic, dynamic>>[#C8]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inference_in_constructor_parameters.dart:
+- E1. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:10:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
+- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.textual_outline.expect
new file mode 100644
index 0000000..707dc9c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+X foo<X>(X x) => x;
+enum E1 { bar(foo); const E1(int Function(int) f); }
+enum E2<X> { bar(foo); const E2(X f); }
+enum E3<X extends num, Y extends String, Z extends Function(X, Y)> { element }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.expect
new file mode 100644
index 0000000..ae69448
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 bar = #C3;
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C6;
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = #C5;
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  return x;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "bar"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
+  #C6 = <self::E2<dynamic>*>[#C5]
+  #C7 = "element"
+  #C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
+  #C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inference_in_constructor_parameters.dart:
+- E1. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:10:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
+- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.modular.expect
new file mode 100644
index 0000000..ae69448
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.modular.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 bar = #C3;
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C6;
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = #C5;
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  return x;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "bar"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
+  #C6 = <self::E2<dynamic>*>[#C5]
+  #C7 = "element"
+  #C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
+  #C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inference_in_constructor_parameters.dart:
+- E1. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:10:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
+- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.outline.expect
new file mode 100644
index 0000000..399e220
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.outline.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::bar];
+  static const field self::E1 bar = const self::E1::•(0, "bar", self::foo<core::int>);
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = const <self::E2<dynamic>>[self::E2::bar];
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = const self::E2::•<<X extends core::Object? = dynamic>(X%) → X%>(0, "bar", self::foo);
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = const <self::E3<dynamic, dynamic, dynamic>>[self::E3::element];
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = const self::E3::•<core::num, core::String, (core::num, core::String) → dynamic>(0, "element");
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:7:6 -> ListConstant(const <E1*>[const E1{_Enum.index: 0, _Enum._name: "bar"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:8:3 -> InstanceConstant(const E1{_Enum.index: 0, _Enum._name: "bar"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:13:6 -> ListConstant(const <E2<dynamic>*>[const E2<X* Function<X>(X*)*>{_Enum.index: 0, _Enum._name: "bar"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:14:3 -> InstanceConstant(const E2<X* Function<X>(X*)*>{_Enum.index: 0, _Enum._name: "bar"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6 -> ListConstant(const <E3<dynamic, dynamic, dynamic>*>[const E3<num*, String*, dynamic Function(num*, String*)*>{_Enum.index: 0, _Enum._name: "element"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:20:3 -> InstanceConstant(const E3<num*, String*, dynamic Function(num*, String*)*>{_Enum.index: 0, _Enum._name: "element"})
+Extra constant evaluation: evaluated: 21, effectively constant: 6
diff --git a/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.transformed.expect
new file mode 100644
index 0000000..ae69448
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.transformed.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C4;
+  static const field self::E1 bar = #C3;
+  const constructor •(core::int index, core::String name, (core::int) → core::int f) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C6;
+  static const field self::E2<<X extends core::Object? = dynamic>(X%) → X%> bar = #C5;
+  const constructor •(core::int index, core::String name, self::E2::X% f) → self::E2<self::E2::X%>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
+  static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
+  const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+}
+static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
+  return x;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "bar"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = <self::E1*>[#C3]
+  #C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
+  #C6 = <self::E2<dynamic>*>[#C5]
+  #C7 = "element"
+  #C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
+  #C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inference_in_constructor_parameters.dart:
+- E1. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:10:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
+- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart
new file mode 100644
index 0000000..971776f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E<X> {
+  one(1),
+  two("2");
+
+  final X field;
+
+  const E(this.field);
+}
+
+test() {
+  foo(E.one, E.two); // Ok.
+}
+
+foo(E<int> ei, E<String> es) {
+  bar(ei, es); // Ok.
+  bar(E.one, E.two); // Ok.
+  bar(es, ei); // Error.
+  bar(E.two, E.one); // Error.
+}
+
+bar(E<int> ei, E<String> es) {
+  baz(ei, es); // Ok.
+}
+
+baz(E<Object> ei, E<Object> es) {
+  boz(ei, es); // Error.
+  boz(E.one, E.two); // Error.
+}
+
+boz(E<Never> ei, E<Never> es) {}
+
+checkIsType<T>(x) {
+  if (x is! T) {
+    throw "Expected value of type ${x.runtimeType} to also be of type ${T}.";
+  }
+}
+
+checkIsNotType<T>(x) {
+  if (x is T) {
+    throw "Expected value of type ${x.runtimeType} to not be of type ${T}.";
+  }
+}
+
+main() {
+  checkIsType<E<dynamic>>(E.one);
+  checkIsType<E<dynamic>>(E.two);
+  checkIsType<E<int>>(E.one);
+  checkIsType<E<String>>(E.two);
+
+  checkIsNotType<E<Never>>(E.one);
+  checkIsNotType<E<Never>>(E.two);
+  checkIsNotType<E<String>>(E.one);
+  checkIsNotType<E<int>>(E.two);
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect
new file mode 100644
index 0000000..7e8bae6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e8bae6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect
new file mode 100644
index 0000000..8ce4f0c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+enum E<X> { one(1), two("2"); final X field; const E(this.field); }
+test() {}
+foo(E<int> ei, E<String> es) {}
+bar(E<int> ei, E<String> es) {}
+baz(E<Object> ei, E<Object> es) {}
+boz(E<Never> ei, E<Never> es) {}
+checkIsType<T>(x) {}
+checkIsNotType<T>(x) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect
new file mode 100644
index 0000000..0f67ffa
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = const <self::E<dynamic>>[self::E::one, self::E::two];
+  static const field self::E<core::int> one = const self::E::•<core::int>(0, "one", 1);
+  static const field self::E<core::String> two = const self::E::•<core::String>(1, "two", "2");
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic
+  ;
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic
+  ;
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic
+  ;
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic
+  ;
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic
+  ;
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic
+  ;
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:5:6 -> ListConstant(const <E<dynamic>*>[const E<int*>{E.field: 1, _Enum.index: 0, _Enum._name: "one"}, const E<String*>{E.field: "2", _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:6:3 -> InstanceConstant(const E<int*>{E.field: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:7:3 -> InstanceConstant(const E<String*>{E.field: "2", _Enum.index: 1, _Enum._name: "two"})
+Extra constant evaluation: evaluated: 9, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart b/pkg/front_end/testcases/enhanced_enums/issue48084.dart
new file mode 100644
index 0000000..433bea6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E {
+  one("foo"),
+  two("bar");
+
+  final String field;
+
+  const E(this.field);
+
+  @override
+  String toString() => field;
+}
+
+expectEquals(a, b) {
+  if (a != b) {
+    throw "Expected '$a' and '$b' to be equal.";
+  }
+}
+
+main() {
+  expectEquals("${E.one}", "foo");
+  expectEquals("${E.two}", "bar");
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.expect
new file mode 100644
index 0000000..1da7d5a
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C4;
+  static const field self::E two = #C8;
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @#C10
+  method toString() → core::String
+    return this.{self::E::field}{core::String};
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic {
+  if(!(a =={core::Object::==}{(core::Object) → core::bool} b)) {
+    throw "Expected '${a}' and '${b}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals("${#C4}", "foo");
+  self::expectEquals("${#C8}", "bar");
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E {field:#C1, index:#C2, _name:#C3}
+  #C5 = "bar"
+  #C6 = 1
+  #C7 = "two"
+  #C8 = self::E {field:#C5, index:#C6, _name:#C7}
+  #C9 = <self::E>[#C4, #C8]
+  #C10 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48084.dart:
+- E. (from org-dartlang-testcase:///issue48084.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.transformed.expect
new file mode 100644
index 0000000..1da7d5a
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.strong.transformed.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C4;
+  static const field self::E two = #C8;
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @#C10
+  method toString() → core::String
+    return this.{self::E::field}{core::String};
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic {
+  if(!(a =={core::Object::==}{(core::Object) → core::bool} b)) {
+    throw "Expected '${a}' and '${b}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals("${#C4}", "foo");
+  self::expectEquals("${#C8}", "bar");
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E {field:#C1, index:#C2, _name:#C3}
+  #C5 = "bar"
+  #C6 = 1
+  #C7 = "two"
+  #C8 = self::E {field:#C5, index:#C6, _name:#C7}
+  #C9 = <self::E>[#C4, #C8]
+  #C10 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48084.dart:
+- E. (from org-dartlang-testcase:///issue48084.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.textual_outline.expect
new file mode 100644
index 0000000..57d7640
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum E { one("foo"), two("bar"); final String field; const E(this.field); @override String toString() => field; }
+expectEquals(a, b) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.expect
new file mode 100644
index 0000000..32c1780
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C4;
+  static const field self::E two = #C8;
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @#C10
+  method toString() → core::String
+    return this.{self::E::field}{core::String};
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic {
+  if(!(a =={core::Object::==}{(core::Object) → core::bool} b)) {
+    throw "Expected '${a}' and '${b}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals("${#C4}", "foo");
+  self::expectEquals("${#C8}", "bar");
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E {field:#C1, index:#C2, _name:#C3}
+  #C5 = "bar"
+  #C6 = 1
+  #C7 = "two"
+  #C8 = self::E {field:#C5, index:#C6, _name:#C7}
+  #C9 = <self::E*>[#C4, #C8]
+  #C10 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48084.dart:
+- E. (from org-dartlang-testcase:///issue48084.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.modular.expect
new file mode 100644
index 0000000..32c1780
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.modular.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C4;
+  static const field self::E two = #C8;
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @#C10
+  method toString() → core::String
+    return this.{self::E::field}{core::String};
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic {
+  if(!(a =={core::Object::==}{(core::Object) → core::bool} b)) {
+    throw "Expected '${a}' and '${b}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals("${#C4}", "foo");
+  self::expectEquals("${#C8}", "bar");
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E {field:#C1, index:#C2, _name:#C3}
+  #C5 = "bar"
+  #C6 = 1
+  #C7 = "two"
+  #C8 = self::E {field:#C5, index:#C6, _name:#C7}
+  #C9 = <self::E*>[#C4, #C8]
+  #C10 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48084.dart:
+- E. (from org-dartlang-testcase:///issue48084.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.outline.expect
new file mode 100644
index 0000000..1419d47
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.outline.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = const <self::E>[self::E::one, self::E::two];
+  static const field self::E one = const self::E::•(0, "one", "foo");
+  static const field self::E two = const self::E::•(1, "two", "bar");
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @core::override
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///issue48084.dart:13:4 -> InstanceConstant(const _Override{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue48084.dart:5:6 -> ListConstant(const <E*>[const E{E.field: "foo", _Enum.index: 0, _Enum._name: "one"}, const E{E.field: "bar", _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue48084.dart:6:3 -> InstanceConstant(const E{E.field: "foo", _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue48084.dart:7:3 -> InstanceConstant(const E{E.field: "bar", _Enum.index: 1, _Enum._name: "two"})
+Extra constant evaluation: evaluated: 10, effectively constant: 4
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.transformed.expect
new file mode 100644
index 0000000..32c1780
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48084.dart.weak.transformed.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C4;
+  static const field self::E two = #C8;
+  final field core::String field;
+  const constructor •(core::int index, core::String name, core::String field) → self::E
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  @#C10
+  method toString() → core::String
+    return this.{self::E::field}{core::String};
+}
+static method expectEquals(dynamic a, dynamic b) → dynamic {
+  if(!(a =={core::Object::==}{(core::Object) → core::bool} b)) {
+    throw "Expected '${a}' and '${b}' to be equal.";
+  }
+}
+static method main() → dynamic {
+  self::expectEquals("${#C4}", "foo");
+  self::expectEquals("${#C8}", "bar");
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E {field:#C1, index:#C2, _name:#C3}
+  #C5 = "bar"
+  #C6 = 1
+  #C7 = "two"
+  #C8 = self::E {field:#C5, index:#C6, _name:#C7}
+  #C9 = <self::E*>[#C4, #C8]
+  #C10 = core::_Override {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48084.dart:
+- E. (from org-dartlang-testcase:///issue48084.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart b/pkg/front_end/testcases/enhanced_enums/issue48181.dart
new file mode 100644
index 0000000..9d6ac05
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E {
+  e1,
+  e2;
+  factory E.f(int i) => E.values[i];
+}
+
+enum F {
+  f1,
+  f2(42),
+  f3.foo();
+  factory F(int i) => F.values[i];
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.expect
new file mode 100644
index 0000000..0f6d2ba
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C7;
+  static const field self::E e1 = #C3;
+  static const field self::E e2 = #C6;
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    return #C7.{core::List::[]}(i){(core::int) → self::E};
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    return invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^".{core::List::[]}(i){(core::int) → self::F};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "e1"
+  #C3 = self::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "e2"
+  #C6 = self::E {index:#C4, _name:#C5}
+  #C7 = <self::E>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48181.dart:
+- E. (from org-dartlang-testcase:///issue48181.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f6d2ba
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C7;
+  static const field self::E e1 = #C3;
+  static const field self::E e2 = #C6;
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    return #C7.{core::List::[]}(i){(core::int) → self::E};
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    return invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^".{core::List::[]}(i){(core::int) → self::F};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "e1"
+  #C3 = self::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "e2"
+  #C6 = self::E {index:#C4, _name:#C5}
+  #C7 = <self::E>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48181.dart:
+- E. (from org-dartlang-testcase:///issue48181.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.textual_outline.expect
new file mode 100644
index 0000000..ac00eb5e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum E { e1, e2; factory E.f(int i) => E.values[i]; }
+enum F { f1, f2(42), f3.foo(); factory F(int i) => F.values[i]; }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.expect
new file mode 100644
index 0000000..ff44426
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C7;
+  static const field self::E e1 = #C3;
+  static const field self::E e2 = #C6;
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    return #C7.{core::List::[]}(i){(core::int) → self::E};
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    return invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^".{core::List::[]}(i){(core::int) → self::F};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "e1"
+  #C3 = self::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "e2"
+  #C6 = self::E {index:#C4, _name:#C5}
+  #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48181.dart:
+- E. (from org-dartlang-testcase:///issue48181.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.modular.expect
new file mode 100644
index 0000000..ff44426
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.modular.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C7;
+  static const field self::E e1 = #C3;
+  static const field self::E e2 = #C6;
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    return #C7.{core::List::[]}(i){(core::int) → self::E};
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    return invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^".{core::List::[]}(i){(core::int) → self::F};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "e1"
+  #C3 = self::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "e2"
+  #C6 = self::E {index:#C4, _name:#C5}
+  #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48181.dart:
+- E. (from org-dartlang-testcase:///issue48181.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.outline.expect
new file mode 100644
index 0000000..dbb7eac
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.outline.expect
@@ -0,0 +1,56 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = const <self::E>[self::E::e1, self::E::e2];
+  static const field self::E e1 = const self::E::•(0, "e1");
+  static const field self::E e2 = const self::E::•(1, "e2");
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    ;
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = const <self::F>[self::F::f1, self::F::f2, self::F::f3];
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue48181.dart:5:6 -> ListConstant(const <E*>[const E{_Enum.index: 0, _Enum._name: "e1"}, const E{_Enum.index: 1, _Enum._name: "e2"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue48181.dart:6:3 -> InstanceConstant(const E{_Enum.index: 0, _Enum._name: "e1"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue48181.dart:7:3 -> InstanceConstant(const E{_Enum.index: 1, _Enum._name: "e2"})
+Extra constant evaluation: evaluated: 15, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.transformed.expect
new file mode 100644
index 0000000..ff44426
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue48181.dart.weak.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+//   f1,
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+//   f2(42),
+//     ^
+//
+// pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+//   f3.foo();
+//     ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C7;
+  static const field self::E e1 = #C3;
+  static const field self::E e2 = #C6;
+  const constructor •(core::int index, core::String name) → self::E
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f(core::int i) → self::E
+    return #C7.{core::List::[]}(i){(core::int) → self::E};
+}
+class F extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::F> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^";
+  static const field self::F f2 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:13:5: Error: Couldn't find constructor 'F'.
+  f2(42),
+    ^";
+  static const field self::F f3 = invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:14:5: Error: Couldn't find constructor 'F.foo'.
+  f3.foo();
+    ^^^";
+  method toString() → core::String
+    return "F.${this.{core::_Enum::_name}{core::String}}";
+  static factory •(core::int i) → self::F
+    return invalid-expression "pkg/front_end/testcases/enhanced_enums/issue48181.dart:12:5: Error: Couldn't find constructor 'F'.
+  f1,
+    ^".{core::List::[]}(i){(core::int) → self::F};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "e1"
+  #C3 = self::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "e2"
+  #C6 = self::E {index:#C4, _name:#C5}
+  #C7 = <self::E*>[#C3, #C6]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48181.dart:
+- E. (from org-dartlang-testcase:///issue48181.dart:5:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart b/pkg/front_end/testcases/enhanced_enums/members.dart
new file mode 100644
index 0000000..a4fab29
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E {
+  one(1),
+  two(2);
+
+  final int foo;
+  final int bar = 42;
+
+  static E staticFoo = new E.f();
+
+  const E(this.foo);
+
+  factory E.f() => E.one;
+
+  int method(int value) => value + 10;
+
+  String staticMethod(double d, bool b) => "$d$b";
+}
+
+enum E2<X> {
+  one<num>(1),
+  two("2");
+
+  final X foo;
+  final X? bar = null;
+
+  static var staticFoo = () => new E2.f();
+
+  const E2(this.foo);
+
+  factory E2.f() => throw 42;
+
+  int method(int value) => value + 10;
+
+  String staticMethod(double d, X x) => "$d$x";
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect
new file mode 100644
index 0000000..c358d70
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C5;
+  static const field self::E two = #C8;
+  final field core::int foo;
+  final field core::int bar = 42;
+  static field self::E staticFoo = self::E::f();
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    return #C5;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, core::bool b) → core::String
+    return "${d}${b}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C14;
+  static const field self::E2<core::num> one = #C11;
+  static const field self::E2<core::String> two = #C13;
+  final field self::E2::X% foo;
+  final field self::E2::X? bar = null;
+  static field () → self::E2<dynamic> staticFoo = () → self::E2<dynamic> => self::E2::f<dynamic>();
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    return throw 42;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    return "${d}${x}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 42
+  #C3 = 0
+  #C4 = "one"
+  #C5 = self::E {foo:#C1, bar:#C2, index:#C3, _name:#C4}
+  #C6 = 2
+  #C7 = "two"
+  #C8 = self::E {foo:#C6, bar:#C2, index:#C1, _name:#C7}
+  #C9 = <self::E>[#C5, #C8]
+  #C10 = null
+  #C11 = self::E2<core::num> {foo:#C1, bar:#C10, index:#C3, _name:#C4}
+  #C12 = "2"
+  #C13 = self::E2<core::String> {foo:#C12, bar:#C10, index:#C1, _name:#C7}
+  #C14 = <self::E2<dynamic>>[#C11, #C13]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///members.dart:
+- E. (from org-dartlang-testcase:///members.dart:14:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///members.dart:32:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect
new file mode 100644
index 0000000..c358d70
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C5;
+  static const field self::E two = #C8;
+  final field core::int foo;
+  final field core::int bar = 42;
+  static field self::E staticFoo = self::E::f();
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    return #C5;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, core::bool b) → core::String
+    return "${d}${b}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C14;
+  static const field self::E2<core::num> one = #C11;
+  static const field self::E2<core::String> two = #C13;
+  final field self::E2::X% foo;
+  final field self::E2::X? bar = null;
+  static field () → self::E2<dynamic> staticFoo = () → self::E2<dynamic> => self::E2::f<dynamic>();
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    return throw 42;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    return "${d}${x}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 42
+  #C3 = 0
+  #C4 = "one"
+  #C5 = self::E {foo:#C1, bar:#C2, index:#C3, _name:#C4}
+  #C6 = 2
+  #C7 = "two"
+  #C8 = self::E {foo:#C6, bar:#C2, index:#C1, _name:#C7}
+  #C9 = <self::E>[#C5, #C8]
+  #C10 = null
+  #C11 = self::E2<core::num> {foo:#C1, bar:#C10, index:#C3, _name:#C4}
+  #C12 = "2"
+  #C13 = self::E2<core::String> {foo:#C12, bar:#C10, index:#C1, _name:#C7}
+  #C14 = <self::E2<dynamic>>[#C11, #C13]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///members.dart:
+- E. (from org-dartlang-testcase:///members.dart:14:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///members.dart:32:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.textual_outline.expect
new file mode 100644
index 0000000..1037478
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum E { one(1), two(2); final int foo; final int bar = 42; static E staticFoo = new E.f(); const E(this.foo); factory E.f() => E.one; int method(int value) => value + 10; String staticMethod(double d, bool b) => "$d$b"; }
+enum E2<X> { one<num>(1), two("2"); final X foo; final X? bar = null; static var staticFoo = () => new E2.f(); const E2(this.foo); factory E2.f() => throw 42; int method(int value) => value + 10; String staticMethod(double d, X x) => "$d$x"; }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect
new file mode 100644
index 0000000..16019e2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C5;
+  static const field self::E two = #C8;
+  final field core::int foo;
+  final field core::int bar = 42;
+  static field self::E staticFoo = self::E::f();
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    return #C5;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, core::bool b) → core::String
+    return "${d}${b}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C14;
+  static const field self::E2<core::num> one = #C11;
+  static const field self::E2<core::String> two = #C13;
+  final field self::E2::X% foo;
+  final field self::E2::X? bar = null;
+  static field () → self::E2<dynamic> staticFoo = () → self::E2<dynamic> => self::E2::f<dynamic>();
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    return throw 42;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    return "${d}${x}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 42
+  #C3 = 0
+  #C4 = "one"
+  #C5 = self::E {foo:#C1, bar:#C2, index:#C3, _name:#C4}
+  #C6 = 2
+  #C7 = "two"
+  #C8 = self::E {foo:#C6, bar:#C2, index:#C1, _name:#C7}
+  #C9 = <self::E*>[#C5, #C8]
+  #C10 = null
+  #C11 = self::E2<core::num*> {foo:#C1, bar:#C10, index:#C3, _name:#C4}
+  #C12 = "2"
+  #C13 = self::E2<core::String*> {foo:#C12, bar:#C10, index:#C1, _name:#C7}
+  #C14 = <self::E2<dynamic>*>[#C11, #C13]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///members.dart:
+- E. (from org-dartlang-testcase:///members.dart:14:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///members.dart:32:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect
new file mode 100644
index 0000000..16019e2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C5;
+  static const field self::E two = #C8;
+  final field core::int foo;
+  final field core::int bar = 42;
+  static field self::E staticFoo = self::E::f();
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    return #C5;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, core::bool b) → core::String
+    return "${d}${b}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C14;
+  static const field self::E2<core::num> one = #C11;
+  static const field self::E2<core::String> two = #C13;
+  final field self::E2::X% foo;
+  final field self::E2::X? bar = null;
+  static field () → self::E2<dynamic> staticFoo = () → self::E2<dynamic> => self::E2::f<dynamic>();
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    return throw 42;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    return "${d}${x}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 42
+  #C3 = 0
+  #C4 = "one"
+  #C5 = self::E {foo:#C1, bar:#C2, index:#C3, _name:#C4}
+  #C6 = 2
+  #C7 = "two"
+  #C8 = self::E {foo:#C6, bar:#C2, index:#C1, _name:#C7}
+  #C9 = <self::E*>[#C5, #C8]
+  #C10 = null
+  #C11 = self::E2<core::num*> {foo:#C1, bar:#C10, index:#C3, _name:#C4}
+  #C12 = "2"
+  #C13 = self::E2<core::String*> {foo:#C12, bar:#C10, index:#C1, _name:#C7}
+  #C14 = <self::E2<dynamic>*>[#C11, #C13]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///members.dart:
+- E. (from org-dartlang-testcase:///members.dart:14:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///members.dart:32:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect
new file mode 100644
index 0000000..65b7311
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = const <self::E>[self::E::one, self::E::two];
+  static const field self::E one = const self::E::•(0, "one", 1);
+  static const field self::E two = const self::E::•(1, "two", 2);
+  final field core::int foo;
+  final field core::int bar;
+  static field self::E staticFoo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    ;
+  method method(core::int value) → core::int
+    ;
+  method staticMethod(core::double d, core::bool b) → core::String
+    ;
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = const <self::E2<dynamic>>[self::E2::one, self::E2::two];
+  static const field self::E2<core::num> one = const self::E2::•<core::num>(0, "one", 1);
+  static const field self::E2<core::String> two = const self::E2::•<core::String>(1, "two", "2");
+  final field self::E2::X% foo;
+  final field self::E2::X? bar;
+  static field () → self::E2<dynamic> staticFoo;
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    ;
+  method method(core::int value) → core::int
+    ;
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///members.dart:5:6 -> ListConstant(const <E*>[const E{E.foo: 1, E.bar: null, _Enum.index: 0, _Enum._name: "one"}, const E{E.foo: 2, E.bar: null, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:6:3 -> InstanceConstant(const E{E.foo: 1, E.bar: null, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:7:3 -> InstanceConstant(const E{E.foo: 2, E.bar: null, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///members.dart:23:6 -> ListConstant(const <E2<dynamic>*>[const E2<num*>{E2.foo: 1, E2.bar: null, _Enum.index: 0, _Enum._name: "one"}, const E2<String*>{E2.foo: "2", E2.bar: null, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:24:3 -> InstanceConstant(const E2<num*>{E2.foo: 1, E2.bar: null, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///members.dart:25:3 -> InstanceConstant(const E2<String*>{E2.foo: "2", E2.bar: null, _Enum.index: 1, _Enum._name: "two"})
+Extra constant evaluation: evaluated: 18, effectively constant: 6
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect
new file mode 100644
index 0000000..16019e2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C9;
+  static const field self::E one = #C5;
+  static const field self::E two = #C8;
+  final field core::int foo;
+  final field core::int bar = 42;
+  static field self::E staticFoo = self::E::f();
+  const constructor •(core::int index, core::String name, core::int foo) → self::E
+    : self::E::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+  static factory f() → self::E
+    return #C5;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, core::bool b) → core::String
+    return "${d}${b}";
+}
+class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic>> values = #C14;
+  static const field self::E2<core::num> one = #C11;
+  static const field self::E2<core::String> two = #C13;
+  final field self::E2::X% foo;
+  final field self::E2::X? bar = null;
+  static field () → self::E2<dynamic> staticFoo = () → self::E2<dynamic> => self::E2::f<dynamic>();
+  const constructor •(core::int index, core::String name, self::E2::X% foo) → self::E2<self::E2::X%>
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
+    return throw 42;
+  method method(core::int value) → core::int
+    return value.{core::num::+}(10){(core::num) → core::int};
+  method staticMethod(core::double d, covariant-by-class self::E2::X% x) → core::String
+    return "${d}${x}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 42
+  #C3 = 0
+  #C4 = "one"
+  #C5 = self::E {foo:#C1, bar:#C2, index:#C3, _name:#C4}
+  #C6 = 2
+  #C7 = "two"
+  #C8 = self::E {foo:#C6, bar:#C2, index:#C1, _name:#C7}
+  #C9 = <self::E*>[#C5, #C8]
+  #C10 = null
+  #C11 = self::E2<core::num*> {foo:#C1, bar:#C10, index:#C3, _name:#C4}
+  #C12 = "2"
+  #C13 = self::E2<core::String*> {foo:#C12, bar:#C10, index:#C1, _name:#C7}
+  #C14 = <self::E2<dynamic>*>[#C11, #C13]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///members.dart:
+- E. (from org-dartlang-testcase:///members.dart:14:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///members.dart:32:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart
new file mode 100644
index 0000000..b73e541
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E0 {
+  one(1, bar: 1),
+  two(2, bar: 2);
+
+  final int foo;
+  final int bar;
+
+  const E0(this.foo, {required this.bar});
+}
+
+enum E1<X> {
+  one(foo: "1"),
+  two(foo: 2);
+
+  final X foo;
+
+  const E1({required this.foo});
+}
+
+enum E2<X, Y, Z> {
+  one(1, bar: "1", baz: 3.14),
+  two("2", baz: 3.14, bar: 2),
+  three(3.0, bar: false);
+
+  final X foo;
+  final Y bar;
+  final Z? baz;
+
+  const E2(this.foo, {required this.bar, this.baz = null});
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.expect
new file mode 100644
index 0000000..9056dd8
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = #C8;
+  static const field self::E0 one = #C4;
+  static const field self::E0 two = #C7;
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name = #C9, core::int foo, {required core::int bar = #C9}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = #C13;
+  static const field self::E1<core::String> one = #C11;
+  static const field self::E1<core::int> two = #C12;
+  final field self::E1::X% foo;
+  const constructor •(core::int index = #C9, core::String name, {required self::E1::X% foo = #C9}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = #C22;
+  static const field self::E2<core::int, core::String, core::double> one = #C15;
+  static const field self::E2<core::String, core::int, core::double> two = #C17;
+  static const field self::E2<core::double, core::bool, dynamic> three = #C21;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name = #C9, self::E2::X% foo, {required self::E2::Y% bar = #C9, self::E2::Z? baz = #C9}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E0 {foo:#C1, bar:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E0 {foo:#C5, bar:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E0>[#C4, #C7]
+  #C9 = null
+  #C10 = "1"
+  #C11 = self::E1<core::String> {foo:#C10, index:#C2, _name:#C3}
+  #C12 = self::E1<core::int> {foo:#C5, index:#C1, _name:#C6}
+  #C13 = <self::E1<dynamic>>[#C11, #C12]
+  #C14 = 3.14
+  #C15 = self::E2<core::int, core::String, core::double> {foo:#C1, bar:#C10, baz:#C14, index:#C2, _name:#C3}
+  #C16 = "2"
+  #C17 = self::E2<core::String, core::int, core::double> {foo:#C16, bar:#C5, baz:#C14, index:#C1, _name:#C6}
+  #C18 = 3.0
+  #C19 = false
+  #C20 = "three"
+  #C21 = self::E2<core::double, core::bool, dynamic> {foo:#C18, bar:#C19, baz:#C9, index:#C5, _name:#C20}
+  #C22 = <self::E2<dynamic, dynamic, dynamic>>[#C15, #C17, #C21]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///named_arguments.dart:
+- E0. (from org-dartlang-testcase:///named_arguments.dart:12:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1. (from org-dartlang-testcase:///named_arguments.dart:21:9)
+- E2. (from org-dartlang-testcase:///named_arguments.dart:33:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.transformed.expect
new file mode 100644
index 0000000..9056dd8
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.strong.transformed.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = #C8;
+  static const field self::E0 one = #C4;
+  static const field self::E0 two = #C7;
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name = #C9, core::int foo, {required core::int bar = #C9}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = #C13;
+  static const field self::E1<core::String> one = #C11;
+  static const field self::E1<core::int> two = #C12;
+  final field self::E1::X% foo;
+  const constructor •(core::int index = #C9, core::String name, {required self::E1::X% foo = #C9}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = #C22;
+  static const field self::E2<core::int, core::String, core::double> one = #C15;
+  static const field self::E2<core::String, core::int, core::double> two = #C17;
+  static const field self::E2<core::double, core::bool, dynamic> three = #C21;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name = #C9, self::E2::X% foo, {required self::E2::Y% bar = #C9, self::E2::Z? baz = #C9}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E0 {foo:#C1, bar:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E0 {foo:#C5, bar:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E0>[#C4, #C7]
+  #C9 = null
+  #C10 = "1"
+  #C11 = self::E1<core::String> {foo:#C10, index:#C2, _name:#C3}
+  #C12 = self::E1<core::int> {foo:#C5, index:#C1, _name:#C6}
+  #C13 = <self::E1<dynamic>>[#C11, #C12]
+  #C14 = 3.14
+  #C15 = self::E2<core::int, core::String, core::double> {foo:#C1, bar:#C10, baz:#C14, index:#C2, _name:#C3}
+  #C16 = "2"
+  #C17 = self::E2<core::String, core::int, core::double> {foo:#C16, bar:#C5, baz:#C14, index:#C1, _name:#C6}
+  #C18 = 3.0
+  #C19 = false
+  #C20 = "three"
+  #C21 = self::E2<core::double, core::bool, dynamic> {foo:#C18, bar:#C19, baz:#C9, index:#C5, _name:#C20}
+  #C22 = <self::E2<dynamic, dynamic, dynamic>>[#C15, #C17, #C21]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///named_arguments.dart:
+- E0. (from org-dartlang-testcase:///named_arguments.dart:12:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1. (from org-dartlang-testcase:///named_arguments.dart:21:9)
+- E2. (from org-dartlang-testcase:///named_arguments.dart:33:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.textual_outline.expect
new file mode 100644
index 0000000..c2dd324
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+enum E0 { one(1, bar: 1), two(2, bar: 2); final int foo; final int bar; const E0(this.foo, {required this.bar}); }
+enum E1<X> { one(foo: "1"), two(foo: 2); final X foo; const E1({required this.foo}); }
+enum E2<X, Y, Z> { one(1, bar: "1", baz: 3.14), two("2", baz: 3.14, bar: 2), three(3.0, bar: false); final X foo; final Y bar; final Z? baz; const E2(this.foo, {required this.bar, this.baz = null}); }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.expect
new file mode 100644
index 0000000..5c96c28
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = #C8;
+  static const field self::E0 one = #C4;
+  static const field self::E0 two = #C7;
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name = #C9, core::int foo, {required core::int bar = #C9}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = #C13;
+  static const field self::E1<core::String> one = #C11;
+  static const field self::E1<core::int> two = #C12;
+  final field self::E1::X% foo;
+  const constructor •(core::int index = #C9, core::String name, {required self::E1::X% foo = #C9}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = #C22;
+  static const field self::E2<core::int, core::String, core::double> one = #C15;
+  static const field self::E2<core::String, core::int, core::double> two = #C17;
+  static const field self::E2<core::double, core::bool, dynamic> three = #C21;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name = #C9, self::E2::X% foo, {required self::E2::Y% bar = #C9, self::E2::Z? baz = #C9}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E0 {foo:#C1, bar:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E0 {foo:#C5, bar:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E0*>[#C4, #C7]
+  #C9 = null
+  #C10 = "1"
+  #C11 = self::E1<core::String*> {foo:#C10, index:#C2, _name:#C3}
+  #C12 = self::E1<core::int*> {foo:#C5, index:#C1, _name:#C6}
+  #C13 = <self::E1<dynamic>*>[#C11, #C12]
+  #C14 = 3.14
+  #C15 = self::E2<core::int*, core::String*, core::double*> {foo:#C1, bar:#C10, baz:#C14, index:#C2, _name:#C3}
+  #C16 = "2"
+  #C17 = self::E2<core::String*, core::int*, core::double*> {foo:#C16, bar:#C5, baz:#C14, index:#C1, _name:#C6}
+  #C18 = 3.0
+  #C19 = false
+  #C20 = "three"
+  #C21 = self::E2<core::double*, core::bool*, dynamic> {foo:#C18, bar:#C19, baz:#C9, index:#C5, _name:#C20}
+  #C22 = <self::E2<dynamic, dynamic, dynamic>*>[#C15, #C17, #C21]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///named_arguments.dart:
+- E0. (from org-dartlang-testcase:///named_arguments.dart:12:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1. (from org-dartlang-testcase:///named_arguments.dart:21:9)
+- E2. (from org-dartlang-testcase:///named_arguments.dart:33:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.modular.expect
new file mode 100644
index 0000000..5c96c28
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.modular.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = #C8;
+  static const field self::E0 one = #C4;
+  static const field self::E0 two = #C7;
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name = #C9, core::int foo, {required core::int bar = #C9}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = #C13;
+  static const field self::E1<core::String> one = #C11;
+  static const field self::E1<core::int> two = #C12;
+  final field self::E1::X% foo;
+  const constructor •(core::int index = #C9, core::String name, {required self::E1::X% foo = #C9}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = #C22;
+  static const field self::E2<core::int, core::String, core::double> one = #C15;
+  static const field self::E2<core::String, core::int, core::double> two = #C17;
+  static const field self::E2<core::double, core::bool, dynamic> three = #C21;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name = #C9, self::E2::X% foo, {required self::E2::Y% bar = #C9, self::E2::Z? baz = #C9}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E0 {foo:#C1, bar:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E0 {foo:#C5, bar:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E0*>[#C4, #C7]
+  #C9 = null
+  #C10 = "1"
+  #C11 = self::E1<core::String*> {foo:#C10, index:#C2, _name:#C3}
+  #C12 = self::E1<core::int*> {foo:#C5, index:#C1, _name:#C6}
+  #C13 = <self::E1<dynamic>*>[#C11, #C12]
+  #C14 = 3.14
+  #C15 = self::E2<core::int*, core::String*, core::double*> {foo:#C1, bar:#C10, baz:#C14, index:#C2, _name:#C3}
+  #C16 = "2"
+  #C17 = self::E2<core::String*, core::int*, core::double*> {foo:#C16, bar:#C5, baz:#C14, index:#C1, _name:#C6}
+  #C18 = 3.0
+  #C19 = false
+  #C20 = "three"
+  #C21 = self::E2<core::double*, core::bool*, dynamic> {foo:#C18, bar:#C19, baz:#C9, index:#C5, _name:#C20}
+  #C22 = <self::E2<dynamic, dynamic, dynamic>*>[#C15, #C17, #C21]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///named_arguments.dart:
+- E0. (from org-dartlang-testcase:///named_arguments.dart:12:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1. (from org-dartlang-testcase:///named_arguments.dart:21:9)
+- E2. (from org-dartlang-testcase:///named_arguments.dart:33:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.outline.expect
new file mode 100644
index 0000000..c98ffa3
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.outline.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = const <self::E0>[self::E0::one, self::E0::two];
+  static const field self::E0 one = const self::E0::•(0, "one", 1, bar: 1);
+  static const field self::E0 two = const self::E0::•(1, "two", 2, bar: 2);
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name, core::int foo, {required core::int bar}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = const <self::E1<dynamic>>[self::E1::one, self::E1::two];
+  static const field self::E1<core::String> one = const self::E1::•<core::String>(0, "one", foo: "1");
+  static const field self::E1<core::int> two = const self::E1::•<core::int>(1, "two", foo: 2);
+  final field self::E1::X% foo;
+  const constructor •(core::int index, core::String name, {required self::E1::X% foo}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = const <self::E2<dynamic, dynamic, dynamic>>[self::E2::one, self::E2::two, self::E2::three];
+  static const field self::E2<core::int, core::String, core::double> one = const self::E2::•<core::int, core::String, core::double>(0, "one", 1, bar: "1", baz: 3.14);
+  static const field self::E2<core::String, core::int, core::double> two = const self::E2::•<core::String, core::int, core::double>(1, "two", "2", baz: 3.14, bar: 2);
+  static const field self::E2<core::double, core::bool, dynamic> three = const self::E2::•<core::double, core::bool, dynamic>(2, "three", 3.0, bar: false);
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, {required self::E2::Y% bar, self::E2::Z? baz = null}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///named_arguments.dart:5:6 -> ListConstant(const <E0*>[const E0{E0.foo: 1, E0.bar: 1, _Enum.index: 0, _Enum._name: "one"}, const E0{E0.foo: 2, E0.bar: 2, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:6:3 -> InstanceConstant(const E0{E0.foo: 1, E0.bar: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:7:3 -> InstanceConstant(const E0{E0.foo: 2, E0.bar: 2, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///named_arguments.dart:15:6 -> ListConstant(const <E1<dynamic>*>[const E1<String*>{E1.foo: "1", _Enum.index: 0, _Enum._name: "one"}, const E1<int*>{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:16:3 -> InstanceConstant(const E1<String*>{E1.foo: "1", _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:17:3 -> InstanceConstant(const E1<int*>{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///named_arguments.dart:24:6 -> ListConstant(const <E2<dynamic, dynamic, dynamic>*>[const E2<int*, String*, double*>{E2.foo: 1, E2.bar: "1", E2.baz: 3.14, _Enum.index: 0, _Enum._name: "one"}, const E2<String*, int*, double*>{E2.foo: "2", E2.bar: 2, E2.baz: 3.14, _Enum.index: 1, _Enum._name: "two"}, const E2<double*, bool*, dynamic>{E2.foo: 3.0, E2.bar: false, E2.baz: null, _Enum.index: 2, _Enum._name: "three"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:25:3 -> InstanceConstant(const E2<int*, String*, double*>{E2.foo: 1, E2.bar: "1", E2.baz: 3.14, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:26:3 -> InstanceConstant(const E2<String*, int*, double*>{E2.foo: "2", E2.bar: 2, E2.baz: 3.14, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///named_arguments.dart:27:3 -> InstanceConstant(const E2<double*, bool*, dynamic>{E2.foo: 3.0, E2.bar: false, E2.baz: null, _Enum.index: 2, _Enum._name: "three"})
+Extra constant evaluation: evaluated: 31, effectively constant: 10
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.transformed.expect
new file mode 100644
index 0000000..5c96c28
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments.dart.weak.transformed.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E0 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E0> values = #C8;
+  static const field self::E0 one = #C4;
+  static const field self::E0 two = #C7;
+  final field core::int foo;
+  final field core::int bar;
+  const constructor •(core::int index, core::String name = #C9, core::int foo, {required core::int bar = #C9}) → self::E0
+    : self::E0::foo = foo, self::E0::bar = bar, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E0.${this.{core::_Enum::_name}{core::String}}";
+}
+class E1<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1<dynamic>> values = #C13;
+  static const field self::E1<core::String> one = #C11;
+  static const field self::E1<core::int> two = #C12;
+  final field self::E1::X% foo;
+  const constructor •(core::int index = #C9, core::String name, {required self::E1::X% foo = #C9}) → self::E1<self::E1::X%>
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic, Z extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic, dynamic>> values = #C22;
+  static const field self::E2<core::int, core::String, core::double> one = #C15;
+  static const field self::E2<core::String, core::int, core::double> two = #C17;
+  static const field self::E2<core::double, core::bool, dynamic> three = #C21;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  final field self::E2::Z? baz;
+  const constructor •(core::int index, core::String name = #C9, self::E2::X% foo, {required self::E2::Y% bar = #C9, self::E2::Z? baz = #C9}) → self::E2<self::E2::X%, self::E2::Y%, self::E2::Z%>
+    : self::E2::foo = foo, self::E2::bar = bar, self::E2::baz = baz, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E0 {foo:#C1, bar:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E0 {foo:#C5, bar:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E0*>[#C4, #C7]
+  #C9 = null
+  #C10 = "1"
+  #C11 = self::E1<core::String*> {foo:#C10, index:#C2, _name:#C3}
+  #C12 = self::E1<core::int*> {foo:#C5, index:#C1, _name:#C6}
+  #C13 = <self::E1<dynamic>*>[#C11, #C12]
+  #C14 = 3.14
+  #C15 = self::E2<core::int*, core::String*, core::double*> {foo:#C1, bar:#C10, baz:#C14, index:#C2, _name:#C3}
+  #C16 = "2"
+  #C17 = self::E2<core::String*, core::int*, core::double*> {foo:#C16, bar:#C5, baz:#C14, index:#C1, _name:#C6}
+  #C18 = 3.0
+  #C19 = false
+  #C20 = "three"
+  #C21 = self::E2<core::double*, core::bool*, dynamic> {foo:#C18, bar:#C19, baz:#C9, index:#C5, _name:#C20}
+  #C22 = <self::E2<dynamic, dynamic, dynamic>*>[#C15, #C17, #C21]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///named_arguments.dart:
+- E0. (from org-dartlang-testcase:///named_arguments.dart:12:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1. (from org-dartlang-testcase:///named_arguments.dart:21:9)
+- E2. (from org-dartlang-testcase:///named_arguments.dart:33:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.expect
index b209df1..ffb1eca 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.expect
@@ -5,7 +5,7 @@
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = #C4;
   static const field self::E a = #C3;
-  const constructor •(core::int index, core::String name) → self::E
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -23,6 +23,6 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:
-- E. (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:5:6)
+- E.b (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:8:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.transformed.expect
index b209df1..ffb1eca 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = #C4;
   static const field self::E a = #C3;
-  const constructor •(core::int index, core::String name) → self::E
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -23,6 +23,6 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:
-- E. (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:5:6)
+- E.b (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:8:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.expect
index 5cc89c4..08918e1 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.expect
@@ -5,7 +5,7 @@
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = #C4;
   static const field self::E a = #C3;
-  const constructor •(core::int index, core::String name) → self::E
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -23,6 +23,6 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:
-- E. (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:5:6)
+- E.b (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:8:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.modular.expect
index 5cc89c4..08918e1 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.modular.expect
@@ -5,7 +5,7 @@
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = #C4;
   static const field self::E a = #C3;
-  const constructor •(core::int index, core::String name) → self::E
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -23,6 +23,6 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:
-- E. (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:5:6)
+- E.b (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:8:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.outline.expect
index 2732493..cf85d8d 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.outline.expect
@@ -4,8 +4,8 @@
 
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = const <self::E>[self::E::a];
-  static const field self::E a = const self::E::•(0, "a");
-  const constructor •(core::int index, core::String name) → self::E
+  static const field self::E a = const self::E::b(0, "a");
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
diff --git a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.transformed.expect
index 5cc89c4..08918e1 100644
--- a/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/qualified_names_with_no_type_arguments.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 class E extends core::_Enum /*isEnum*/  {
   static const field core::List<self::E> values = #C4;
   static const field self::E a = #C3;
-  const constructor •(core::int index, core::String name) → self::E
+  const constructor b(core::int index, core::String name) → self::E
     : super core::_Enum::•(index, name)
     ;
   method toString() → core::String
@@ -23,6 +23,6 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:
-- E. (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:5:6)
+- E.b (from org-dartlang-testcase:///qualified_names_with_no_type_arguments.dart:8:9)
 - _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart
new file mode 100644
index 0000000..e047de1
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E1 {
+  one(1),
+  two.named(2);
+
+  final int foo;
+
+  const E1(this.foo);
+  const E1.named(int value) : this(value); // Ok.
+}
+
+enum E2 {
+  one(1),
+  two.named(2);
+
+  final int foo;
+
+  const E2(this.foo);
+  const E2.named(int value) : this(value, value); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect
new file mode 100644
index 0000000..99bf4f6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   const E2.named(int value) : this(value, value); // Error.
+//         ^^^^^
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
+//   final int foo;
+//             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  static const field self::E2 one = #C9;
+  static const field self::E2 two = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1>[#C4, #C7]
+  #C9 = self::E2 {foo:#C1, index:#C2, _name:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_initializers.dart:
+- E1. (from org-dartlang-testcase:///redirecting_initializers.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///redirecting_initializers.dart:12:9)
+- E2. (from org-dartlang-testcase:///redirecting_initializers.dart:21:9)
+- E2.named (from org-dartlang-testcase:///redirecting_initializers.dart:22:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect
new file mode 100644
index 0000000..99bf4f6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   const E2.named(int value) : this(value, value); // Error.
+//         ^^^^^
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
+//   final int foo;
+//             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  static const field self::E2 one = #C9;
+  static const field self::E2 two = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1>[#C4, #C7]
+  #C9 = self::E2 {foo:#C1, index:#C2, _name:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_initializers.dart:
+- E1. (from org-dartlang-testcase:///redirecting_initializers.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///redirecting_initializers.dart:12:9)
+- E2. (from org-dartlang-testcase:///redirecting_initializers.dart:21:9)
+- E2.named (from org-dartlang-testcase:///redirecting_initializers.dart:22:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.textual_outline.expect
new file mode 100644
index 0000000..8246ad5
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum E1 { one(1), two.named(2); final int foo; const E1(this.foo); const E1.named(int value) : this(value); }
+enum E2 { one(1), two.named(2); final int foo; const E2(this.foo); const E2.named(int value) : this(value, value); }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.expect
new file mode 100644
index 0000000..352aa87
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   const E2.named(int value) : this(value, value); // Error.
+//         ^^^^^
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
+//   final int foo;
+//             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  static const field self::E2 one = #C9;
+  static const field self::E2 two = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2 {foo:#C1, index:#C2, _name:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_initializers.dart:
+- E1. (from org-dartlang-testcase:///redirecting_initializers.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///redirecting_initializers.dart:12:9)
+- E2. (from org-dartlang-testcase:///redirecting_initializers.dart:21:9)
+- E2.named (from org-dartlang-testcase:///redirecting_initializers.dart:22:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.modular.expect
new file mode 100644
index 0000000..352aa87
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.modular.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   const E2.named(int value) : this(value, value); // Error.
+//         ^^^^^
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
+//   final int foo;
+//             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  static const field self::E2 one = #C9;
+  static const field self::E2 two = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2 {foo:#C1, index:#C2, _name:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_initializers.dart:
+- E1. (from org-dartlang-testcase:///redirecting_initializers.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///redirecting_initializers.dart:12:9)
+- E2. (from org-dartlang-testcase:///redirecting_initializers.dart:21:9)
+- E2.named (from org-dartlang-testcase:///redirecting_initializers.dart:22:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.outline.expect
new file mode 100644
index 0000000..6ded04c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.outline.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::one, self::E1::two];
+  static const field self::E1 one = const self::E1::•(0, "one", 1);
+  static const field self::E1 two = const self::E1::named(1, "two", 2);
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = const <self::E2>[self::E2::one, self::E2::two];
+  static const field self::E2 one = const self::E2::•(0, "one", 1);
+  static const field self::E2 two = const self::E2::named(1, "two", 2);
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_initializers.dart:5:6 -> ListConstant(const <E1*>[const E1{E1.foo: 1, _Enum.index: 0, _Enum._name: "one"}, const E1{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_initializers.dart:6:3 -> InstanceConstant(const E1{E1.foo: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_initializers.dart:7:3 -> InstanceConstant(const E1{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_initializers.dart:15:6 -> InstanceConstant(const E2{E2.foo: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_initializers.dart:16:3 -> InstanceConstant(const E2{E2.foo: 1, _Enum.index: 0, _Enum._name: "one"})
+Extra constant evaluation: evaluated: 23, effectively constant: 5
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.transformed.expect
new file mode 100644
index 0000000..352aa87
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.weak.transformed.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+// Try removing the extra positional arguments.
+//   const E2.named(int value) : this(value, value); // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   const E2.named(int value) : this(value, value); // Error.
+//         ^^^^^
+// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
+//   final int foo;
+//             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : this self::E1::•(index, name, value)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2> values = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  static const field self::E2 one = #C9;
+  static const field self::E2 two = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^";
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E2
+    : self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E2
+    : self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  const E2.named(int value) : this(value, value); // Error.
+                                  ^"
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2 {foo:#C1, index:#C2, _name:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_initializers.dart:
+- E1. (from org-dartlang-testcase:///redirecting_initializers.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///redirecting_initializers.dart:12:9)
+- E2. (from org-dartlang-testcase:///redirecting_initializers.dart:21:9)
+- E2.named (from org-dartlang-testcase:///redirecting_initializers.dart:22:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart
new file mode 100644
index 0000000..c82bd4d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum E1 {
+  one(1),
+  two.named(2);
+
+  final int foo;
+
+  const E1(this.foo);
+
+  const E1.named(int value) : foo = value;
+}
+
+enum E2<X, Y> {
+  one<int, String>(1, "one"),
+  two.named("two", 2),
+  three.named("three", "three");
+
+  final X foo;
+  final Y bar;
+
+  const E2(this.foo, this.bar);
+  const E2.named(Y this.bar, X this.foo);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.expect
new file mode 100644
index 0000000..b546ffd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = #C13;
+  static const field self::E2<core::int, core::String> one = #C9;
+  static const field self::E2<core::int, core::String> two = #C10;
+  static const field self::E2<core::String, core::String> three = #C12;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1>[#C4, #C7]
+  #C9 = self::E2<core::int, core::String> {foo:#C1, bar:#C3, index:#C2, _name:#C3}
+  #C10 = self::E2<core::int, core::String> {foo:#C5, bar:#C6, index:#C1, _name:#C6}
+  #C11 = "three"
+  #C12 = self::E2<core::String, core::String> {foo:#C11, bar:#C11, index:#C5, _name:#C11}
+  #C13 = <self::E2<dynamic, dynamic>>[#C9, #C10, #C12]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_fields.dart:
+- E1. (from org-dartlang-testcase:///simple_fields.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///simple_fields.dart:13:9)
+- E2. (from org-dartlang-testcase:///simple_fields.dart:24:9)
+- E2.named (from org-dartlang-testcase:///simple_fields.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.transformed.expect
new file mode 100644
index 0000000..b546ffd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.strong.transformed.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = #C13;
+  static const field self::E2<core::int, core::String> one = #C9;
+  static const field self::E2<core::int, core::String> two = #C10;
+  static const field self::E2<core::String, core::String> three = #C12;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1>[#C4, #C7]
+  #C9 = self::E2<core::int, core::String> {foo:#C1, bar:#C3, index:#C2, _name:#C3}
+  #C10 = self::E2<core::int, core::String> {foo:#C5, bar:#C6, index:#C1, _name:#C6}
+  #C11 = "three"
+  #C12 = self::E2<core::String, core::String> {foo:#C11, bar:#C11, index:#C5, _name:#C11}
+  #C13 = <self::E2<dynamic, dynamic>>[#C9, #C10, #C12]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_fields.dart:
+- E1. (from org-dartlang-testcase:///simple_fields.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///simple_fields.dart:13:9)
+- E2. (from org-dartlang-testcase:///simple_fields.dart:24:9)
+- E2.named (from org-dartlang-testcase:///simple_fields.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.textual_outline.expect
new file mode 100644
index 0000000..d11d9cd
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+enum E1 { one(1), two.named(2); final int foo; const E1(this.foo); const E1.named(int value) : foo = value; }
+enum E2<X, Y> { one<int, String>(1, "one"), two.named("two", 2), three.named("three", "three"); final X foo; final Y bar; const E2(this.foo, this.bar); const E2.named(Y this.bar, X this.foo); }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.expect
new file mode 100644
index 0000000..c1e1607
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = #C13;
+  static const field self::E2<core::int, core::String> one = #C9;
+  static const field self::E2<core::int, core::String> two = #C10;
+  static const field self::E2<core::String, core::String> three = #C12;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2<core::int*, core::String*> {foo:#C1, bar:#C3, index:#C2, _name:#C3}
+  #C10 = self::E2<core::int*, core::String*> {foo:#C5, bar:#C6, index:#C1, _name:#C6}
+  #C11 = "three"
+  #C12 = self::E2<core::String*, core::String*> {foo:#C11, bar:#C11, index:#C5, _name:#C11}
+  #C13 = <self::E2<dynamic, dynamic>*>[#C9, #C10, #C12]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_fields.dart:
+- E1. (from org-dartlang-testcase:///simple_fields.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///simple_fields.dart:13:9)
+- E2. (from org-dartlang-testcase:///simple_fields.dart:24:9)
+- E2.named (from org-dartlang-testcase:///simple_fields.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.modular.expect
new file mode 100644
index 0000000..c1e1607
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.modular.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = #C13;
+  static const field self::E2<core::int, core::String> one = #C9;
+  static const field self::E2<core::int, core::String> two = #C10;
+  static const field self::E2<core::String, core::String> three = #C12;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2<core::int*, core::String*> {foo:#C1, bar:#C3, index:#C2, _name:#C3}
+  #C10 = self::E2<core::int*, core::String*> {foo:#C5, bar:#C6, index:#C1, _name:#C6}
+  #C11 = "three"
+  #C12 = self::E2<core::String*, core::String*> {foo:#C11, bar:#C11, index:#C5, _name:#C11}
+  #C13 = <self::E2<dynamic, dynamic>*>[#C9, #C10, #C12]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_fields.dart:
+- E1. (from org-dartlang-testcase:///simple_fields.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///simple_fields.dart:13:9)
+- E2. (from org-dartlang-testcase:///simple_fields.dart:24:9)
+- E2.named (from org-dartlang-testcase:///simple_fields.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.outline.expect
new file mode 100644
index 0000000..e4af5a2
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::one, self::E1::two];
+  static const field self::E1 one = const self::E1::•(0, "one", 1);
+  static const field self::E1 two = const self::E1::named(1, "two", 2);
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = const <self::E2<dynamic, dynamic>>[self::E2::one, self::E2::two, self::E2::three];
+  static const field self::E2<core::int, core::String> one = const self::E2::•<core::int, core::String>(0, "one", 1, "one");
+  static const field self::E2<core::int, core::String> two = const self::E2::named<core::int, core::String>(1, "two", "two", 2);
+  static const field self::E2<core::String, core::String> three = const self::E2::named<core::String, core::String>(2, "three", "three", "three");
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_fields.dart:5:6 -> ListConstant(const <E1*>[const E1{E1.foo: 1, _Enum.index: 0, _Enum._name: "one"}, const E1{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_fields.dart:6:3 -> InstanceConstant(const E1{E1.foo: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_fields.dart:7:3 -> InstanceConstant(const E1{E1.foo: 2, _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_fields.dart:16:6 -> ListConstant(const <E2<dynamic, dynamic>*>[const E2<int*, String*>{E2.foo: 1, E2.bar: "one", _Enum.index: 0, _Enum._name: "one"}, const E2<int*, String*>{E2.foo: 2, E2.bar: "two", _Enum.index: 1, _Enum._name: "two"}, const E2<String*, String*>{E2.foo: "three", E2.bar: "three", _Enum.index: 2, _Enum._name: "three"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_fields.dart:17:3 -> InstanceConstant(const E2<int*, String*>{E2.foo: 1, E2.bar: "one", _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_fields.dart:18:3 -> InstanceConstant(const E2<int*, String*>{E2.foo: 2, E2.bar: "two", _Enum.index: 1, _Enum._name: "two"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_fields.dart:19:3 -> InstanceConstant(const E2<String*, String*>{E2.foo: "three", E2.bar: "three", _Enum.index: 2, _Enum._name: "three"})
+Extra constant evaluation: evaluated: 27, effectively constant: 7
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.transformed.expect
new file mode 100644
index 0000000..c1e1607
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_fields.dart.weak.transformed.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E1 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E1> values = #C8;
+  static const field self::E1 one = #C4;
+  static const field self::E1 two = #C7;
+  final field core::int foo;
+  const constructor •(core::int index, core::String name, core::int foo) → self::E1
+    : self::E1::foo = foo, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, core::int value) → self::E1
+    : self::E1::foo = value, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+}
+class E2<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E2<dynamic, dynamic>> values = #C13;
+  static const field self::E2<core::int, core::String> one = #C9;
+  static const field self::E2<core::int, core::String> two = #C10;
+  static const field self::E2<core::String, core::String> three = #C12;
+  final field self::E2::X% foo;
+  final field self::E2::Y% bar;
+  const constructor •(core::int index, core::String name, self::E2::X% foo, self::E2::Y% bar) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::foo = foo, self::E2::bar = bar, super core::_Enum::•(index, name)
+    ;
+  const constructor named(core::int index, core::String name, self::E2::Y% bar, self::E2::X% foo) → self::E2<self::E2::X%, self::E2::Y%>
+    : self::E2::bar = bar, self::E2::foo = foo, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E1 {foo:#C1, index:#C2, _name:#C3}
+  #C5 = 2
+  #C6 = "two"
+  #C7 = self::E1 {foo:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E1*>[#C4, #C7]
+  #C9 = self::E2<core::int*, core::String*> {foo:#C1, bar:#C3, index:#C2, _name:#C3}
+  #C10 = self::E2<core::int*, core::String*> {foo:#C5, bar:#C6, index:#C1, _name:#C6}
+  #C11 = "three"
+  #C12 = self::E2<core::String*, core::String*> {foo:#C11, bar:#C11, index:#C5, _name:#C11}
+  #C13 = <self::E2<dynamic, dynamic>*>[#C9, #C10, #C12]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_fields.dart:
+- E1. (from org-dartlang-testcase:///simple_fields.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E1.named (from org-dartlang-testcase:///simple_fields.dart:13:9)
+- E2. (from org-dartlang-testcase:///simple_fields.dart:24:9)
+- E2.named (from org-dartlang-testcase:///simple_fields.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart
new file mode 100644
index 0000000..07b8a79
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class I {
+  void foo();
+}
+
+enum E1 implements I { // Ok.
+  one,
+  two;
+
+  void foo() {}
+}
+
+enum E2 implements I { // Error.
+  one,
+  two
+}
+
+enum E3 implements I? { // Error.
+  one,
+  two;
+
+  void foo() {}
+}
+
+enum E4 {
+  one,
+  two;
+
+  void foo() {}
+}
+
+bar(I i) {}
+
+test(E1 e1, E2 e2, E3 e3, E4 e4) {
+  bar(e1); // Ok.
+  bar(e2); // Ok.
+  bar(e3); // Ok.
+  bar(e4); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.expect
new file mode 100644
index 0000000..8c56fb4
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+//  - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//  - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//   bar(e4); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = #C16;
+  static const field self::E4 one = #C14;
+  static const field self::E4 two = #C15;
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+static method bar(self::I i) → dynamic {}
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic {
+  self::bar(e1);
+  self::bar(e2);
+  self::bar(e3);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+ - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+ - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+  bar(e4); // Error.
+      ^" in e4 as{TypeError,ForNonNullableByDefault} self::I);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3>[#C11, #C12]
+  #C14 = self::E4 {index:#C1, _name:#C2}
+  #C15 = self::E4 {index:#C4, _name:#C5}
+  #C16 = <self::E4>[#C14, #C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_interfaces.dart:
+- E1. (from org-dartlang-testcase:///simple_interfaces.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_interfaces.dart:16:6)
+- E3. (from org-dartlang-testcase:///simple_interfaces.dart:21:6)
+- E4. (from org-dartlang-testcase:///simple_interfaces.dart:28:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.transformed.expect
new file mode 100644
index 0000000..8c56fb4
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.strong.transformed.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+//  - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//  - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//   bar(e4); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = #C16;
+  static const field self::E4 one = #C14;
+  static const field self::E4 two = #C15;
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+static method bar(self::I i) → dynamic {}
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic {
+  self::bar(e1);
+  self::bar(e2);
+  self::bar(e3);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+ - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+ - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+  bar(e4); // Error.
+      ^" in e4 as{TypeError,ForNonNullableByDefault} self::I);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3>[#C11, #C12]
+  #C14 = self::E4 {index:#C1, _name:#C2}
+  #C15 = self::E4 {index:#C4, _name:#C5}
+  #C16 = <self::E4>[#C14, #C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_interfaces.dart:
+- E1. (from org-dartlang-testcase:///simple_interfaces.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_interfaces.dart:16:6)
+- E3. (from org-dartlang-testcase:///simple_interfaces.dart:21:6)
+- E4. (from org-dartlang-testcase:///simple_interfaces.dart:28:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.textual_outline.expect
new file mode 100644
index 0000000..b33af83
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+abstract class I {
+  void foo();
+}
+enum E1 implements I { one, two; void foo() {} }
+enum E2 implements I { one, two }
+enum E3 implements I? { one, two; void foo() {} }
+enum E4 { one, two; void foo() {} }
+bar(I i) {}
+test(E1 e1, E2 e2, E3 e3, E4 e4) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.expect
new file mode 100644
index 0000000..fbe74f9
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+//  - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//  - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//   bar(e4); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = #C16;
+  static const field self::E4 one = #C14;
+  static const field self::E4 two = #C15;
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+static method bar(self::I i) → dynamic {}
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic {
+  self::bar(e1);
+  self::bar(e2);
+  self::bar(e3);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+ - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+ - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+  bar(e4); // Error.
+      ^" in e4 as{TypeError,ForNonNullableByDefault} self::I);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = self::E4 {index:#C1, _name:#C2}
+  #C15 = self::E4 {index:#C4, _name:#C5}
+  #C16 = <self::E4*>[#C14, #C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_interfaces.dart:
+- E1. (from org-dartlang-testcase:///simple_interfaces.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_interfaces.dart:16:6)
+- E3. (from org-dartlang-testcase:///simple_interfaces.dart:21:6)
+- E4. (from org-dartlang-testcase:///simple_interfaces.dart:28:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.modular.expect
new file mode 100644
index 0000000..fbe74f9
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.modular.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+//  - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//  - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//   bar(e4); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = #C16;
+  static const field self::E4 one = #C14;
+  static const field self::E4 two = #C15;
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+static method bar(self::I i) → dynamic {}
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic {
+  self::bar(e1);
+  self::bar(e2);
+  self::bar(e3);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+ - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+ - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+  bar(e4); // Error.
+      ^" in e4 as{TypeError,ForNonNullableByDefault} self::I);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = self::E4 {index:#C1, _name:#C2}
+  #C15 = self::E4 {index:#C4, _name:#C5}
+  #C16 = <self::E4*>[#C14, #C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_interfaces.dart:
+- E1. (from org-dartlang-testcase:///simple_interfaces.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_interfaces.dart:16:6)
+- E3. (from org-dartlang-testcase:///simple_interfaces.dart:21:6)
+- E4. (from org-dartlang-testcase:///simple_interfaces.dart:28:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.outline.expect
new file mode 100644
index 0000000..02c7b48
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.outline.expect
@@ -0,0 +1,98 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::one, self::E1::two];
+  static const field self::E1 one = const self::E1::•(0, "one");
+  static const field self::E1 two = const self::E1::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void
+    ;
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = const <self::E2>[self::E2::one, self::E2::two];
+  static const field self::E2 one = const self::E2::•(0, "one");
+  static const field self::E2 two = const self::E2::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = const <self::E3>[self::E3::one, self::E3::two];
+  static const field self::E3 one = const self::E3::•(0, "one");
+  static const field self::E3 two = const self::E3::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void
+    ;
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = const <self::E4>[self::E4::one, self::E4::two];
+  static const field self::E4 one = const self::E4::•(0, "one");
+  static const field self::E4 two = const self::E4::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void
+    ;
+}
+static method bar(self::I i) → dynamic
+  ;
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_interfaces.dart:9:6 -> ListConstant(const <E1*>[const E1{_Enum.index: 0, _Enum._name: "one"}, const E1{_Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:10:3 -> InstanceConstant(const E1{_Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:11:3 -> InstanceConstant(const E1{_Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_interfaces.dart:16:6 -> ListConstant(const <E2*>[const E2{_Enum.index: 0, _Enum._name: "one"}, const E2{_Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:17:3 -> InstanceConstant(const E2{_Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:18:3 -> InstanceConstant(const E2{_Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_interfaces.dart:21:6 -> ListConstant(const <E3*>[const E3{_Enum.index: 0, _Enum._name: "one"}, const E3{_Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:22:3 -> InstanceConstant(const E3{_Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:23:3 -> InstanceConstant(const E3{_Enum.index: 1, _Enum._name: "two"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_interfaces.dart:28:6 -> ListConstant(const <E4*>[const E4{_Enum.index: 0, _Enum._name: "one"}, const E4{_Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:29:3 -> InstanceConstant(const E4{_Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_interfaces.dart:30:3 -> InstanceConstant(const E4{_Enum.index: 1, _Enum._name: "two"})
+Extra constant evaluation: evaluated: 32, effectively constant: 12
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.transformed.expect
new file mode 100644
index 0000000..fbe74f9
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart.weak.transformed.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:21:20: Error: Can't implement 'I' because it's marked with '?'.
+// enum E3 implements I? { // Error.
+//                    ^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:16:6: Error: The non-abstract class 'E2' is missing implementations for these members:
+//  - I.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// enum E2 implements I { // Error.
+//      ^^
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:6:8: Context: 'I.foo' is defined here.
+//   void foo();
+//        ^^^
+//
+// pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+//  - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//  - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+//   bar(e4); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class E1 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E1.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E2 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E2.${this.{core::_Enum::_name}{core::String}}";
+}
+class E3 extends core::_Enum implements self::I /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E3.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+class E4 extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E4> values = #C16;
+  static const field self::E4 one = #C14;
+  static const field self::E4 two = #C15;
+  const constructor •(core::int index, core::String name) → self::E4
+    : super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E4.${this.{core::_Enum::_name}{core::String}}";
+  method foo() → void {}
+}
+static method bar(self::I i) → dynamic {}
+static method test(self::E1 e1, self::E2 e2, self::E3 e3, self::E4 e4) → dynamic {
+  self::bar(e1);
+  self::bar(e2);
+  self::bar(e3);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart:41:7: Error: The argument type 'E4' can't be assigned to the parameter type 'I'.
+ - 'E4' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+ - 'I' is from 'pkg/front_end/testcases/enhanced_enums/simple_interfaces.dart'.
+  bar(e4); // Error.
+      ^" in e4 as{TypeError,ForNonNullableByDefault} self::I);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = self::E4 {index:#C1, _name:#C2}
+  #C15 = self::E4 {index:#C4, _name:#C5}
+  #C16 = <self::E4*>[#C14, #C15]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_interfaces.dart:
+- E1. (from org-dartlang-testcase:///simple_interfaces.dart:9:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_interfaces.dart:16:6)
+- E3. (from org-dartlang-testcase:///simple_interfaces.dart:21:6)
+- E4. (from org-dartlang-testcase:///simple_interfaces.dart:28:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart
new file mode 100644
index 0000000..81e592e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 {
+  String get foo => "foo";
+}
+
+class B {
+  int bar() => 42;
+}
+
+mixin M {
+  void set callOnAssignment(void Function() f) {
+    f();
+  }
+}
+
+enum E1 with A { one, two }
+
+enum E2 with A, B { one, two }
+
+enum E3 with M { one, two }
+
+expectEquals(x, y) {
+  if (x != y) {
+    throw "Expected '$x' and '$y' to be equal.";
+  }
+}
+
+expectThrows(void Function() f) {
+  try {
+    f();
+    throw "Expected function to throw.";
+  } catch (e) {}
+}
+
+void throwOnCall() {
+  throw 42;
+}
+
+main() {
+  expectEquals(E1.one.foo, "foo");
+  expectEquals(E1.two.foo, "foo");
+  expectEquals(E2.one.foo, "foo");
+  expectEquals(E2.two.foo, "foo");
+  expectEquals(E2.one.bar(), "bar");
+  expectEquals(E2.two.bar(), "bar");
+  expectThrows(E3.one.callOnAssignment = throwOnCall);
+  expectThrows(E3.two.callOnAssignment = throwOnCall);
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.expect
new file mode 100644
index 0000000..6e10e5c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method bar() → core::int
+    return 42;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+abstract class _E1&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super self::_E1&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+abstract class _E2&_Enum&A&B = self::_E2&_Enum&A with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  mixin-super-stub method bar() → core::int
+    return super.{self::B::bar}();
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super self::_E2&_Enum&A&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub set callOnAssignment(() → void f) → void
+    return super.{self::M::callOnAssignment} = f;
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super self::_E3&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method expectThrows(() → void f) → dynamic {
+  try {
+    f(){() → void};
+    throw "Expected function to throw.";
+  }
+  on core::Object catch(final core::Object e) {
+  }
+}
+static method throwOnCall() → void {
+  throw 42;
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C6.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C9.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectEquals(#C9.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectThrows(#C11.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+  self::expectThrows(#C12.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3>[#C11, #C12]
+  #C14 = static-tearoff self::throwOnCall
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_mixins.dart:
+- E1. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _E1&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A&B. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- E3. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
+- _E3&_Enum&M. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.transformed.expect
new file mode 100644
index 0000000..4a5994b
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.strong.transformed.expect
@@ -0,0 +1,138 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method bar() → core::int
+    return 42;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+abstract class _E1&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super self::_E1&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::String
+    return "foo";
+}
+abstract class _E2&_Enum&A&B extends self::_E2&_Enum&A implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  method bar() → core::int
+    return 42;
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super self::_E2&_Enum&A&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super self::_E3&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method expectThrows(() → void f) → dynamic {
+  try {
+    f(){() → void};
+    throw "Expected function to throw.";
+  }
+  on core::Object catch(final core::Object e) {
+  }
+}
+static method throwOnCall() → void {
+  throw 42;
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C6.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C9.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectEquals(#C9.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectThrows(#C11.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+  self::expectThrows(#C12.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3>[#C11, #C12]
+  #C14 = static-tearoff self::throwOnCall
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_mixins.dart:
+- E1. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _E1&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A&B. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- E3. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
+- _E3&_Enum&M. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.textual_outline.expect
new file mode 100644
index 0000000..8e3abd8
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.textual_outline.expect
@@ -0,0 +1,16 @@
+class A {
+  String get foo => "foo";
+}
+class B {
+  int bar() => 42;
+}
+mixin M {
+  void set callOnAssignment(void Function() f) {}
+}
+enum E1 with A { one, two }
+enum E2 with A, B { one, two }
+enum E3 with M { one, two }
+expectEquals(x, y) {}
+expectThrows(void Function() f) {}
+void throwOnCall() {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.expect
new file mode 100644
index 0000000..82c66e8
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method bar() → core::int
+    return 42;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+abstract class _E1&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super self::_E1&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+abstract class _E2&_Enum&A&B = self::_E2&_Enum&A with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  mixin-super-stub method bar() → core::int
+    return super.{self::B::bar}();
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super self::_E2&_Enum&A&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub set callOnAssignment(() → void f) → void
+    return super.{self::M::callOnAssignment} = f;
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super self::_E3&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method expectThrows(() → void f) → dynamic {
+  try {
+    f(){() → void};
+    throw "Expected function to throw.";
+  }
+  on core::Object catch(final core::Object e) {
+  }
+}
+static method throwOnCall() → void {
+  throw 42;
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C6.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C9.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectEquals(#C9.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectThrows(#C11.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+  self::expectThrows(#C12.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = static-tearoff self::throwOnCall
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_mixins.dart:
+- E1. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _E1&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A&B. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- E3. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
+- _E3&_Enum&M. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.modular.expect
new file mode 100644
index 0000000..82c66e8
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.modular.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method bar() → core::int
+    return 42;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+abstract class _E1&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super self::_E1&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+abstract class _E2&_Enum&A&B = self::_E2&_Enum&A with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  mixin-super-stub method bar() → core::int
+    return super.{self::B::bar}();
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super self::_E2&_Enum&A&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub set callOnAssignment(() → void f) → void
+    return super.{self::M::callOnAssignment} = f;
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super self::_E3&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method expectThrows(() → void f) → dynamic {
+  try {
+    f(){() → void};
+    throw "Expected function to throw.";
+  }
+  on core::Object catch(final core::Object e) {
+  }
+}
+static method throwOnCall() → void {
+  throw 42;
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C6.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C9.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectEquals(#C9.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectThrows(#C11.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+  self::expectThrows(#C12.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = static-tearoff self::throwOnCall
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_mixins.dart:
+- E1. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _E1&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A&B. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- E3. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
+- _E3&_Enum&M. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.outline.expect
new file mode 100644
index 0000000..abd958f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.outline.expect
@@ -0,0 +1,96 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  get foo() → core::String
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    ;
+  method bar() → core::int
+    ;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void
+    ;
+}
+abstract class _E1&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = const <self::E1>[self::E1::one, self::E1::two];
+  static const field self::E1 one = const self::E1::•(0, "one");
+  static const field self::E1 two = const self::E1::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E1
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A = core::_Enum with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub get foo() → core::String
+    return super.{self::A::foo};
+}
+abstract class _E2&_Enum&A&B = self::_E2&_Enum&A with self::B /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  mixin-super-stub method bar() → core::int
+    return super.{self::B::bar}();
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = const <self::E2>[self::E2::one, self::E2::two];
+  static const field self::E2 one = const self::E2::•(0, "one");
+  static const field self::E2 two = const self::E2::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E2
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M = core::_Enum with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  mixin-super-stub set callOnAssignment(() → void f) → void
+    return super.{self::M::callOnAssignment} = f;
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = const <self::E3>[self::E3::one, self::E3::two];
+  static const field self::E3 one = const self::E3::•(0, "one");
+  static const field self::E3 two = const self::E3::•(1, "two");
+  const constructor •(core::int index, core::String name) → self::E3
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic
+  ;
+static method expectThrows(() → void f) → dynamic
+  ;
+static method throwOnCall() → void
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_mixins.dart:19:6 -> ListConstant(const <E1*>[const E1{}, const E1{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:19:18 -> InstanceConstant(const E1{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:19:23 -> InstanceConstant(const E1{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_mixins.dart:21:6 -> ListConstant(const <E2*>[const E2{}, const E2{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:21:21 -> InstanceConstant(const E2{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:21:26 -> InstanceConstant(const E2{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///simple_mixins.dart:23:6 -> ListConstant(const <E3*>[const E3{}, const E3{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:23:18 -> InstanceConstant(const E3{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///simple_mixins.dart:23:23 -> InstanceConstant(const E3{})
+Extra constant evaluation: evaluated: 22, effectively constant: 9
diff --git a/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.transformed.expect
new file mode 100644
index 0000000..af40a65
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/simple_mixins.dart.weak.transformed.expect
@@ -0,0 +1,138 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  method bar() → core::int
+    return 42;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+abstract class _E1&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E1&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::String
+    return "foo";
+}
+class E1 extends self::_E1&_Enum&A /*isEnum*/  {
+  static const field core::List<self::E1> values = #C7;
+  static const field self::E1 one = #C3;
+  static const field self::E1 two = #C6;
+  const constructor •(core::int index, core::String name) → self::E1
+    : super self::_E1&_Enum&A::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E2&_Enum&A extends core::_Enum implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A
+    : super core::_Enum::•(index, _name)
+    ;
+  get foo() → core::String
+    return "foo";
+}
+abstract class _E2&_Enum&A&B extends self::_E2&_Enum&A implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E2&_Enum&A&B
+    : super self::_E2&_Enum&A::•(index, _name)
+    ;
+  method bar() → core::int
+    return 42;
+}
+class E2 extends self::_E2&_Enum&A&B /*isEnum*/  {
+  static const field core::List<self::E2> values = #C10;
+  static const field self::E2 one = #C8;
+  static const field self::E2 two = #C9;
+  const constructor •(core::int index, core::String name) → self::E2
+    : super self::_E2&_Enum&A&B::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+abstract class _E3&_Enum&M extends core::_Enum implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E3&_Enum&M
+    : super core::_Enum::•(index, _name)
+    ;
+  set callOnAssignment(() → void f) → void {
+    f(){() → void};
+  }
+}
+class E3 extends self::_E3&_Enum&M /*isEnum*/  {
+  static const field core::List<self::E3> values = #C13;
+  static const field self::E3 one = #C11;
+  static const field self::E3 two = #C12;
+  const constructor •(core::int index, core::String name) → self::E3
+    : super self::_E3&_Enum&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method expectEquals(dynamic x, dynamic y) → dynamic {
+  if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
+    throw "Expected '${x}' and '${y}' to be equal.";
+  }
+}
+static method expectThrows(() → void f) → dynamic {
+  try {
+    f(){() → void};
+    throw "Expected function to throw.";
+  }
+  on core::Object catch(final core::Object e) {
+  }
+}
+static method throwOnCall() → void {
+  throw 42;
+}
+static method main() → dynamic {
+  self::expectEquals(#C3.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C6.{self::_E1&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C9.{self::_E2&_Enum&A::foo}{core::String}, "foo");
+  self::expectEquals(#C8.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectEquals(#C9.{self::_E2&_Enum&A&B::bar}(){() → core::int}, "bar");
+  self::expectThrows(#C11.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+  self::expectThrows(#C12.{self::_E3&_Enum&M::callOnAssignment} = #C14);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "one"
+  #C3 = self::E1 {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "two"
+  #C6 = self::E1 {index:#C4, _name:#C5}
+  #C7 = <self::E1*>[#C3, #C6]
+  #C8 = self::E2 {index:#C1, _name:#C2}
+  #C9 = self::E2 {index:#C4, _name:#C5}
+  #C10 = <self::E2*>[#C8, #C9]
+  #C11 = self::E3 {index:#C1, _name:#C2}
+  #C12 = self::E3 {index:#C4, _name:#C5}
+  #C13 = <self::E3*>[#C11, #C12]
+  #C14 = static-tearoff self::throwOnCall
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_mixins.dart:
+- E1. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _E1&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:19:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- E2. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A&B. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- _E2&_Enum&A. (from org-dartlang-testcase:///simple_mixins.dart:21:6)
+- E3. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
+- _E3&_Enum&M. (from org-dartlang-testcase:///simple_mixins.dart:23:6)
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart
new file mode 100644
index 0000000..1e4851f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The test checks an execution path where _Enum as supertype was checked before
+// being resolved.
+
+mixin GM<T> on Enum {}
+
+mixin M on Object {}
+
+abstract class I {}
+
+abstract class GI<T> {}
+
+enum E<S extends num, T extends num>
+    with GM<T>, M
+    implements I, GI<S> { element }
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.expect
new file mode 100644
index 0000000..2a27047
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> = core::_Enum with self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> = self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = #C4;
+  static const field self::E<core::num, core::num> element = #C3;
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    : super self::_E&_Enum&GM&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E<core::num, core::num> {index:#C1, _name:#C2}
+  #C4 = <self::E<dynamic, dynamic>>[#C3]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///supertype_resolved_before_checking.dart:
+- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.transformed.expect
new file mode 100644
index 0000000..f14e87d
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.strong.transformed.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> extends core::_Enum implements self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> extends self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = #C4;
+  static const field self::E<core::num, core::num> element = #C3;
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    : super self::_E&_Enum&GM&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E<core::num, core::num> {index:#C1, _name:#C2}
+  #C4 = <self::E<dynamic, dynamic>>[#C3]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///supertype_resolved_before_checking.dart:
+- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.textual_outline.expect
new file mode 100644
index 0000000..5874d3e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+mixin GM<T> on Enum {}
+mixin M on Object {}
+abstract class I {}
+abstract class GI<T> {}
+enum E<S extends num, T extends num> with GM<T>, M implements I, GI<S> { element }
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.expect
new file mode 100644
index 0000000..93e970e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> = core::_Enum with self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> = self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = #C4;
+  static const field self::E<core::num, core::num> element = #C3;
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    : super self::_E&_Enum&GM&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E<core::num*, core::num*> {index:#C1, _name:#C2}
+  #C4 = <self::E<dynamic, dynamic>*>[#C3]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///supertype_resolved_before_checking.dart:
+- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.modular.expect
new file mode 100644
index 0000000..93e970e
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.modular.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> = core::_Enum with self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> = self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = #C4;
+  static const field self::E<core::num, core::num> element = #C3;
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    : super self::_E&_Enum&GM&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E<core::num*, core::num*> {index:#C1, _name:#C2}
+  #C4 = <self::E<dynamic, dynamic>*>[#C3]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///supertype_resolved_before_checking.dart:
+- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.outline.expect
new file mode 100644
index 0000000..7647f76
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.outline.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> = core::_Enum with self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> = self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> with self::M /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = const <self::E<dynamic, dynamic>>[self::E::element];
+  static const field self::E<core::num, core::num> element = const self::E::•<core::num, core::num>(0, "element");
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6 -> ListConstant(const <E<dynamic, dynamic>*>[const E<num*, num*>{}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///supertype_resolved_before_checking.dart:18:27 -> InstanceConstant(const E<num*, num*>{})
+Extra constant evaluation: evaluated: 6, effectively constant: 2
diff --git a/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.transformed.expect
new file mode 100644
index 0000000..af64aef
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/supertype_resolved_before_checking.dart.weak.transformed.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/  {
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+}
+abstract class GI<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::GI<self::GI::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class _E&_Enum&GM<S extends core::num, T extends core::num> extends core::_Enum implements self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
+    : super core::_Enum::•(index, _name)
+    ;
+}
+abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> extends self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
+    : super self::_E&_Enum&GM::•(index, _name)
+    ;
+}
+class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/  {
+  static const field core::List<self::E<core::num, core::num>> values = #C4;
+  static const field self::E<core::num, core::num> element = #C3;
+  const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
+    : super self::_E&_Enum&GM&M::•(index, name)
+    ;
+  method toString() → core::String
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = "element"
+  #C3 = self::E<core::num*, core::num*> {index:#C1, _name:#C2}
+  #C4 = <self::E<dynamic, dynamic>*>[#C3]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///supertype_resolved_before_checking.dart:
+- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/expression/a.dart b/pkg/front_end/testcases/expression/a.dart
new file mode 100644
index 0000000..63db95e
--- /dev/null
+++ b/pkg/front_end/testcases/expression/a.dart
@@ -0,0 +1,13 @@
+import "b.dart";
+
+main() {
+  Foo foo = new Foo();
+  print(foo.foo);
+}
+
+class Foo<E1> {
+  E1 get foo => null;
+  String get bar => "hello";
+}
+
+class Bar {}
diff --git a/pkg/front_end/testcases/expression/b.dart b/pkg/front_end/testcases/expression/b.dart
new file mode 100644
index 0000000..dc9ed0a
--- /dev/null
+++ b/pkg/front_end/testcases/expression/b.dart
@@ -0,0 +1,4 @@
+class Foo<E2> {
+  E2 get foo => null;
+  int get bar => 42;
+}
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml b/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml
new file mode 100644
index 0000000..30dce60
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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: "a.dart"
+import: "b.dart"
+definitions: []
+position: "a.dart#Foo"
+expression: |
+  foo
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml.expect b/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml.expect
new file mode 100644
index 0000000..e9f21d4
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_1.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{#lib1::Foo::foo}{#lib1::Foo::E1*};
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml b/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml
new file mode 100644
index 0000000..2fba111
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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: "a.dart"
+import: "b.dart"
+definitions: []
+position: "a.dart#Foo"
+expression: |
+  bar.length
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml.expect b/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml.expect
new file mode 100644
index 0000000..bdeb445
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_2.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{#lib1::Foo::bar}{dart.core::String*}.{dart.core::String::length}{dart.core::int*};
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml b/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml
new file mode 100644
index 0000000..f8eb3a8
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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: "a.dart"
+import: "b.dart"
+definitions: []
+position: "a.dart#Bar"
+expression: |
+  new Foo().bar.length
diff --git a/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml.expect b/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml.expect
new file mode 100644
index 0000000..01c5a65
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_import_3.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return new #lib1::Foo::•<dynamic>().{#lib1::Foo::bar}{dart.core::String*}.{dart.core::String::length}{dart.core::int*};
diff --git a/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml b/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml
new file mode 100644
index 0000000..23272e3
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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: "main.dart#E"
+expression: |
+  t
diff --git a/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml.expect b/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml.expect
new file mode 100644
index 0000000..d7463a7
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_t.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{main::E::t}{main::E::T*};
diff --git a/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml b/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml
new file mode 100644
index 0000000..343d2ba
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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:collection#LinkedList"
+expression: |
+  first
diff --git a/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml.expect b/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml.expect
new file mode 100644
index 0000000..9625a0d
--- /dev/null
+++ b/pkg/front_end/testcases/expression/inside_class_with_t_in_dart_collection.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /*isLegacy, from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{dart.collection::LinkedList::first}{dart.collection::LinkedList::E*};
diff --git a/pkg/front_end/testcases/expression/main.dart b/pkg/front_end/testcases/expression/main.dart
index f65db93..0c25d47 100644
--- a/pkg/front_end/testcases/expression/main.dart
+++ b/pkg/front_end/testcases/expression/main.dart
@@ -5,6 +5,9 @@
 library main;
 
 import 'dart:io' show File, Process, exit;
+import 'dart:collection';
+
+class Entry extends LinkedListEntry<Entry> {}
 
 List<String> listOfStrings = ["hello"];
 
@@ -92,3 +95,8 @@
     return 42;
   }
 }
+
+class E<T> {
+  T _t;
+  T get t => _t;
+}
diff --git a/pkg/front_end/testcases/general/conditional_import.dart b/pkg/front_end/testcases/general/conditional_import.dart
index 067c784..648ea9b 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart
+++ b/pkg/front_end/testcases/general/conditional_import.dart
@@ -8,7 +8,11 @@
     if (dart.library.html) "dart:html" as a;
 
 // All three libraries have an HttpRequest class.
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
@@ -20,6 +24,13 @@
 }
 
 testB(b.HttpRequest request) {
+  request.certificate; // ok (from dart:io)
+  request.response; // ok (from dart:io and dart:html)
+  request.readyState; // error (from dart:html)
+  request.hashCode; // ok
+}
+
+testC(c.HttpRequest request) {
   request.certificate; // error
   request.response; // error
   request.readyState; // error
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.textual_outline.expect b/pkg/front_end/testcases/general/conditional_import.dart.textual_outline.expect
index dc10727..a62da80 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.textual_outline.expect
@@ -1,11 +1,15 @@
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
 
 class HttpRequest {}
 
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/conditional_import.dart.textual_outline_modelled.expect
index 6e90f3d..7af9c6f 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.textual_outline_modelled.expect
@@ -1,4 +1,7 @@
-import "conditional_import.dart" if (dart.library.foo) "dart:foo" as b;
+import "conditional_import.dart" if (dart.library.foo) "dart:foo" as c;
+import "conditional_import.dart"
+    if (dart.library.html) "dart:html"
+    if (dart.library.io) "dart:io" as b;
 import "conditional_import.dart"
     if (dart.library.io) "dart:io"
     if (dart.library.html) "dart:html" as a;
@@ -8,4 +11,5 @@
 expect(expected, actual) {}
 testA(a.HttpRequest request) {}
 testB(b.HttpRequest request) {}
+testC(c.HttpRequest request) {}
 void main() {}
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.weak.expect b/pkg/front_end/testcases/general/conditional_import.dart.weak.expect
index 0ae3432..00999c9 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.weak.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'dart:_http'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error (from dart:html)
 //           ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:_http'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+//   request.readyState; // error (from dart:html)
+//           ^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -32,7 +38,8 @@
 import "dart:io" as io;
 
 import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:io" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -42,25 +49,35 @@
 static method testA(_ht::HttpRequest request) → dynamic {
   request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
   request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'dart:_http'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error (from dart:html)
           ^^^^^^^^^^" in request{<unresolved>}.readyState;
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(_ht::HttpRequest request) → dynamic {
+  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
+  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:_http'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+  request.readyState; // error (from dart:html)
+          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -69,8 +86,8 @@
 }
 static method main() → void {
   self::expect(true, #C1);
-  self::expect(false, #C1);
-  self::expect(false, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -78,5 +95,6 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
+  #C2 = false
 }
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.weak.modular.expect b/pkg/front_end/testcases/general/conditional_import.dart.weak.modular.expect
index 0ae3432..00999c9 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.weak.modular.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'dart:_http'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error (from dart:html)
 //           ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:_http'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+//   request.readyState; // error (from dart:html)
+//           ^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -32,7 +38,8 @@
 import "dart:io" as io;
 
 import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:io" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -42,25 +49,35 @@
 static method testA(_ht::HttpRequest request) → dynamic {
   request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
   request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'dart:_http'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error (from dart:html)
           ^^^^^^^^^^" in request{<unresolved>}.readyState;
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(_ht::HttpRequest request) → dynamic {
+  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
+  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:_http'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+  request.readyState; // error (from dart:html)
+          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -69,8 +86,8 @@
 }
 static method main() → void {
   self::expect(true, #C1);
-  self::expect(false, #C1);
-  self::expect(false, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -78,5 +95,6 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
+  #C2 = false
 }
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.weak.outline.expect b/pkg/front_end/testcases/general/conditional_import.dart.weak.outline.expect
index 17e396c..98d7644 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.weak.outline.expect
@@ -4,7 +4,8 @@
 import "dart:_http" as _ht;
 
 import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:io" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -12,7 +13,9 @@
 }
 static method testA(_ht::HttpRequest request) → dynamic
   ;
-static method testB(self::HttpRequest request) → dynamic
+static method testB(_ht::HttpRequest request) → dynamic
+  ;
+static method testC(self::HttpRequest request) → dynamic
   ;
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/general/conditional_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general/conditional_import.dart.weak.transformed.expect
index 0ae3432..00999c9 100644
--- a/pkg/front_end/testcases/general/conditional_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/conditional_import.dart.weak.transformed.expect
@@ -2,25 +2,31 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'dart:_http'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error (from dart:html)
 //           ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+//  - 'HttpRequest' is from 'dart:_http'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+//   request.readyState; // error (from dart:html)
+//           ^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
 //   request.certificate; // error
 //           ^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
 //   request.response; // error
 //           ^^^^^^^^
 //
-// pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+// pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
 //  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
 //   request.readyState; // error
@@ -32,7 +38,8 @@
 import "dart:io" as io;
 
 import "dart:io" as a;
-import "org-dartlang-testcase:///conditional_import.dart" as b;
+import "dart:io" as b;
+import "org-dartlang-testcase:///conditional_import.dart" as c;
 
 class HttpRequest extends core::Object {
   synthetic constructor •() → self::HttpRequest
@@ -42,25 +49,35 @@
 static method testA(_ht::HttpRequest request) → dynamic {
   request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
   request.{_ht::HttpRequest::response}{_ht::HttpResponse};
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:18:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:22:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'dart:_http'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error (from dart:html)
           ^^^^^^^^^^" in request{<unresolved>}.readyState;
   request.{core::Object::hashCode}{core::int};
 }
-static method testB(self::HttpRequest request) → dynamic {
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:23:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
+static method testB(_ht::HttpRequest request) → dynamic {
+  request.{_ht::HttpRequest::certificate}{io::X509Certificate?};
+  request.{_ht::HttpRequest::response}{_ht::HttpResponse};
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:29:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+ - 'HttpRequest' is from 'dart:_http'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
+  request.readyState; // error (from dart:html)
+          ^^^^^^^^^^" in request{<unresolved>}.readyState;
+  request.{core::Object::hashCode}{core::int};
+}
+static method testC(self::HttpRequest request) → dynamic {
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:34:11: Error: The getter 'certificate' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'certificate'.
   request.certificate; // error
           ^^^^^^^^^^^" in request{<unresolved>}.certificate;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:24:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:35:11: Error: The getter 'response' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'response'.
   request.response; // error
           ^^^^^^^^" in request{<unresolved>}.response;
-  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:25:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
+  invalid-expression "pkg/front_end/testcases/general/conditional_import.dart:36:11: Error: The getter 'readyState' isn't defined for the class 'HttpRequest'.
  - 'HttpRequest' is from 'pkg/front_end/testcases/general/conditional_import.dart'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'readyState'.
   request.readyState; // error
@@ -69,8 +86,8 @@
 }
 static method main() → void {
   self::expect(true, #C1);
-  self::expect(false, #C1);
-  self::expect(false, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
@@ -78,5 +95,6 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
+  #C2 = false
 }
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.expect
index be365f6..a0f8836 100644
--- a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.expect
@@ -34,7 +34,7 @@
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:11: Context: While analyzing:
@@ -182,7 +182,7 @@
 static const field self::Foo* foo1 = #C4;
 static const field self::Foo* foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo* foo3 = invalid-expression "This assertion failed with message: btw foo was false";
-static const field self::Foo* foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo* foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo* foo5 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.modular.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.modular.expect
index be365f6..a0f8836 100644
--- a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.modular.expect
@@ -34,7 +34,7 @@
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:11: Context: While analyzing:
@@ -182,7 +182,7 @@
 static const field self::Foo* foo1 = #C4;
 static const field self::Foo* foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo* foo3 = invalid-expression "This assertion failed with message: btw foo was false";
-static const field self::Foo* foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo* foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo* foo5 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.transformed.expect
index 8d10eb2..c635add 100644
--- a/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/const_asserts.dart:34:11: Context: While analyzing:
@@ -182,7 +182,7 @@
 static const field self::Foo* foo1 = #C4;
 static const field self::Foo* foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo* foo3 = invalid-expression "This assertion failed with message: btw foo was false";
-static const field self::Foo* foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo* foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo* foo5 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.expect
index 9f6cb29..9106d0c 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.expect
@@ -19,7 +19,7 @@
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:11: Context: While analyzing:
@@ -98,7 +98,7 @@
 static const field self::Foo foo1 = #C9;
 static const field self::Foo foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo foo3 = #C12;
-static const field self::Foo foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo foo5 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.modular.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.modular.expect
index 9f6cb29..9106d0c 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.modular.expect
@@ -19,7 +19,7 @@
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:11: Context: While analyzing:
@@ -98,7 +98,7 @@
 static const field self::Foo foo1 = #C9;
 static const field self::Foo foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo foo3 = #C12;
-static const field self::Foo foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo foo5 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.transformed.expect
index 0bcf7671..d6b50e0 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.weak.transformed.expect
@@ -19,7 +19,7 @@
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:24: Error: Constant evaluation error:
 // const Foo foo4 = const Foo.withInvalidMessage(42);
 //                        ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: This assertion failed with a non-String message.
 //   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
 //                                                        ^
 // pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:11: Context: While analyzing:
@@ -98,7 +98,7 @@
 static const field self::Foo foo1 = #C9;
 static const field self::Foo foo2 = invalid-expression "This assertion failed with message: x is not positive";
 static const field self::Foo foo3 = #C12;
-static const field self::Foo foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo foo4 = invalid-expression "This assertion failed with a non-String message.";
 static const field self::Foo foo5 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   const Foo.withInvalidCondition(this.x) : assert(x);
                                                   ^";
diff --git a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.expect b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.expect
index dfe0844..d038898 100644
--- a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.expect
+++ b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart:11:6: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // test(E e) {} // Error.
 //      ^
 //
diff --git a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.modular.expect b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.modular.expect
index dfe0844..d038898 100644
--- a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.modular.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart:11:6: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // test(E e) {} // Error.
 //      ^
 //
diff --git a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.outline.expect b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.outline.expect
index 7be45bb..05bcb32 100644
--- a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.outline.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart:11:6: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // test(E e) {} // Error.
 //      ^
 //
diff --git a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.transformed.expect b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.transformed.expect
index dfe0844..d038898 100644
--- a/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_type_when_experiment_not_enabled.dart:11:6: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // test(E e) {} // Error.
 //      ^
 //
diff --git a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.expect b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.expect
index 0c596cb..1fcab84f 100644
--- a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.expect
+++ b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart:9:11: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // extension type E on A {} // Error because of 'type'.
 //           ^^^^
 //
diff --git a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.modular.expect b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.modular.expect
index 0c596cb..1fcab84f 100644
--- a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.modular.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart:9:11: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // extension type E on A {} // Error because of 'type'.
 //           ^^^^
 //
diff --git a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.outline.expect b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.outline.expect
index 8b21c25..9141057 100644
--- a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.outline.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart:9:11: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // extension type E on A {} // Error because of 'type'.
 //           ^^^^
 //
diff --git a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.transformed.expect b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.transformed.expect
index 0c596cb..1fcab84f 100644
--- a/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/extension_types_feature_not_enabled.dart:9:11: Error: This requires the 'extension-types' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // extension type E on A {} // Error because of 'type'.
 //           ^^^^
 //
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect
index 6895041..d92782a 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect
@@ -40,7 +40,7 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect
index 6895041..d92782a 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect
@@ -40,7 +40,7 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
index 57cc30b..0765c4c 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
@@ -40,9 +40,9 @@
   set y(core::double* #v) → void
     return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C12.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #v);
   get next() → ffi::Pointer<self::Coordinate*>*
-    return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
+    return ffi::_fromAddress<self::Coordinate*>(ffi::_loadAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
   set next(ffi::Pointer<self::Coordinate*>* #v) → void
-    return ffi::_storeIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #v.{ffi::Pointer::address}{core::int});
+    return ffi::_storeAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #v.{ffi::Pointer::address}{core::int});
   @#C16
   static get /*isNonNullableByDefault*/ #sizeOf() → core::int*
     return #C19.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
@@ -59,22 +59,22 @@
   #C7 = core::pragma {name:#C1, options:#C6}
   #C8 = ffi::Double {}
   #C9 = 0
-  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.weak.expect b/pkg/front_end/testcases/general/hierarchy.dart.weak.expect
index 3c3d062..42fb0ba 100644
--- a/pkg/front_end/testcases/general/hierarchy.dart.weak.expect
+++ b/pkg/front_end/testcases/general/hierarchy.dart.weak.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
 // pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
 //  - A1.extendedInterfaceMember
 // Try to either
@@ -88,11 +93,6 @@
 //   void mixedInAndImplementedInterfaceMember() {}
 //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
-// Try removing one of the occurrences.
-// class A6 extends A1 implements A1 {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.weak.modular.expect b/pkg/front_end/testcases/general/hierarchy.dart.weak.modular.expect
index 3c3d062..42fb0ba 100644
--- a/pkg/front_end/testcases/general/hierarchy.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/hierarchy.dart.weak.modular.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
 // pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
 //  - A1.extendedInterfaceMember
 // Try to either
@@ -88,11 +93,6 @@
 //   void mixedInAndImplementedInterfaceMember() {}
 //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
-// Try removing one of the occurrences.
-// class A6 extends A1 implements A1 {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.weak.outline.expect b/pkg/front_end/testcases/general/hierarchy.dart.weak.outline.expect
index 66c5f61..f96deda 100644
--- a/pkg/front_end/testcases/general/hierarchy.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/hierarchy.dart.weak.outline.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
 // pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
 //  - A1.extendedInterfaceMember
 // Try to either
@@ -88,11 +93,6 @@
 //   void mixedInAndImplementedInterfaceMember() {}
 //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
-// Try removing one of the occurrences.
-// class A6 extends A1 implements A1 {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.weak.transformed.expect b/pkg/front_end/testcases/general/hierarchy.dart.weak.transformed.expect
index 2c99461f9..1b21721 100644
--- a/pkg/front_end/testcases/general/hierarchy.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/hierarchy.dart.weak.transformed.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
 // pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
 //  - A1.extendedInterfaceMember
 // Try to either
@@ -88,11 +93,6 @@
 //   void mixedInAndImplementedInterfaceMember() {}
 //        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
-// Try removing one of the occurrences.
-// class A6 extends A1 implements A1 {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/issue31767.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue31767.dart.weak.outline.expect
index d4d8c65..9e60bbc 100644
--- a/pkg/front_end/testcases/general/issue31767.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/issue31767.dart.weak.outline.expect
@@ -25,7 +25,7 @@
     ;
 }
 class D = self::C with self::M {
-  synthetic constructor foo(core::int* x, [core::int* y, core::int* z]) → self::D*
+  synthetic constructor foo(core::int* x, [core::int* y = 0, core::int* z = 0]) → self::D*
     : super self::C::foo(x, y, z)
     ;
   mixin-super-stub get w2() → core::int*
@@ -36,7 +36,7 @@
     ;
 }
 class E = iss::A with self::N {
-  synthetic constructor foo(core::int* x, [core::int* y, core::int* z, iss::_A* a]) → self::E*
+  synthetic constructor foo(core::int* x, [core::int* y = iss::_private, core::int* z = iss::_private, iss::_A* a = const iss::_A::•(5)]) → self::E*
     : super iss::A::foo(x, y, z, a)
     ;
   mixin-super-stub get w2() → core::int*
@@ -92,7 +92,10 @@
 
 
 Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///issue31767.dart:31:7 -> IntConstant(3)
+Evaluated: StaticGet @ org-dartlang-testcase:///issue31767.dart:31:7 -> IntConstant(3)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue31767.dart:31:7 -> InstanceConstant(const _A{_A.field: 5})
 Evaluated: StaticGet @ org-dartlang-testcase:///issue31767_lib.dart:14:25 -> IntConstant(3)
 Evaluated: StaticGet @ org-dartlang-testcase:///issue31767_lib.dart:14:43 -> IntConstant(3)
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue31767_lib.dart:14:68 -> InstanceConstant(const _A{_A.field: 5})
-Extra constant evaluation: evaluated: 13, effectively constant: 3
+Extra constant evaluation: evaluated: 16, effectively constant: 6
diff --git a/pkg/front_end/testcases/general/issue47994a.dart b/pkg/front_end/testcases/general/issue47994a.dart
new file mode 100644
index 0000000..a669064
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Const {
+  const Const();
+}
+
+class BuildAssert {
+  const BuildAssert(bool condition, [Object? message])
+      : assert(condition, message);
+}
+
+const _assert1 = BuildAssert(false);
+const _assert2 = BuildAssert(false, null);
+const _assert3 = BuildAssert(false, 'foo');
+const _assert4 = BuildAssert(false, 0);
+const _assert5 = BuildAssert(false, const {});
+const _assert6 = BuildAssert(false, #_symbol);
+const _assert7 = BuildAssert(false, const Const());
+
+void main() {}
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue47994a.dart.textual_outline.expect
new file mode 100644
index 0000000..11ad895
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+class Const {
+  const Const();
+}
+
+class BuildAssert {
+  const BuildAssert(bool condition, [Object? message])
+      : assert(condition, message);
+}
+
+const _assert1 = BuildAssert(false);
+const _assert2 = BuildAssert(false, null);
+const _assert3 = BuildAssert(false, 'foo');
+const _assert4 = BuildAssert(false, 0);
+const _assert5 = BuildAssert(false, const {});
+const _assert6 = BuildAssert(false, #_symbol);
+const _assert7 = BuildAssert(false, const Const());
+void main() {}
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue47994a.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..96343a0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class BuildAssert {
+  const BuildAssert(bool condition, [Object? message])
+      : assert(condition, message);
+}
+
+class Const {
+  const Const();
+}
+
+const _assert1 = BuildAssert(false);
+const _assert2 = BuildAssert(false, null);
+const _assert3 = BuildAssert(false, 'foo');
+const _assert4 = BuildAssert(false, 0);
+const _assert5 = BuildAssert(false, const {});
+const _assert6 = BuildAssert(false, #_symbol);
+const _assert7 = BuildAssert(false, const Const());
+void main() {}
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.weak.expect b/pkg/front_end/testcases/general/issue47994a.dart.weak.expect
new file mode 100644
index 0000000..af71fb3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.weak.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue47994a.dart:14:18: Error: Constant evaluation error:
+// const _assert1 = BuildAssert(false);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:14:7: Context: While analyzing:
+// const _assert1 = BuildAssert(false);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:15:18: Error: Constant evaluation error:
+// const _assert2 = BuildAssert(false, null);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:15:7: Context: While analyzing:
+// const _assert2 = BuildAssert(false, null);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:16:18: Error: Constant evaluation error:
+// const _assert3 = BuildAssert(false, 'foo');
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed with message: foo
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:16:7: Context: While analyzing:
+// const _assert3 = BuildAssert(false, 'foo');
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:17:18: Error: Constant evaluation error:
+// const _assert4 = BuildAssert(false, 0);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:17:7: Context: While analyzing:
+// const _assert4 = BuildAssert(false, 0);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:18:18: Error: Constant evaluation error:
+// const _assert5 = BuildAssert(false, const {});
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:18:7: Context: While analyzing:
+// const _assert5 = BuildAssert(false, const {});
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:19:18: Error: Constant evaluation error:
+// const _assert6 = BuildAssert(false, #_symbol);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:19:7: Context: While analyzing:
+// const _assert6 = BuildAssert(false, #_symbol);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:20:18: Error: Constant evaluation error:
+// const _assert7 = BuildAssert(false, const Const());
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:20:7: Context: While analyzing:
+// const _assert7 = BuildAssert(false, const Const());
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class BuildAssert extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::bool condition, [core::Object? message = #C1]) → self::BuildAssert
+    : assert(condition, message), super core::Object::•()
+    ;
+}
+static const field self::BuildAssert _assert1 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert2 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert3 = invalid-expression "This assertion failed with message: foo";
+static const field self::BuildAssert _assert4 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert5 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert6 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert7 = invalid-expression "This assertion failed with a non-String message.";
+static method main() → void {}
+
+constants  {
+  #C1 = null
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994a.dart:
+- BuildAssert. (from org-dartlang-testcase:///issue47994a.dart:10:9)
+- Const. (from org-dartlang-testcase:///issue47994a.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue47994a.dart.weak.modular.expect
new file mode 100644
index 0000000..af71fb3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.weak.modular.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue47994a.dart:14:18: Error: Constant evaluation error:
+// const _assert1 = BuildAssert(false);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:14:7: Context: While analyzing:
+// const _assert1 = BuildAssert(false);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:15:18: Error: Constant evaluation error:
+// const _assert2 = BuildAssert(false, null);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:15:7: Context: While analyzing:
+// const _assert2 = BuildAssert(false, null);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:16:18: Error: Constant evaluation error:
+// const _assert3 = BuildAssert(false, 'foo');
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed with message: foo
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:16:7: Context: While analyzing:
+// const _assert3 = BuildAssert(false, 'foo');
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:17:18: Error: Constant evaluation error:
+// const _assert4 = BuildAssert(false, 0);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:17:7: Context: While analyzing:
+// const _assert4 = BuildAssert(false, 0);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:18:18: Error: Constant evaluation error:
+// const _assert5 = BuildAssert(false, const {});
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:18:7: Context: While analyzing:
+// const _assert5 = BuildAssert(false, const {});
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:19:18: Error: Constant evaluation error:
+// const _assert6 = BuildAssert(false, #_symbol);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:19:7: Context: While analyzing:
+// const _assert6 = BuildAssert(false, #_symbol);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:20:18: Error: Constant evaluation error:
+// const _assert7 = BuildAssert(false, const Const());
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:20:7: Context: While analyzing:
+// const _assert7 = BuildAssert(false, const Const());
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class BuildAssert extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::bool condition, [core::Object? message = #C1]) → self::BuildAssert
+    : assert(condition, message), super core::Object::•()
+    ;
+}
+static const field self::BuildAssert _assert1 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert2 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert3 = invalid-expression "This assertion failed with message: foo";
+static const field self::BuildAssert _assert4 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert5 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert6 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert7 = invalid-expression "This assertion failed with a non-String message.";
+static method main() → void {}
+
+constants  {
+  #C1 = null
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994a.dart:
+- BuildAssert. (from org-dartlang-testcase:///issue47994a.dart:10:9)
+- Const. (from org-dartlang-testcase:///issue47994a.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue47994a.dart.weak.outline.expect
new file mode 100644
index 0000000..0347e2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class BuildAssert extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::bool condition, [core::Object? message]) → self::BuildAssert
+    : assert(condition, message), super core::Object::•()
+    ;
+}
+static const field self::BuildAssert _assert1 = const self::BuildAssert::•(false);
+static const field self::BuildAssert _assert2 = const self::BuildAssert::•(false, null);
+static const field self::BuildAssert _assert3 = const self::BuildAssert::•(false, "foo");
+static const field self::BuildAssert _assert4 = const self::BuildAssert::•(false, 0);
+static const field self::BuildAssert _assert5 = const self::BuildAssert::•(false, const <dynamic, dynamic>{});
+static const field self::BuildAssert _assert6 = const self::BuildAssert::•(false, #_symbol);
+static const field self::BuildAssert _assert7 = const self::BuildAssert::•(false, const self::Const::•());
+static method main() → void
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MapLiteral @ org-dartlang-testcase:///issue47994a.dart:18:37 -> MapConstant(const <dynamic, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///issue47994a.dart:19:37 -> SymbolConstant(#_symbol)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue47994a.dart:20:43 -> InstanceConstant(const Const{})
+Extra constant evaluation: evaluated: 12, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/issue47994a.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue47994a.dart.weak.transformed.expect
new file mode 100644
index 0000000..af71fb3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994a.dart.weak.transformed.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue47994a.dart:14:18: Error: Constant evaluation error:
+// const _assert1 = BuildAssert(false);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:14:7: Context: While analyzing:
+// const _assert1 = BuildAssert(false);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:15:18: Error: Constant evaluation error:
+// const _assert2 = BuildAssert(false, null);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed.
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:15:7: Context: While analyzing:
+// const _assert2 = BuildAssert(false, null);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:16:18: Error: Constant evaluation error:
+// const _assert3 = BuildAssert(false, 'foo');
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:16: Context: This assertion failed with message: foo
+//       : assert(condition, message);
+//                ^
+// pkg/front_end/testcases/general/issue47994a.dart:16:7: Context: While analyzing:
+// const _assert3 = BuildAssert(false, 'foo');
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:17:18: Error: Constant evaluation error:
+// const _assert4 = BuildAssert(false, 0);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:17:7: Context: While analyzing:
+// const _assert4 = BuildAssert(false, 0);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:18:18: Error: Constant evaluation error:
+// const _assert5 = BuildAssert(false, const {});
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:18:7: Context: While analyzing:
+// const _assert5 = BuildAssert(false, const {});
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:19:18: Error: Constant evaluation error:
+// const _assert6 = BuildAssert(false, #_symbol);
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:19:7: Context: While analyzing:
+// const _assert6 = BuildAssert(false, #_symbol);
+//       ^
+//
+// pkg/front_end/testcases/general/issue47994a.dart:20:18: Error: Constant evaluation error:
+// const _assert7 = BuildAssert(false, const Const());
+//                  ^
+// pkg/front_end/testcases/general/issue47994a.dart:11:27: Context: This assertion failed with a non-String message.
+//       : assert(condition, message);
+//                           ^
+// pkg/front_end/testcases/general/issue47994a.dart:20:7: Context: While analyzing:
+// const _assert7 = BuildAssert(false, const Const());
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class BuildAssert extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::bool condition, [core::Object? message = #C1]) → self::BuildAssert
+    : assert(condition, message), super core::Object::•()
+    ;
+}
+static const field self::BuildAssert _assert1 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert2 = invalid-expression "This assertion failed.";
+static const field self::BuildAssert _assert3 = invalid-expression "This assertion failed with message: foo";
+static const field self::BuildAssert _assert4 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert5 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert6 = invalid-expression "This assertion failed with a non-String message.";
+static const field self::BuildAssert _assert7 = invalid-expression "This assertion failed with a non-String message.";
+static method main() → void {}
+
+constants  {
+  #C1 = null
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994a.dart:
+- BuildAssert. (from org-dartlang-testcase:///issue47994a.dart:10:9)
+- Const. (from org-dartlang-testcase:///issue47994a.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue47994b.dart b/pkg/front_end/testcases/general/issue47994b.dart
new file mode 100644
index 0000000..1fbaf90
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Const {
+  const Const();
+}
+
+class Class {
+  const Class(Object? message) : assert(false, message);
+}
+
+main() {
+  expect(null, test(() {
+    assert(false);
+  }));
+  expect(null, test(() {
+    assert(false, null);
+  }));
+  expect('foo', test(() {
+    assert(false, 'foo');
+  }));
+  expect(0, test(() {
+    assert(false, 0);
+  }));
+  expect(const {}, test(() {
+    assert(false, const {});
+  }));
+  expect(#_symbol, test(() {
+    assert(false, #_symbol);
+  }));
+  expect(const Const(), test(() {
+    assert(false, const Const());
+  }));
+
+  expect(null, test(() {
+    Class(null);
+  }));
+  expect('foo', test(() {
+    Class('foo');
+  }));
+  expect(0, test(() {
+    Class(0);
+  }));
+  expect(const {}, test(() {
+    Class(const {});
+  }));
+  expect(#_symbol, test(() {
+    Class(#_symbol);
+  }));
+  expect(const Const(), test(() {
+    Class(const Const());
+  }));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+Object? test(void Function() f) {
+  try {
+    f();
+  } on AssertionError catch (e) {
+    print(e);
+    return e.message;
+  } catch (e) {
+    throw 'Unexpected exception $e (${e.runtimeType}';
+  }
+  throw 'Missing exception';
+}
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue47994b.dart.textual_outline.expect
new file mode 100644
index 0000000..e522fca
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+class Const {
+  const Const();
+}
+
+class Class {
+  const Class(Object? message) : assert(false, message);
+}
+
+main() {}
+expect(expected, actual) {}
+Object? test(void Function() f) {}
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue47994b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..84a681d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+Object? test(void Function() f) {}
+
+class Class {
+  const Class(Object? message) : assert(false, message);
+}
+
+class Const {
+  const Const();
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.weak.expect b/pkg/front_end/testcases/general/issue47994b.dart.weak.expect
new file mode 100644
index 0000000..94d8be3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.weak.expect
@@ -0,0 +1,84 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class Class extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::Object? message) → self::Class
+    : assert(false, message), super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::expect(null, self::test(() → void {
+    assert(false);
+  }));
+  self::expect(null, self::test(() → void {
+    assert(false, null);
+  }));
+  self::expect("foo", self::test(() → void {
+    assert(false, "foo");
+  }));
+  self::expect(0, self::test(() → void {
+    assert(false, 0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    assert(false, #C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    assert(false, #C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    assert(false, #C3);
+  }));
+  self::expect(null, self::test(() → void {
+    new self::Class::•(null);
+  }));
+  self::expect("foo", self::test(() → void {
+    new self::Class::•("foo");
+  }));
+  self::expect(0, self::test(() → void {
+    new self::Class::•(0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    new self::Class::•(#C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    new self::Class::•(#C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    new self::Class::•(#C3);
+  }));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method test(() → void f) → core::Object? {
+  try {
+    f(){() → void};
+  }
+  on core::AssertionError catch(final core::AssertionError e) {
+    core::print(e);
+    return e.{core::AssertionError::message}{core::Object?};
+  }
+  on core::Object catch(final core::Object e) {
+    throw "Unexpected exception ${e} (${e.{core::Object::runtimeType}{core::Type}}";
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = <dynamic, dynamic>{)
+  #C2 = #org-dartlang-testcase:///issue47994b.dart::_symbol
+  #C3 = self::Const {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994b.dart:
+- Const. (from org-dartlang-testcase:///issue47994b.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue47994b.dart.weak.modular.expect
new file mode 100644
index 0000000..94d8be3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.weak.modular.expect
@@ -0,0 +1,84 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class Class extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::Object? message) → self::Class
+    : assert(false, message), super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::expect(null, self::test(() → void {
+    assert(false);
+  }));
+  self::expect(null, self::test(() → void {
+    assert(false, null);
+  }));
+  self::expect("foo", self::test(() → void {
+    assert(false, "foo");
+  }));
+  self::expect(0, self::test(() → void {
+    assert(false, 0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    assert(false, #C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    assert(false, #C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    assert(false, #C3);
+  }));
+  self::expect(null, self::test(() → void {
+    new self::Class::•(null);
+  }));
+  self::expect("foo", self::test(() → void {
+    new self::Class::•("foo");
+  }));
+  self::expect(0, self::test(() → void {
+    new self::Class::•(0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    new self::Class::•(#C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    new self::Class::•(#C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    new self::Class::•(#C3);
+  }));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method test(() → void f) → core::Object? {
+  try {
+    f(){() → void};
+  }
+  on core::AssertionError catch(final core::AssertionError e) {
+    core::print(e);
+    return e.{core::AssertionError::message}{core::Object?};
+  }
+  on core::Object catch(final core::Object e) {
+    throw "Unexpected exception ${e} (${e.{core::Object::runtimeType}{core::Type}}";
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = <dynamic, dynamic>{)
+  #C2 = #org-dartlang-testcase:///issue47994b.dart::_symbol
+  #C3 = self::Const {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994b.dart:
+- Const. (from org-dartlang-testcase:///issue47994b.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue47994b.dart.weak.outline.expect
new file mode 100644
index 0000000..ebe1a07
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.weak.outline.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class Class extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::Object? message) → self::Class
+    : assert(false, message), super core::Object::•()
+    ;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method test(() → void f) → core::Object?
+  ;
diff --git a/pkg/front_end/testcases/general/issue47994b.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue47994b.dart.weak.transformed.expect
new file mode 100644
index 0000000..94d8be3
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47994b.dart.weak.transformed.expect
@@ -0,0 +1,84 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Const extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::Const
+    : super core::Object::•()
+    ;
+}
+class Class extends core::Object /*hasConstConstructor*/  {
+  const constructor •(core::Object? message) → self::Class
+    : assert(false, message), super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::expect(null, self::test(() → void {
+    assert(false);
+  }));
+  self::expect(null, self::test(() → void {
+    assert(false, null);
+  }));
+  self::expect("foo", self::test(() → void {
+    assert(false, "foo");
+  }));
+  self::expect(0, self::test(() → void {
+    assert(false, 0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    assert(false, #C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    assert(false, #C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    assert(false, #C3);
+  }));
+  self::expect(null, self::test(() → void {
+    new self::Class::•(null);
+  }));
+  self::expect("foo", self::test(() → void {
+    new self::Class::•("foo");
+  }));
+  self::expect(0, self::test(() → void {
+    new self::Class::•(0);
+  }));
+  self::expect(#C1, self::test(() → void {
+    new self::Class::•(#C1);
+  }));
+  self::expect(#C2, self::test(() → void {
+    new self::Class::•(#C2);
+  }));
+  self::expect(#C3, self::test(() → void {
+    new self::Class::•(#C3);
+  }));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method test(() → void f) → core::Object? {
+  try {
+    f(){() → void};
+  }
+  on core::AssertionError catch(final core::AssertionError e) {
+    core::print(e);
+    return e.{core::AssertionError::message}{core::Object?};
+  }
+  on core::Object catch(final core::Object e) {
+    throw "Unexpected exception ${e} (${e.{core::Object::runtimeType}{core::Type}}";
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = <dynamic, dynamic>{)
+  #C2 = #org-dartlang-testcase:///issue47994b.dart::_symbol
+  #C3 = self::Const {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47994b.dart:
+- Const. (from org-dartlang-testcase:///issue47994b.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue48090.dart b/pkg/front_end/testcases/general/issue48090.dart
new file mode 100644
index 0000000..5164441
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+void main() {
+  String debugName = Isolate.current.debugName ?? ''; // ok
+}
+
+void test() {
+  String debugName = Isolate.current.debugName; // error
+}
diff --git a/pkg/front_end/testcases/general/issue48090.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue48090.dart.textual_outline.expect
new file mode 100644
index 0000000..9ab0a0f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+import 'dart:isolate';
+
+void main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/general/issue48090.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue48090.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9ab0a0f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+import 'dart:isolate';
+
+void main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/general/issue48090.dart.weak.expect b/pkg/front_end/testcases/general/issue48090.dart.weak.expect
new file mode 100644
index 0000000..9a0be82
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+//   String debugName = Isolate.current.debugName; // error
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:isolate" as iso;
+
+import "dart:isolate";
+
+static method main() → void {
+  core::String debugName = let final core::String? #t1 = iso::Isolate::current.{iso::Isolate::debugName}{core::String?} in #t1 == null ?{core::String} "" : #t1{core::String};
+}
+static method test() → void {
+  core::String debugName = invalid-expression "pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+  String debugName = Isolate.current.debugName; // error
+                                     ^" in iso::Isolate::current.{iso::Isolate::debugName}{core::String?} as{TypeError,ForNonNullableByDefault} core::String;
+}
diff --git a/pkg/front_end/testcases/general/issue48090.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue48090.dart.weak.modular.expect
new file mode 100644
index 0000000..9a0be82
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.weak.modular.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+//   String debugName = Isolate.current.debugName; // error
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:isolate" as iso;
+
+import "dart:isolate";
+
+static method main() → void {
+  core::String debugName = let final core::String? #t1 = iso::Isolate::current.{iso::Isolate::debugName}{core::String?} in #t1 == null ?{core::String} "" : #t1{core::String};
+}
+static method test() → void {
+  core::String debugName = invalid-expression "pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+  String debugName = Isolate.current.debugName; // error
+                                     ^" in iso::Isolate::current.{iso::Isolate::debugName}{core::String?} as{TypeError,ForNonNullableByDefault} core::String;
+}
diff --git a/pkg/front_end/testcases/general/issue48090.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue48090.dart.weak.outline.expect
new file mode 100644
index 0000000..bc35ad4
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.weak.outline.expect
@@ -0,0 +1,9 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:isolate";
+
+static method main() → void
+  ;
+static method test() → void
+  ;
diff --git a/pkg/front_end/testcases/general/issue48090.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue48090.dart.weak.transformed.expect
new file mode 100644
index 0000000..7288854
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48090.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+//   String debugName = Isolate.current.debugName; // error
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:isolate" as iso;
+
+import "dart:isolate";
+
+static method main() → void {
+  core::String debugName = let final core::String? #t1 = iso::Isolate::current.{iso::Isolate::debugName}{core::String?} in #t1 == null ?{core::String} "" : #t1{core::String};
+}
+static method test() → void {
+  core::String debugName = invalid-expression "pkg/front_end/testcases/general/issue48090.dart:12:38: Error: A value of type 'String?' can't be assigned to a variable of type 'String' because 'String?' is nullable and 'String' isn't.
+  String debugName = Isolate.current.debugName; // error
+                                     ^" in iso::Isolate::current.{iso::Isolate::debugName}{core::String?};
+}
diff --git a/pkg/front_end/testcases/general/issue48131.dart b/pkg/front_end/testcases/general/issue48131.dart
new file mode 100644
index 0000000..cf58ea6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {
+  new B<Object>().foo<int>();
+}
diff --git a/pkg/front_end/testcases/general/issue48131.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue48131.dart.textual_outline.expect
new file mode 100644
index 0000000..2e5ec26
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/general/issue48131.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue48131.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2e5ec26
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/general/issue48131.dart.weak.expect b/pkg/front_end/testcases/general/issue48131.dart.weak.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.weak.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/general/issue48131.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue48131.dart.weak.modular.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.weak.modular.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/general/issue48131.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue48131.dart.weak.outline.expect
new file mode 100644
index 0000000..8eabec2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void
+    ;
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/general/issue48131.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue48131.dart.weak.transformed.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48131.dart.weak.transformed.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/general/issue48148.dart b/pkg/front_end/testcases/general/issue48148.dart
new file mode 100644
index 0000000..0cf1e2c
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const HInvalid invalidExample = HInvalidComposite(
+  [
+    HInvalidLeaf(0),
+    HInvalidChild(
+      HInvalidLeaf(0),
+    ),
+    HInvalidError("error message"),
+  ],
+);
+
+typedef HInvalid = HBase<HKindInvalid>;
+typedef HInvalidComposite<CHILD extends HInvalid>
+    = HBaseComposite<HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends HInvalid> = HBaseChild<HKindInvalid, CHILD>;
+typedef HInvalidLeaf = HBaseLeaf<HKindInvalid>;
+typedef HInvalidError = HBaseError<HKindInvalid>;
+
+abstract class HBase<HKT extends HKind> implements Kind<HKT> {}
+
+class HBaseComposite<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  final List<CHILD> children;
+
+  const HBaseComposite(
+    final this.children,
+  );
+}
+
+class HBaseChild<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  final CHILD child;
+
+  const HBaseChild(
+    final this.child,
+  );
+}
+
+class HBaseLeaf<HKT extends HKindValid> implements HBase<HKT> {
+  final int data;
+
+  const HBaseLeaf(
+    final this.data,
+  );
+}
+
+class HBaseError<HKT extends HKindInvalid> implements HBase<HKT> {
+  final String errorMessage;
+
+  const HBaseError(
+    final this.errorMessage,
+  );
+}
+
+abstract class Kind<HKT extends HKind> {}
+
+abstract class HKind {}
+
+abstract class HKindValid implements HKind {}
+
+abstract class HKindInvalid implements HKindValid {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue48148.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue48148.dart.textual_outline.expect
new file mode 100644
index 0000000..14cef3d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.textual_outline.expect
@@ -0,0 +1,57 @@
+const HInvalid invalidExample = HInvalidComposite(
+  [
+    HInvalidLeaf(0),
+    HInvalidChild(
+      HInvalidLeaf(0),
+    ),
+    HInvalidError("error message"),
+  ],
+);
+typedef HInvalid = HBase<HKindInvalid>;
+typedef HInvalidComposite<CHILD extends HInvalid>
+    = HBaseComposite<HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends HInvalid> = HBaseChild<HKindInvalid, CHILD>;
+typedef HInvalidLeaf = HBaseLeaf<HKindInvalid>;
+typedef HInvalidError = HBaseError<HKindInvalid>;
+
+abstract class HBase<HKT extends HKind> implements Kind<HKT> {}
+
+class HBaseComposite<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  final List<CHILD> children;
+  const HBaseComposite(
+    final this.children,
+  );
+}
+
+class HBaseChild<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  final CHILD child;
+  const HBaseChild(
+    final this.child,
+  );
+}
+
+class HBaseLeaf<HKT extends HKindValid> implements HBase<HKT> {
+  final int data;
+  const HBaseLeaf(
+    final this.data,
+  );
+}
+
+class HBaseError<HKT extends HKindInvalid> implements HBase<HKT> {
+  final String errorMessage;
+  const HBaseError(
+    final this.errorMessage,
+  );
+}
+
+abstract class Kind<HKT extends HKind> {}
+
+abstract class HKind {}
+
+abstract class HKindValid implements HKind {}
+
+abstract class HKindInvalid implements HKindValid {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue48148.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue48148.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..937cb18
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.textual_outline_modelled.expect
@@ -0,0 +1,56 @@
+abstract class HBase<HKT extends HKind> implements Kind<HKT> {}
+
+abstract class HKind {}
+
+abstract class HKindInvalid implements HKindValid {}
+
+abstract class HKindValid implements HKind {}
+
+abstract class Kind<HKT extends HKind> {}
+
+class HBaseChild<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  const HBaseChild(
+    final this.child,
+  );
+  final CHILD child;
+}
+
+class HBaseComposite<HKT extends HKindValid, CHILD extends HBase<HKT>>
+    implements HBase<HKT> {
+  const HBaseComposite(
+    final this.children,
+  );
+  final List<CHILD> children;
+}
+
+class HBaseError<HKT extends HKindInvalid> implements HBase<HKT> {
+  const HBaseError(
+    final this.errorMessage,
+  );
+  final String errorMessage;
+}
+
+class HBaseLeaf<HKT extends HKindValid> implements HBase<HKT> {
+  const HBaseLeaf(
+    final this.data,
+  );
+  final int data;
+}
+
+const HInvalid invalidExample = HInvalidComposite(
+  [
+    HInvalidLeaf(0),
+    HInvalidChild(
+      HInvalidLeaf(0),
+    ),
+    HInvalidError("error message"),
+  ],
+);
+main() {}
+typedef HInvalid = HBase<HKindInvalid>;
+typedef HInvalidChild<CHILD extends HInvalid> = HBaseChild<HKindInvalid, CHILD>;
+typedef HInvalidComposite<CHILD extends HInvalid>
+    = HBaseComposite<HKindInvalid, CHILD>;
+typedef HInvalidError = HBaseError<HKindInvalid>;
+typedef HInvalidLeaf = HBaseLeaf<HKindInvalid>;
diff --git a/pkg/front_end/testcases/general/issue48148.dart.weak.expect b/pkg/front_end/testcases/general/issue48148.dart.weak.expect
new file mode 100644
index 0000000..dd37ee2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.weak.expect
@@ -0,0 +1,83 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef HInvalid = self::HBase<self::HKindInvalid>;
+typedef HInvalidComposite<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseComposite<self::HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseChild<self::HKindInvalid, CHILD>;
+typedef HInvalidLeaf = self::HBaseLeaf<self::HKindInvalid>;
+typedef HInvalidError = self::HBaseError<self::HKindInvalid>;
+abstract class HBase<HKT extends self::HKind> extends core::Object implements self::Kind<self::HBase::HKT> {
+  synthetic constructor •() → self::HBase<self::HBase::HKT>
+    : super core::Object::•()
+    ;
+}
+class HBaseComposite<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseComposite::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseComposite::HKT> /*hasConstConstructor*/  {
+  final field core::List<self::HBaseComposite::CHILD> children;
+  const constructor •(final core::List<self::HBaseComposite::CHILD> children) → self::HBaseComposite<self::HBaseComposite::HKT, self::HBaseComposite::CHILD>
+    : self::HBaseComposite::children = children, super core::Object::•()
+    ;
+}
+class HBaseChild<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseChild::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseChild::HKT> /*hasConstConstructor*/  {
+  final field self::HBaseChild::CHILD child;
+  const constructor •(final self::HBaseChild::CHILD child) → self::HBaseChild<self::HBaseChild::HKT, self::HBaseChild::CHILD>
+    : self::HBaseChild::child = child, super core::Object::•()
+    ;
+}
+class HBaseLeaf<HKT extends self::HKindValid> extends core::Object implements self::HBase<self::HBaseLeaf::HKT> /*hasConstConstructor*/  {
+  final field core::int data;
+  const constructor •(final core::int data) → self::HBaseLeaf<self::HBaseLeaf::HKT>
+    : self::HBaseLeaf::data = data, super core::Object::•()
+    ;
+}
+class HBaseError<HKT extends self::HKindInvalid> extends core::Object implements self::HBase<self::HBaseError::HKT> /*hasConstConstructor*/  {
+  final field core::String errorMessage;
+  const constructor •(final core::String errorMessage) → self::HBaseError<self::HBaseError::HKT>
+    : self::HBaseError::errorMessage = errorMessage, super core::Object::•()
+    ;
+}
+abstract class Kind<HKT extends self::HKind> extends core::Object {
+  synthetic constructor •() → self::Kind<self::Kind::HKT>
+    : super core::Object::•()
+    ;
+}
+abstract class HKind extends core::Object {
+  synthetic constructor •() → self::HKind
+    : super core::Object::•()
+    ;
+}
+abstract class HKindValid extends core::Object implements self::HKind {
+  synthetic constructor •() → self::HKindValid
+    : super core::Object::•()
+    ;
+}
+abstract class HKindInvalid extends core::Object implements self::HKindValid {
+  synthetic constructor •() → self::HKindInvalid
+    : super core::Object::•()
+    ;
+}
+static const field self::HBase<self::HKindInvalid> invalidExample = #C7;
+static method main() → dynamic {}
+static method _#HInvalidComposite#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(core::List<self::_#HInvalidComposite#new#tearOff::CHILD> children) → self::HBaseComposite<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>
+  return new self::HBaseComposite::•<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>(children);
+static method _#HInvalidChild#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(self::_#HInvalidChild#new#tearOff::CHILD child) → self::HBaseChild<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>
+  return new self::HBaseChild::•<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>(child);
+
+constants  {
+  #C1 = 0
+  #C2 = self::HBaseLeaf<self::HKindInvalid*> {data:#C1}
+  #C3 = self::HBaseChild<self::HKindInvalid*, self::HBaseLeaf<self::HKindInvalid*>*> {child:#C2}
+  #C4 = "error message"
+  #C5 = self::HBaseError<self::HKindInvalid*> {errorMessage:#C4}
+  #C6 = <self::HBase<self::HKindInvalid*>*>[#C2, #C3, #C5]
+  #C7 = self::HBaseComposite<self::HKindInvalid*, self::HBase<self::HKindInvalid*>*> {children:#C6}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48148.dart:
+- HBaseLeaf. (from org-dartlang-testcase:///issue48148.dart:45:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- HBaseChild. (from org-dartlang-testcase:///issue48148.dart:37:9)
+- HBaseError. (from org-dartlang-testcase:///issue48148.dart:53:9)
+- HBaseComposite. (from org-dartlang-testcase:///issue48148.dart:28:9)
diff --git a/pkg/front_end/testcases/general/issue48148.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue48148.dart.weak.modular.expect
new file mode 100644
index 0000000..dd37ee2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.weak.modular.expect
@@ -0,0 +1,83 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef HInvalid = self::HBase<self::HKindInvalid>;
+typedef HInvalidComposite<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseComposite<self::HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseChild<self::HKindInvalid, CHILD>;
+typedef HInvalidLeaf = self::HBaseLeaf<self::HKindInvalid>;
+typedef HInvalidError = self::HBaseError<self::HKindInvalid>;
+abstract class HBase<HKT extends self::HKind> extends core::Object implements self::Kind<self::HBase::HKT> {
+  synthetic constructor •() → self::HBase<self::HBase::HKT>
+    : super core::Object::•()
+    ;
+}
+class HBaseComposite<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseComposite::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseComposite::HKT> /*hasConstConstructor*/  {
+  final field core::List<self::HBaseComposite::CHILD> children;
+  const constructor •(final core::List<self::HBaseComposite::CHILD> children) → self::HBaseComposite<self::HBaseComposite::HKT, self::HBaseComposite::CHILD>
+    : self::HBaseComposite::children = children, super core::Object::•()
+    ;
+}
+class HBaseChild<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseChild::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseChild::HKT> /*hasConstConstructor*/  {
+  final field self::HBaseChild::CHILD child;
+  const constructor •(final self::HBaseChild::CHILD child) → self::HBaseChild<self::HBaseChild::HKT, self::HBaseChild::CHILD>
+    : self::HBaseChild::child = child, super core::Object::•()
+    ;
+}
+class HBaseLeaf<HKT extends self::HKindValid> extends core::Object implements self::HBase<self::HBaseLeaf::HKT> /*hasConstConstructor*/  {
+  final field core::int data;
+  const constructor •(final core::int data) → self::HBaseLeaf<self::HBaseLeaf::HKT>
+    : self::HBaseLeaf::data = data, super core::Object::•()
+    ;
+}
+class HBaseError<HKT extends self::HKindInvalid> extends core::Object implements self::HBase<self::HBaseError::HKT> /*hasConstConstructor*/  {
+  final field core::String errorMessage;
+  const constructor •(final core::String errorMessage) → self::HBaseError<self::HBaseError::HKT>
+    : self::HBaseError::errorMessage = errorMessage, super core::Object::•()
+    ;
+}
+abstract class Kind<HKT extends self::HKind> extends core::Object {
+  synthetic constructor •() → self::Kind<self::Kind::HKT>
+    : super core::Object::•()
+    ;
+}
+abstract class HKind extends core::Object {
+  synthetic constructor •() → self::HKind
+    : super core::Object::•()
+    ;
+}
+abstract class HKindValid extends core::Object implements self::HKind {
+  synthetic constructor •() → self::HKindValid
+    : super core::Object::•()
+    ;
+}
+abstract class HKindInvalid extends core::Object implements self::HKindValid {
+  synthetic constructor •() → self::HKindInvalid
+    : super core::Object::•()
+    ;
+}
+static const field self::HBase<self::HKindInvalid> invalidExample = #C7;
+static method main() → dynamic {}
+static method _#HInvalidComposite#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(core::List<self::_#HInvalidComposite#new#tearOff::CHILD> children) → self::HBaseComposite<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>
+  return new self::HBaseComposite::•<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>(children);
+static method _#HInvalidChild#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(self::_#HInvalidChild#new#tearOff::CHILD child) → self::HBaseChild<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>
+  return new self::HBaseChild::•<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>(child);
+
+constants  {
+  #C1 = 0
+  #C2 = self::HBaseLeaf<self::HKindInvalid*> {data:#C1}
+  #C3 = self::HBaseChild<self::HKindInvalid*, self::HBaseLeaf<self::HKindInvalid*>*> {child:#C2}
+  #C4 = "error message"
+  #C5 = self::HBaseError<self::HKindInvalid*> {errorMessage:#C4}
+  #C6 = <self::HBase<self::HKindInvalid*>*>[#C2, #C3, #C5]
+  #C7 = self::HBaseComposite<self::HKindInvalid*, self::HBase<self::HKindInvalid*>*> {children:#C6}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48148.dart:
+- HBaseLeaf. (from org-dartlang-testcase:///issue48148.dart:45:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- HBaseChild. (from org-dartlang-testcase:///issue48148.dart:37:9)
+- HBaseError. (from org-dartlang-testcase:///issue48148.dart:53:9)
+- HBaseComposite. (from org-dartlang-testcase:///issue48148.dart:28:9)
diff --git a/pkg/front_end/testcases/general/issue48148.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue48148.dart.weak.outline.expect
new file mode 100644
index 0000000..1048f95
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.weak.outline.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef HInvalid = self::HBase<self::HKindInvalid>;
+typedef HInvalidComposite<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseComposite<self::HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseChild<self::HKindInvalid, CHILD>;
+typedef HInvalidLeaf = self::HBaseLeaf<self::HKindInvalid>;
+typedef HInvalidError = self::HBaseError<self::HKindInvalid>;
+abstract class HBase<HKT extends self::HKind> extends core::Object implements self::Kind<self::HBase::HKT> {
+  synthetic constructor •() → self::HBase<self::HBase::HKT>
+    ;
+}
+class HBaseComposite<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseComposite::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseComposite::HKT> /*hasConstConstructor*/  {
+  final field core::List<self::HBaseComposite::CHILD> children;
+  const constructor •(final core::List<self::HBaseComposite::CHILD> children) → self::HBaseComposite<self::HBaseComposite::HKT, self::HBaseComposite::CHILD>
+    : self::HBaseComposite::children = children, super core::Object::•()
+    ;
+}
+class HBaseChild<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseChild::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseChild::HKT> /*hasConstConstructor*/  {
+  final field self::HBaseChild::CHILD child;
+  const constructor •(final self::HBaseChild::CHILD child) → self::HBaseChild<self::HBaseChild::HKT, self::HBaseChild::CHILD>
+    : self::HBaseChild::child = child, super core::Object::•()
+    ;
+}
+class HBaseLeaf<HKT extends self::HKindValid> extends core::Object implements self::HBase<self::HBaseLeaf::HKT> /*hasConstConstructor*/  {
+  final field core::int data;
+  const constructor •(final core::int data) → self::HBaseLeaf<self::HBaseLeaf::HKT>
+    : self::HBaseLeaf::data = data, super core::Object::•()
+    ;
+}
+class HBaseError<HKT extends self::HKindInvalid> extends core::Object implements self::HBase<self::HBaseError::HKT> /*hasConstConstructor*/  {
+  final field core::String errorMessage;
+  const constructor •(final core::String errorMessage) → self::HBaseError<self::HBaseError::HKT>
+    : self::HBaseError::errorMessage = errorMessage, super core::Object::•()
+    ;
+}
+abstract class Kind<HKT extends self::HKind> extends core::Object {
+  synthetic constructor •() → self::Kind<self::Kind::HKT>
+    ;
+}
+abstract class HKind extends core::Object {
+  synthetic constructor •() → self::HKind
+    ;
+}
+abstract class HKindValid extends core::Object implements self::HKind {
+  synthetic constructor •() → self::HKindValid
+    ;
+}
+abstract class HKindInvalid extends core::Object implements self::HKindValid {
+  synthetic constructor •() → self::HKindInvalid
+    ;
+}
+static const field self::HBase<self::HKindInvalid> invalidExample = const self::HBaseComposite::•<self::HKindInvalid, self::HBase<self::HKindInvalid>>(const <self::HBase<self::HKindInvalid>>[const self::HBaseLeaf::•<self::HKindInvalid>(0), const self::HBaseChild::•<self::HKindInvalid, self::HBaseLeaf<self::HKindInvalid>>(const self::HBaseLeaf::•<self::HKindInvalid>(0)), const self::HBaseError::•<self::HKindInvalid>("error message")]);
+static method main() → dynamic
+  ;
+static method _#HInvalidComposite#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(core::List<self::_#HInvalidComposite#new#tearOff::CHILD> children) → self::HBaseComposite<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>
+  return new self::HBaseComposite::•<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>(children);
+static method _#HInvalidChild#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(self::_#HInvalidChild#new#tearOff::CHILD child) → self::HBaseChild<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>
+  return new self::HBaseChild::•<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>(child);
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue48148.dart:5:16 -> InstanceConstant(const HBaseComposite<HKindInvalid*, HBase<HKindInvalid*>*>{HBaseComposite.children: const <HBase<HKindInvalid*>*>[const HBaseLeaf<HKindInvalid*>{HBaseLeaf.data: 0}, const HBaseChild<HKindInvalid*, HBaseLeaf<HKindInvalid*>*>{HBaseChild.child: const HBaseLeaf<HKindInvalid*>{HBaseLeaf.data: 0}}, const HBaseError<HKindInvalid*>{HBaseError.errorMessage: "error message"}]})
+Extra constant evaluation: evaluated: 9, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue48148.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue48148.dart.weak.transformed.expect
new file mode 100644
index 0000000..dd37ee2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue48148.dart.weak.transformed.expect
@@ -0,0 +1,83 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef HInvalid = self::HBase<self::HKindInvalid>;
+typedef HInvalidComposite<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseComposite<self::HKindInvalid, CHILD>;
+typedef HInvalidChild<CHILD extends self::HBase<self::HKindInvalid>> = self::HBaseChild<self::HKindInvalid, CHILD>;
+typedef HInvalidLeaf = self::HBaseLeaf<self::HKindInvalid>;
+typedef HInvalidError = self::HBaseError<self::HKindInvalid>;
+abstract class HBase<HKT extends self::HKind> extends core::Object implements self::Kind<self::HBase::HKT> {
+  synthetic constructor •() → self::HBase<self::HBase::HKT>
+    : super core::Object::•()
+    ;
+}
+class HBaseComposite<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseComposite::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseComposite::HKT> /*hasConstConstructor*/  {
+  final field core::List<self::HBaseComposite::CHILD> children;
+  const constructor •(final core::List<self::HBaseComposite::CHILD> children) → self::HBaseComposite<self::HBaseComposite::HKT, self::HBaseComposite::CHILD>
+    : self::HBaseComposite::children = children, super core::Object::•()
+    ;
+}
+class HBaseChild<HKT extends self::HKindValid, CHILD extends self::HBase<self::HBaseChild::HKT> = self::HBase<self::HKindValid>> extends core::Object implements self::HBase<self::HBaseChild::HKT> /*hasConstConstructor*/  {
+  final field self::HBaseChild::CHILD child;
+  const constructor •(final self::HBaseChild::CHILD child) → self::HBaseChild<self::HBaseChild::HKT, self::HBaseChild::CHILD>
+    : self::HBaseChild::child = child, super core::Object::•()
+    ;
+}
+class HBaseLeaf<HKT extends self::HKindValid> extends core::Object implements self::HBase<self::HBaseLeaf::HKT> /*hasConstConstructor*/  {
+  final field core::int data;
+  const constructor •(final core::int data) → self::HBaseLeaf<self::HBaseLeaf::HKT>
+    : self::HBaseLeaf::data = data, super core::Object::•()
+    ;
+}
+class HBaseError<HKT extends self::HKindInvalid> extends core::Object implements self::HBase<self::HBaseError::HKT> /*hasConstConstructor*/  {
+  final field core::String errorMessage;
+  const constructor •(final core::String errorMessage) → self::HBaseError<self::HBaseError::HKT>
+    : self::HBaseError::errorMessage = errorMessage, super core::Object::•()
+    ;
+}
+abstract class Kind<HKT extends self::HKind> extends core::Object {
+  synthetic constructor •() → self::Kind<self::Kind::HKT>
+    : super core::Object::•()
+    ;
+}
+abstract class HKind extends core::Object {
+  synthetic constructor •() → self::HKind
+    : super core::Object::•()
+    ;
+}
+abstract class HKindValid extends core::Object implements self::HKind {
+  synthetic constructor •() → self::HKindValid
+    : super core::Object::•()
+    ;
+}
+abstract class HKindInvalid extends core::Object implements self::HKindValid {
+  synthetic constructor •() → self::HKindInvalid
+    : super core::Object::•()
+    ;
+}
+static const field self::HBase<self::HKindInvalid> invalidExample = #C7;
+static method main() → dynamic {}
+static method _#HInvalidComposite#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(core::List<self::_#HInvalidComposite#new#tearOff::CHILD> children) → self::HBaseComposite<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>
+  return new self::HBaseComposite::•<self::HKindInvalid, self::_#HInvalidComposite#new#tearOff::CHILD>(children);
+static method _#HInvalidChild#new#tearOff<CHILD extends self::HBase<self::HKindInvalid>>(self::_#HInvalidChild#new#tearOff::CHILD child) → self::HBaseChild<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>
+  return new self::HBaseChild::•<self::HKindInvalid, self::_#HInvalidChild#new#tearOff::CHILD>(child);
+
+constants  {
+  #C1 = 0
+  #C2 = self::HBaseLeaf<self::HKindInvalid*> {data:#C1}
+  #C3 = self::HBaseChild<self::HKindInvalid*, self::HBaseLeaf<self::HKindInvalid*>*> {child:#C2}
+  #C4 = "error message"
+  #C5 = self::HBaseError<self::HKindInvalid*> {errorMessage:#C4}
+  #C6 = <self::HBase<self::HKindInvalid*>*>[#C2, #C3, #C5]
+  #C7 = self::HBaseComposite<self::HKindInvalid*, self::HBase<self::HKindInvalid*>*> {children:#C6}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue48148.dart:
+- HBaseLeaf. (from org-dartlang-testcase:///issue48148.dart:45:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- HBaseChild. (from org-dartlang-testcase:///issue48148.dart:37:9)
+- HBaseError. (from org-dartlang-testcase:///issue48148.dart:53:9)
+- HBaseComposite. (from org-dartlang-testcase:///issue48148.dart:28:9)
diff --git a/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
index 8d133e3..ad7a346 100644
--- a/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
@@ -1,13 +1,10 @@
 // @dart = 2.13
 class Foo {
-  Foo operator >>>(_) => this;
+  Foo operator >>> (_) => this;
 }
-
 extension on Symbol {
   String operator >(_) => "Greater Than used";
   String call(_) => "Called";
 }
-
 abstract class Bar implements List<List<List<String>>> {}
-
 main() {}
diff --git a/pkg/front_end/testcases/general/macro_class.dart.weak.expect b/pkg/front_end/testcases/general/macro_class.dart.weak.expect
index 5a61151..ce6b7bb 100644
--- a/pkg/front_end/testcases/general/macro_class.dart.weak.expect
+++ b/pkg/front_end/testcases/general/macro_class.dart.weak.expect
@@ -3,22 +3,22 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/macro_class.dart:8:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class1 {}
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:9:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class2 {}
 //                ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:10:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class3 = Super with Mixin;
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:11:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class4 = Super with Mixin;
 //                ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/macro_class.dart.weak.modular.expect b/pkg/front_end/testcases/general/macro_class.dart.weak.modular.expect
index 5a61151..ce6b7bb 100644
--- a/pkg/front_end/testcases/general/macro_class.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/macro_class.dart.weak.modular.expect
@@ -3,22 +3,22 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/macro_class.dart:8:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class1 {}
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:9:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class2 {}
 //                ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:10:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class3 = Super with Mixin;
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:11:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class4 = Super with Mixin;
 //                ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/macro_class.dart.weak.outline.expect b/pkg/front_end/testcases/general/macro_class.dart.weak.outline.expect
index 13e7bcc..614ee32 100644
--- a/pkg/front_end/testcases/general/macro_class.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/macro_class.dart.weak.outline.expect
@@ -3,22 +3,22 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/macro_class.dart:8:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class1 {}
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:9:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class2 {}
 //                ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:10:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class3 = Super with Mixin;
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:11:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class4 = Super with Mixin;
 //                ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/macro_class.dart.weak.transformed.expect b/pkg/front_end/testcases/general/macro_class.dart.weak.transformed.expect
index 506e808..7f71bca 100644
--- a/pkg/front_end/testcases/general/macro_class.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/macro_class.dart.weak.transformed.expect
@@ -3,22 +3,22 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/macro_class.dart:8:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class1 {}
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:9:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class2 {}
 //                ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:10:7: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // macro class Class3 = Super with Mixin;
 //       ^^^^^
 //
 // pkg/front_end/testcases/general/macro_class.dart:11:16: Error: This requires the 'macros' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.16 or higher, and running 'pub get'.
+// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17 or higher, and running 'pub get'.
 // abstract macro class Class4 = Super with Mixin;
 //                ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.weak.outline.expect
index b84923c..4244473 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.weak.outline.expect
@@ -41,7 +41,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class D = self::C<core::String*> with self::M {
-  synthetic constructor •({dynamic a, dynamic b}) → self::D*
+  synthetic constructor •({dynamic a = 0, dynamic b = invalid-type}) → self::D*
     : super self::C::•(a: a, b: b)
     ;
 }
@@ -50,7 +50,7 @@
     ;
 }
 abstract class _F&C&M = self::C<core::int*> with self::M /*isAnonymousMixin*/  {
-  synthetic constructor •({dynamic a, dynamic b}) → self::_F&C&M*
+  synthetic constructor •({dynamic a = 0, dynamic b = invalid-type}) → self::_F&C&M*
     : super self::C::•(a: a, b: b)
     ;
 }
@@ -64,4 +64,6 @@
 
 Extra constant evaluation status:
 Evaluated: TypeLiteral @ org-dartlang-testcase:///mixin_constructors_with_default_values.dart:9:15 -> TypeLiteralConstant(<invalid>)
-Extra constant evaluation: evaluated: 5, effectively constant: 1
+Evaluated: TypeLiteral @ org-dartlang-testcase:///mixin_constructors_with_default_values.dart:14:7 -> TypeLiteralConstant(<invalid>)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///mixin_constructors_with_default_values.dart:18:7 -> TypeLiteralConstant(<invalid>)
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.weak.outline.expect
index 46d5dff..bffd38a 100644
--- a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.weak.outline.expect
@@ -52,7 +52,7 @@
   synthetic constructor unpatched() → self2::_SubClass&Class&Mixin*
     : super self2::Class::unpatched()
     ;
-  synthetic constructor _internal({core::bool* value}) → self2::_SubClass&Class&Mixin*
+  synthetic constructor _internal({core::bool* value = false}) → self2::_SubClass&Class&Mixin*
     : super self2::Class::_internal(value: value)
     ;
 }
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/common_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/common_lib.dart
new file mode 100644
index 0000000..a4ce2de
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/common_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Common {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/extra_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/extra_lib.dart
new file mode 100644
index 0000000..77f761f
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/extra_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Extra {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/extra_libraries.json b/pkg/front_end/testcases/general/nested_lib_spec/extra_libraries.json
new file mode 100644
index 0000000..4ef762a
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/extra_libraries.json
@@ -0,0 +1,18 @@
+{
+  "_none": {
+    "include": [
+      {
+        "path": "subfolder/sub_libraries.json",
+        "target": "subtarget"
+      }
+    ],
+    "libraries": {
+      "extra": {
+        "patches": [
+          "extra_patch_lib.dart"
+        ],
+        "uri": "extra_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/extra_patch_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/extra_patch_lib.dart
new file mode 100644
index 0000000..71d7fc2
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/extra_patch_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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:_internal';
+
+@patch
+class Extra {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/libraries.json b/pkg/front_end/testcases/general/nested_lib_spec/libraries.json
new file mode 100644
index 0000000..14705fe
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/libraries.json
@@ -0,0 +1,28 @@
+{
+  "none": {
+    "include": [
+      {
+        "path": "extra_libraries.json",
+        "target": "_none"
+      },
+      {
+        "target": "common"
+      }
+    ],
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  },
+  "common": {
+    "libraries": {
+      "common": {
+        "uri": "common_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart b/pkg/front_end/testcases/general/nested_lib_spec/main.dart
new file mode 100644
index 0000000..67e18ef
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:test';
+import 'dart:extra';
+import 'dart:sub';
+import 'dart:sub2';
+import 'dart:super1';
+import 'dart:super2';
+import 'dart:common';
+
+main() {
+  new Class();
+  new Extra();
+  new Sub();
+  new Sub2();
+  new Super1();
+  new Super2();
+  new Common();
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline.expect
new file mode 100644
index 0000000..c544d3d
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+import 'dart:test';
+import 'dart:extra';
+import 'dart:sub';
+import 'dart:sub2';
+import 'dart:super1';
+import 'dart:super2';
+import 'dart:common';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..033e3d1
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+import 'dart:common';
+import 'dart:extra';
+import 'dart:sub';
+import 'dart:sub2';
+import 'dart:super1';
+import 'dart:super2';
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.expect
new file mode 100644
index 0000000..bbfc87a
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+import "dart:extra" as ext;
+import "dart:sub" as sub;
+import "dart:sub2" as sub2;
+import "dart:super1" as sup;
+import "dart:super2" as sup2;
+import "dart:common" as com;
+
+import "dart:test";
+import "dart:extra";
+import "dart:sub";
+import "dart:sub2";
+import "dart:super1";
+import "dart:super2";
+import "dart:common";
+
+static method main() → dynamic {
+  new test::Class::•();
+  new ext::Extra::•();
+  new sub::Sub::•();
+  new sub2::Sub2::•();
+  new sup::Super1::•();
+  new sup2::Super2::•();
+  new com::Common::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  synthetic constructor •() → test::Class
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as ext;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Extra extends core::Object {
+  synthetic constructor •() → ext::Extra
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub;
+import "dart:core" as core;
+
+class Sub extends core::Object {
+  synthetic constructor •() → sub::Sub
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub2;
+import "dart:core" as core;
+
+class Sub2 extends core::Object {
+  synthetic constructor •() → sub2::Sub2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup;
+import "dart:core" as core;
+
+class Super1 extends core::Object {
+  synthetic constructor •() → sup::Super1
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup2;
+import "dart:core" as core;
+
+class Super2 extends core::Object {
+  synthetic constructor •() → sup2::Super2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as com;
+import "dart:core" as core;
+
+class Common extends core::Object {
+  synthetic constructor •() → com::Common
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.modular.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.modular.expect
new file mode 100644
index 0000000..bbfc87a
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.modular.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+import "dart:extra" as ext;
+import "dart:sub" as sub;
+import "dart:sub2" as sub2;
+import "dart:super1" as sup;
+import "dart:super2" as sup2;
+import "dart:common" as com;
+
+import "dart:test";
+import "dart:extra";
+import "dart:sub";
+import "dart:sub2";
+import "dart:super1";
+import "dart:super2";
+import "dart:common";
+
+static method main() → dynamic {
+  new test::Class::•();
+  new ext::Extra::•();
+  new sub::Sub::•();
+  new sub2::Sub2::•();
+  new sup::Super1::•();
+  new sup2::Super2::•();
+  new com::Common::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  synthetic constructor •() → test::Class
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as ext;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Extra extends core::Object {
+  synthetic constructor •() → ext::Extra
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub;
+import "dart:core" as core;
+
+class Sub extends core::Object {
+  synthetic constructor •() → sub::Sub
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub2;
+import "dart:core" as core;
+
+class Sub2 extends core::Object {
+  synthetic constructor •() → sub2::Sub2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup;
+import "dart:core" as core;
+
+class Super1 extends core::Object {
+  synthetic constructor •() → sup::Super1
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup2;
+import "dart:core" as core;
+
+class Super2 extends core::Object {
+  synthetic constructor •() → sup2::Super2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as com;
+import "dart:core" as core;
+
+class Common extends core::Object {
+  synthetic constructor •() → com::Common
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.outline.expect
new file mode 100644
index 0000000..9c88621
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.outline.expect
@@ -0,0 +1,90 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+import "dart:extra";
+import "dart:sub";
+import "dart:sub2";
+import "dart:super1";
+import "dart:super2";
+import "dart:common";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Class extends core::Object {
+  synthetic constructor •() → self2::Class
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Extra extends core::Object {
+  synthetic constructor •() → self3::Extra
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+import "dart:core" as core;
+
+class Sub extends core::Object {
+  synthetic constructor •() → self4::Sub
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self5;
+import "dart:core" as core;
+
+class Sub2 extends core::Object {
+  synthetic constructor •() → self5::Sub2
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+class Super1 extends core::Object {
+  synthetic constructor •() → self6::Super1
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+class Super2 extends core::Object {
+  synthetic constructor •() → self7::Super2
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+class Common extends core::Object {
+  synthetic constructor •() → self8::Common
+    ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///extra_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..bbfc87a
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/main.dart.weak.transformed.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+import "dart:extra" as ext;
+import "dart:sub" as sub;
+import "dart:sub2" as sub2;
+import "dart:super1" as sup;
+import "dart:super2" as sup2;
+import "dart:common" as com;
+
+import "dart:test";
+import "dart:extra";
+import "dart:sub";
+import "dart:sub2";
+import "dart:super1";
+import "dart:super2";
+import "dart:common";
+
+static method main() → dynamic {
+  new test::Class::•();
+  new ext::Extra::•();
+  new sub::Sub::•();
+  new sub2::Sub2::•();
+  new sup::Super1::•();
+  new sup2::Super2::•();
+  new com::Common::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  synthetic constructor •() → test::Class
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as ext;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Extra extends core::Object {
+  synthetic constructor •() → ext::Extra
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub;
+import "dart:core" as core;
+
+class Sub extends core::Object {
+  synthetic constructor •() → sub::Sub
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sub2;
+import "dart:core" as core;
+
+class Sub2 extends core::Object {
+  synthetic constructor •() → sub2::Sub2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup;
+import "dart:core" as core;
+
+class Super1 extends core::Object {
+  synthetic constructor •() → sup::Super1
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup2;
+import "dart:core" as core;
+
+class Super2 extends core::Object {
+  synthetic constructor •() → sup2::Super2
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+import self as com;
+import "dart:core" as core;
+
+class Common extends core::Object {
+  synthetic constructor •() → com::Common
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/origin_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/origin_lib.dart
new file mode 100644
index 0000000..6d966e0
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/origin_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/patch_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/patch_lib.dart
new file mode 100644
index 0000000..c134e75
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/patch_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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:_internal';
+
+@patch
+class Class {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/sub2_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/sub2_lib.dart
new file mode 100644
index 0000000..5a1f9b0
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/sub2_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Sub2 {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_lib.dart
new file mode 100644
index 0000000..2e54c8c
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Sub {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_libraries.json b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_libraries.json
new file mode 100644
index 0000000..ca8782a
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/sub_libraries.json
@@ -0,0 +1,21 @@
+{
+  "subtarget": {
+    "include": [
+      {
+        "path": "../super1_libraries.json",
+        "target": "none"
+      },
+      { "path": "../../nested_lib_spec/super2_libraries.json",
+        "target": "none"
+      }
+    ],
+    "libraries": {
+      "sub": {
+        "uri": "sub_lib.dart"
+      },
+      "sub2": {
+        "uri": "../sub2_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/subfolder/super2_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/super2_lib.dart
new file mode 100644
index 0000000..9ac3219
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/subfolder/super2_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Super2 {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/super1_lib.dart b/pkg/front_end/testcases/general/nested_lib_spec/super1_lib.dart
new file mode 100644
index 0000000..b7b4486
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/super1_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 Super1 {}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/super1_libraries.json b/pkg/front_end/testcases/general/nested_lib_spec/super1_libraries.json
new file mode 100644
index 0000000..28bd7f2
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/super1_libraries.json
@@ -0,0 +1,9 @@
+{
+  "none": {
+    "libraries": {
+      "super1": {
+        "uri": "super1_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_lib_spec/super2_libraries.json b/pkg/front_end/testcases/general/nested_lib_spec/super2_libraries.json
new file mode 100644
index 0000000..f89a448
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_lib_spec/super2_libraries.json
@@ -0,0 +1,9 @@
+{
+  "none": {
+    "libraries": {
+      "super2": {
+        "uri": "subfolder/super2_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_default_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_default_lib.dart
new file mode 100644
index 0000000..00ee769
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_default_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'default';
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_supported.by.spec_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_supported.by.spec_lib.dart
new file mode 100644
index 0000000..1c3a6c7
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_supported.by.spec_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'supported.by.spec';
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_supported.by.target_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_supported.by.target_lib.dart
new file mode 100644
index 0000000..36d5727
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_supported.by.target_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'supported.by.target';
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_internal_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_internal_lib.dart
new file mode 100644
index 0000000..27ca303
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_internal_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'unsupported.by.spec_internal';
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_lib.dart
new file mode 100644
index 0000000..3b9f7f27
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.spec_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'unsupported.by.spec';
diff --git a/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.target_lib.dart b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.target_lib.dart
new file mode 100644
index 0000000..d0216e7
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/import_unsupported.by.target_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 field = 'unsupported.by.target';
diff --git a/pkg/front_end/testcases/general/supported_libraries/libraries.json b/pkg/front_end/testcases/general/supported_libraries/libraries.json
new file mode 100644
index 0000000..13d244b
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/libraries.json
@@ -0,0 +1,23 @@
+{
+  "none": {
+    "libraries": {
+      "supported.by.spec": {
+        "uri": "supported.by.spec_lib.dart"
+      },
+      "_supported.by.target": {
+        "uri": "supported.by.target_lib.dart"
+      },
+      "unsupported.by.spec": {
+        "uri": "unsupported.by.spec_lib.dart",
+        "supported": false
+      },
+      "unsupported.by.target": {
+        "uri": "unsupported.by.target_lib.dart",
+        "supported": true
+      },
+      "_unsupported.by.spec_internal": {
+        "uri": "unsupported.by.spec_internal_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart b/pkg/front_end/testcases/general/supported_libraries/main.dart
new file mode 100644
index 0000000..0677973
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:supported.by.spec';
+import 'dart:unsupported.by.spec';
+import 'dart:unsupported.by.target';
+
+import 'import_default_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    as from_supported_by_spec_first;
+
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    as from_supported_by_target;
+
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    as from_supported_by_spec_last;
+
+main() {
+  supportedBySpec();
+  supportedByTarget(); // Exported through dart:supported.by.spec
+  unsupportedBySpec();
+  unsupportedByTarget();
+  unsupportedBySpecInternal(); // Exported through dart:unsupported.by.spec
+
+  expect('supported.by.spec', from_supported_by_spec_first.field);
+  expect('supported.by.target', from_supported_by_target.field);
+  expect('supported.by.spec', from_supported_by_spec_last.field);
+
+  // `dart:supported.by.spec` is supported by the libraries specification.
+  expect(true, const bool.fromEnvironment('dart.library.supported.by.spec'));
+  // `dart:_supported.by.target` is internal and therefore not supported by
+  // the libraries specification, but the test target supports it explicitly.
+  expect(true, const bool.fromEnvironment('dart.library._supported.by.target'));
+  // `dart:unsupported.by.spec` is unsupported by the libraries specification.
+  expect(false, const bool.fromEnvironment('dart.library.unsupported.by.spec'));
+  // `dart:unsupported.by.target` is unsupported by the libraries specification,
+  // but the test target explicitly marks it as unsupported.
+  expect(
+      false, const bool.fromEnvironment('dart.library.unsupported.by.target'));
+  // `dart:_unsupported.by.spec_internal` is internal and therefore not
+  // supported by the libraries specification.
+  expect(false,
+      const bool.fromEnvironment('dart.library._unsupported.by.spec_internal'));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline.expect
new file mode 100644
index 0000000..da8d39f
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+import 'dart:supported.by.spec';
+import 'dart:unsupported.by.spec';
+import 'dart:unsupported.by.target';
+import 'import_default_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    as from_supported_by_spec_first;
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    as from_supported_by_target;
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    as from_supported_by_spec_last;
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..29001ab
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,27 @@
+import 'dart:supported.by.spec';
+import 'dart:unsupported.by.spec';
+import 'dart:unsupported.by.target';
+import 'import_default_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    as from_supported_by_spec_first;
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    as from_supported_by_target;
+import 'import_default_lib.dart'
+    if (dart.library.unsupported.by.spec) 'import_unsupported.by.spec_lib.dart'
+    if (dart.library.unsupported.by.target) 'import_unsupported.by.target_lib.dart'
+    if (dart.library._unsupported.by.spec_internal) 'import_unsupported.by.spec_internal_lib.dart'
+    if (dart.library.supported.by.spec) 'import_supported.by.spec_lib.dart'
+    if (dart.library._supported.by.target) 'import_supported.by.target_lib.dart'
+    as from_supported_by_spec_last;
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.expect
new file mode 100644
index 0000000..85a3cb7
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.expect
@@ -0,0 +1,87 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:supported.by.spec" as spec;
+import "dart:_supported.by.target" as by_;
+import "dart:unsupported.by.spec" as spec2;
+import "dart:unsupported.by.target" as tar;
+import "dart:_unsupported.by.spec_internal" as spe;
+import "import_supported.by.spec_lib.dart" as spe2;
+import "import_supported.by.target_lib.dart" as tar2;
+import "dart:core" as core;
+
+import "dart:supported.by.spec";
+import "dart:unsupported.by.spec";
+import "dart:unsupported.by.target";
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_first;
+import "org-dartlang-testcase:///import_supported.by.target_lib.dart" as from_supported_by_target;
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_last;
+
+static method main() → dynamic {
+  spec::supportedBySpec();
+  by_::supportedByTarget();
+  spec2::unsupportedBySpec();
+  tar::unsupportedByTarget();
+  spe::unsupportedBySpecInternal();
+  self::expect("supported.by.spec", spe2::field);
+  self::expect("supported.by.target", tar2::field);
+  self::expect("supported.by.spec", spe2::field);
+  self::expect(true, #C1);
+  self::expect(true, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library dart.supported.by.spec /*isNonNullableByDefault*/;
+import self as spec;
+import "dart:_supported.by.target" as by_;
+additionalExports = (by_::supportedByTarget)
+
+export "dart:_supported.by.target";
+
+static method supportedBySpec() → void {}
+
+library dart.unsupported.by.spec /*isUnsupported,isNonNullableByDefault*/;
+import self as spec2;
+import "dart:_unsupported.by.spec_internal" as spe;
+additionalExports = (spe::unsupportedBySpecInternal)
+
+export "dart:_unsupported.by.spec_internal";
+
+static method unsupportedBySpec() → void {}
+
+library dart.unsupported.by.target /*isNonNullableByDefault*/;
+import self as tar;
+
+static method unsupportedByTarget() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as spe2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.spec";
+
+library /*isNonNullableByDefault*/;
+import self as tar2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.target";
+
+library dart._supported.by_target /*isUnsupported,isNonNullableByDefault*/;
+import self as by_;
+
+static method supportedByTarget() → void {}
+
+library dart._unsupported.by.spec_internal /*isUnsupported,isNonNullableByDefault*/;
+import self as spe;
+
+static method unsupportedBySpecInternal() → void {}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.modular.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.modular.expect
new file mode 100644
index 0000000..85a3cb7
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.modular.expect
@@ -0,0 +1,87 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:supported.by.spec" as spec;
+import "dart:_supported.by.target" as by_;
+import "dart:unsupported.by.spec" as spec2;
+import "dart:unsupported.by.target" as tar;
+import "dart:_unsupported.by.spec_internal" as spe;
+import "import_supported.by.spec_lib.dart" as spe2;
+import "import_supported.by.target_lib.dart" as tar2;
+import "dart:core" as core;
+
+import "dart:supported.by.spec";
+import "dart:unsupported.by.spec";
+import "dart:unsupported.by.target";
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_first;
+import "org-dartlang-testcase:///import_supported.by.target_lib.dart" as from_supported_by_target;
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_last;
+
+static method main() → dynamic {
+  spec::supportedBySpec();
+  by_::supportedByTarget();
+  spec2::unsupportedBySpec();
+  tar::unsupportedByTarget();
+  spe::unsupportedBySpecInternal();
+  self::expect("supported.by.spec", spe2::field);
+  self::expect("supported.by.target", tar2::field);
+  self::expect("supported.by.spec", spe2::field);
+  self::expect(true, #C1);
+  self::expect(true, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library dart.supported.by.spec /*isNonNullableByDefault*/;
+import self as spec;
+import "dart:_supported.by.target" as by_;
+additionalExports = (by_::supportedByTarget)
+
+export "dart:_supported.by.target";
+
+static method supportedBySpec() → void {}
+
+library dart.unsupported.by.spec /*isUnsupported,isNonNullableByDefault*/;
+import self as spec2;
+import "dart:_unsupported.by.spec_internal" as spe;
+additionalExports = (spe::unsupportedBySpecInternal)
+
+export "dart:_unsupported.by.spec_internal";
+
+static method unsupportedBySpec() → void {}
+
+library dart.unsupported.by.target /*isNonNullableByDefault*/;
+import self as tar;
+
+static method unsupportedByTarget() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as spe2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.spec";
+
+library /*isNonNullableByDefault*/;
+import self as tar2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.target";
+
+library dart._supported.by_target /*isUnsupported,isNonNullableByDefault*/;
+import self as by_;
+
+static method supportedByTarget() → void {}
+
+library dart._unsupported.by.spec_internal /*isUnsupported,isNonNullableByDefault*/;
+import self as spe;
+
+static method unsupportedBySpecInternal() → void {}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.outline.expect
new file mode 100644
index 0000000..5e500ab
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.outline.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:supported.by.spec";
+import "dart:unsupported.by.spec";
+import "dart:unsupported.by.target";
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_first;
+import "org-dartlang-testcase:///import_supported.by.target_lib.dart" as from_supported_by_target;
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_last;
+
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library dart.supported.by.spec /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_supported.by.target" as by_;
+additionalExports = (by_::supportedByTarget)
+
+export "dart:_supported.by.target";
+
+static method supportedBySpec() → void
+  ;
+
+library dart.unsupported.by.spec /*isUnsupported,isNonNullableByDefault*/;
+import self as self3;
+import "dart:_unsupported.by.spec_internal" as spe;
+additionalExports = (spe::unsupportedBySpecInternal)
+
+export "dart:_unsupported.by.spec_internal";
+
+static method unsupportedBySpec() → void
+  ;
+
+library dart.unsupported.by.target /*isNonNullableByDefault*/;
+import self as self4;
+
+static method unsupportedByTarget() → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self5;
+import "dart:core" as core;
+
+static field core::String field;
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static field core::String field;
+
+library dart._supported.by_target /*isUnsupported,isNonNullableByDefault*/;
+import self as by_;
+
+static method supportedByTarget() → void
+  ;
+
+library dart._unsupported.by.spec_internal /*isUnsupported,isNonNullableByDefault*/;
+import self as spe;
+
+static method unsupportedBySpecInternal() → void
+  ;
diff --git a/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..85a3cb7
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/main.dart.weak.transformed.expect
@@ -0,0 +1,87 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:supported.by.spec" as spec;
+import "dart:_supported.by.target" as by_;
+import "dart:unsupported.by.spec" as spec2;
+import "dart:unsupported.by.target" as tar;
+import "dart:_unsupported.by.spec_internal" as spe;
+import "import_supported.by.spec_lib.dart" as spe2;
+import "import_supported.by.target_lib.dart" as tar2;
+import "dart:core" as core;
+
+import "dart:supported.by.spec";
+import "dart:unsupported.by.spec";
+import "dart:unsupported.by.target";
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_first;
+import "org-dartlang-testcase:///import_supported.by.target_lib.dart" as from_supported_by_target;
+import "org-dartlang-testcase:///import_supported.by.spec_lib.dart" as from_supported_by_spec_last;
+
+static method main() → dynamic {
+  spec::supportedBySpec();
+  by_::supportedByTarget();
+  spec2::unsupportedBySpec();
+  tar::unsupportedByTarget();
+  spe::unsupportedBySpecInternal();
+  self::expect("supported.by.spec", spe2::field);
+  self::expect("supported.by.target", tar2::field);
+  self::expect("supported.by.spec", spe2::field);
+  self::expect(true, #C1);
+  self::expect(true, #C1);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+  self::expect(false, #C2);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library dart.supported.by.spec /*isNonNullableByDefault*/;
+import self as spec;
+import "dart:_supported.by.target" as by_;
+additionalExports = (by_::supportedByTarget)
+
+export "dart:_supported.by.target";
+
+static method supportedBySpec() → void {}
+
+library dart.unsupported.by.spec /*isUnsupported,isNonNullableByDefault*/;
+import self as spec2;
+import "dart:_unsupported.by.spec_internal" as spe;
+additionalExports = (spe::unsupportedBySpecInternal)
+
+export "dart:_unsupported.by.spec_internal";
+
+static method unsupportedBySpec() → void {}
+
+library dart.unsupported.by.target /*isNonNullableByDefault*/;
+import self as tar;
+
+static method unsupportedByTarget() → void {}
+
+library /*isNonNullableByDefault*/;
+import self as spe2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.spec";
+
+library /*isNonNullableByDefault*/;
+import self as tar2;
+import "dart:core" as core;
+
+static field core::String field = "supported.by.target";
+
+library dart._supported.by_target /*isUnsupported,isNonNullableByDefault*/;
+import self as by_;
+
+static method supportedByTarget() → void {}
+
+library dart._unsupported.by.spec_internal /*isUnsupported,isNonNullableByDefault*/;
+import self as spe;
+
+static method unsupportedBySpecInternal() → void {}
+
+constants  {
+  #C1 = true
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/general/supported_libraries/supported.by.spec_lib.dart b/pkg/front_end/testcases/general/supported_libraries/supported.by.spec_lib.dart
new file mode 100644
index 0000000..ea5edc0
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/supported.by.spec_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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.supported.by.spec;
+
+export 'dart:_supported.by.target';
+
+void supportedBySpec() {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/supported.by.target_lib.dart b/pkg/front_end/testcases/general/supported_libraries/supported.by.target_lib.dart
new file mode 100644
index 0000000..673f03d
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/supported.by.target_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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._supported.by_target;
+
+void supportedByTarget() {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_internal_lib.dart b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_internal_lib.dart
new file mode 100644
index 0000000..7171f88
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_internal_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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._unsupported.by.spec_internal;
+
+void unsupportedBySpecInternal() {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_lib.dart b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_lib.dart
new file mode 100644
index 0000000..ac010bb
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.spec_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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.unsupported.by.spec;
+
+export 'dart:_unsupported.by.spec_internal';
+
+void unsupportedBySpec() {}
diff --git a/pkg/front_end/testcases/general/supported_libraries/unsupported.by.target_lib.dart b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.target_lib.dart
new file mode 100644
index 0000000..0ef61dc
--- /dev/null
+++ b/pkg/front_end/testcases/general/supported_libraries/unsupported.by.target_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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.unsupported.by.target;
+
+void unsupportedByTarget() {}
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect b/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect
index cd22c39..bcb7537 100644
--- a/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect
@@ -56,11 +56,11 @@
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = dart.ffi::Uint32 {}
   #C8 = 0
-  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
+  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
   #C10 = "vm:prefer-inline"
   #C11 = dart.core::pragma {name:#C10, options:#C4}
   #C12 = 4
-  #C13 = <dart.core::int*>[#C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
+  #C13 = <dart.core::int*>[#C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
   #C14 = TypeLiteralConstant(lib::Y)
   #C15 = <dart.core::Type>[#C14]
   #C16 = dart.ffi::_FfiStructLayout {fieldTypes:#C15, packing:#C4}
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect b/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect
index cd22c39..bcb7537 100644
--- a/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect
@@ -56,11 +56,11 @@
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = dart.ffi::Uint32 {}
   #C8 = 0
-  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
+  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
   #C10 = "vm:prefer-inline"
   #C11 = dart.core::pragma {name:#C10, options:#C4}
   #C12 = 4
-  #C13 = <dart.core::int*>[#C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
+  #C13 = <dart.core::int*>[#C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
   #C14 = TypeLiteralConstant(lib::Y)
   #C15 = <dart.core::Type>[#C14]
   #C16 = dart.ffi::_FfiStructLayout {fieldTypes:#C15, packing:#C4}
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect b/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect
index 2b217e2..a7835ef 100644
--- a/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect
@@ -62,7 +62,7 @@
   #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = 0
-  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
+  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
   #C9 = "vm:prefer-inline"
   #C10 = dart.core::pragma {name:#C9, options:#C4}
 }
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect b/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect
index 2b217e2..a7835ef 100644
--- a/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect
@@ -62,7 +62,7 @@
   #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = 0
-  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
+  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
   #C9 = "vm:prefer-inline"
   #C10 = dart.core::pragma {name:#C9, options:#C4}
 }
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml b/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml
index 7fd5bb5..4260828 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml
@@ -3,8 +3,7 @@
 # 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.
+# the library should still be included in the output.
 
 type: newworld
 worlds:
@@ -17,4 +16,4 @@
       .packages: untitled:/
     expectedLibraryCount: 1
     errors: false
-    warnings: true
+    warnings: false
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml.world.1.expect b/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml.world.1.expect
index aa34750..c4cd6be 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_main.yaml.world.1.expect
@@ -1,9 +1,4 @@
 main = main::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:untitled/main.dart'.
-//
 library from "package:untitled/main.dart" as main {
 
   static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml b/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml
index 230ec11..e7b80f2 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml
@@ -3,8 +3,8 @@
 # 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.
+# the library should still be included in the output -
+# even if there's errors in main.
 
 type: newworld
 worlds:
@@ -18,4 +18,4 @@
       .packages: untitled:/
     expectedLibraryCount: 1
     errors: true
-    warnings: true
+    warnings: false
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml.world.1.expect b/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml.world.1.expect
index 055bb06..f598435 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_main_with_errors.yaml.world.1.expect
@@ -1,9 +1,4 @@
 main = main::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:untitled/main.dart'.
-//
 library from "package:untitled/main.dart" as main {
 //
 // Problems in library:
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml b/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml
index e6e0487..72eac40 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml
@@ -3,8 +3,7 @@
 # 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.
+# the library should still be included in the output - even if there's no main.
 
 type: newworld
 worlds:
@@ -16,4 +15,4 @@
       .packages: untitled:/
     expectedLibraryCount: 1
     errors: false
-    warnings: true
+    warnings: false
diff --git a/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml.world.1.expect b/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml.world.1.expect
index 6ee484d..b1df83d 100644
--- a/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/entry_not_package_url_no_main.yaml.world.1.expect
@@ -1,9 +1,4 @@
 main = <No Member>;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:untitled/main.dart'.
-//
 library from "package:untitled/main.dart" as main {
 
   static method notMain() → dynamic {}
diff --git a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
index 2e5c180..e6e7693 100644
--- a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
@@ -33,9 +33,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -62,14 +62,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
index a82af2e..7712ae2 100644
--- a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
@@ -33,9 +33,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -66,14 +66,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
index 68633a6..99eefd4 100644
--- a/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
@@ -33,9 +33,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -63,14 +63,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
index e925f93..a889a57 100644
--- a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
@@ -12,17 +12,17 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get a1() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get a2() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get a3() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get blah() → a::NestedStruct
       return new a::NestedStruct::#fromTypedDataBase( block {
         dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
@@ -43,17 +43,17 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get n1() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get n2() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get n3() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     @#C19
     static get #sizeOf() → dart.core::int*
       return #C17.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -101,19 +101,19 @@
   #C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = 0
-  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
+  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
   #C10 = 4
   #C11 = 8
-  #C12 = <dart.core::int*>[#C10, #C11, #C10, #C11, #C11, #C11, #C10, #C11, #C11, #C10, #C11, #C10, #C11, #C11, #C11, #C11, #C10, #C11]
+  #C12 = <dart.core::int*>[#C10, #C11, #C10, #C11, #C11, #C11, #C10, #C11, #C11, #C10, #C11, #C10, #C11, #C10, #C11, #C11, #C11, #C11, #C10, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C11, #C13, #C11, #C13, #C13, #C13, #C11, #C13, #C13, #C11, #C13, #C11, #C13, #C13, #C13, #C13, #C11, #C13]
+  #C14 = <dart.core::int*>[#C11, #C13, #C11, #C13, #C13, #C13, #C11, #C13, #C13, #C11, #C13, #C11, #C13, #C11, #C13, #C13, #C13, #C13, #C11, #C13]
   #C15 = 12
   #C16 = 24
-  #C17 = <dart.core::int*>[#C15, #C16, #C15, #C16, #C16, #C16, #C15, #C16, #C16, #C15, #C16, #C15, #C16, #C16, #C16, #C16, #C15, #C16]
+  #C17 = <dart.core::int*>[#C15, #C16, #C15, #C16, #C16, #C16, #C15, #C16, #C16, #C15, #C16, #C15, #C16, #C15, #C16, #C16, #C16, #C16, #C15, #C16]
   #C18 = "vm:prefer-inline"
   #C19 = dart.core::pragma {name:#C18, options:#C5}
   #C20 = 48
-  #C21 = <dart.core::int*>[#C16, #C20, #C16, #C20, #C20, #C20, #C16, #C20, #C20, #C16, #C20, #C16, #C20, #C20, #C20, #C20, #C16, #C20]
+  #C21 = <dart.core::int*>[#C16, #C20, #C16, #C20, #C20, #C20, #C16, #C20, #C20, #C16, #C20, #C16, #C20, #C16, #C20, #C20, #C20, #C20, #C16, #C20]
   #C22 = <dart.core::Type>[#C2, #C2, #C2]
   #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
   #C24 = dart.core::pragma {name:#C1, options:#C23}
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
index e925f93..a889a57 100644
--- a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
@@ -12,17 +12,17 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get a1() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get a2() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get a3() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set a3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get blah() → a::NestedStruct
       return new a::NestedStruct::#fromTypedDataBase( block {
         dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
@@ -43,17 +43,17 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get n1() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C9.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get n2() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get n3() → dart.ffi::Pointer<dart.ffi::Void>
-      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set n3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     @#C19
     static get #sizeOf() → dart.core::int*
       return #C17.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -101,19 +101,19 @@
   #C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = 0
-  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
+  #C9 = <dart.core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
   #C10 = 4
   #C11 = 8
-  #C12 = <dart.core::int*>[#C10, #C11, #C10, #C11, #C11, #C11, #C10, #C11, #C11, #C10, #C11, #C10, #C11, #C11, #C11, #C11, #C10, #C11]
+  #C12 = <dart.core::int*>[#C10, #C11, #C10, #C11, #C11, #C11, #C10, #C11, #C11, #C10, #C11, #C10, #C11, #C10, #C11, #C11, #C11, #C11, #C10, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C11, #C13, #C11, #C13, #C13, #C13, #C11, #C13, #C13, #C11, #C13, #C11, #C13, #C13, #C13, #C13, #C11, #C13]
+  #C14 = <dart.core::int*>[#C11, #C13, #C11, #C13, #C13, #C13, #C11, #C13, #C13, #C11, #C13, #C11, #C13, #C11, #C13, #C13, #C13, #C13, #C11, #C13]
   #C15 = 12
   #C16 = 24
-  #C17 = <dart.core::int*>[#C15, #C16, #C15, #C16, #C16, #C16, #C15, #C16, #C16, #C15, #C16, #C15, #C16, #C16, #C16, #C16, #C15, #C16]
+  #C17 = <dart.core::int*>[#C15, #C16, #C15, #C16, #C16, #C16, #C15, #C16, #C16, #C15, #C16, #C15, #C16, #C15, #C16, #C16, #C16, #C16, #C15, #C16]
   #C18 = "vm:prefer-inline"
   #C19 = dart.core::pragma {name:#C18, options:#C5}
   #C20 = 48
-  #C21 = <dart.core::int*>[#C16, #C20, #C16, #C20, #C20, #C20, #C16, #C20, #C20, #C16, #C20, #C16, #C20, #C20, #C20, #C20, #C16, #C20]
+  #C21 = <dart.core::int*>[#C16, #C20, #C16, #C20, #C20, #C20, #C16, #C20, #C20, #C16, #C20, #C16, #C20, #C16, #C20, #C20, #C20, #C20, #C16, #C20]
   #C22 = <dart.core::Type>[#C2, #C2, #C2]
   #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
   #C24 = dart.core::pragma {name:#C1, options:#C23}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml
index ca31b68..8f4c25d 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml
+++ b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml
@@ -8,7 +8,7 @@
 type: newworld
 worlds:
   - entry: main.dart
-    warnings: true # Warning: Interpreting this as package URI
+    warnings: false
     experiments: alternative-invalidation-strategy
     sources:
       main.dart: |
@@ -26,7 +26,7 @@
         foo:.
     expectedLibraryCount: 2
   - entry: main.dart
-    warnings: true # Warning: Interpreting this as package URI
+    warnings: false
     experiments: alternative-invalidation-strategy
     worldType: updated
     expectInitializeFromDill: false
@@ -43,7 +43,7 @@
     expectedLibraryCount: 2
     expectsRebuildBodiesOnly: true
   - entry: main.dart
-    warnings: true # Warning: Interpreting this as package URI
+    warnings: false
     experiments: alternative-invalidation-strategy
     worldType: updated
     expectInitializeFromDill: false
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.1.expect
index be30c89..303ea49 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.1.expect
@@ -1,9 +1,4 @@
 main = main::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   static method libMethod() → dynamic {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.2.expect
index e6183a8..75db5a9 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.2.expect
@@ -1,9 +1,4 @@
 main = main::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   static method libMethod() → dynamic {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.3.expect
index bfa1434..81aa2aa 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_27.yaml.world.3.expect
@@ -1,9 +1,4 @@
 main = main::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   static method libMethod() → dynamic {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.1.expect
index 5293243..29c46d4 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.1.expect
@@ -28,34 +28,34 @@
       }
       return this.{main::C::_#C#field5}{dart.core::int?};
     }
-    set field5(dart.core::int? #t1) → void {
+    set field5(dart.core::int? field5#param) → void {
       this.{main::C::_#C#field5#isSet} = true;
-      this.{main::C::_#C#field5} = #t1;
+      this.{main::C::_#C#field5} = field5#param;
     }
     get field6() → dart.core::int?
       return this.{main::C::_#C#field6#isSet}{dart.core::bool} ?{dart.core::int?} this.{main::C::_#C#field6}{dart.core::int?} : throw new dart._internal::LateError::fieldNI("field6");
-    set field6(dart.core::int? #t2) → void {
+    set field6(dart.core::int? field6#param) → void {
       this.{main::C::_#C#field6#isSet} = true;
-      this.{main::C::_#C#field6} = #t2;
+      this.{main::C::_#C#field6} = field6#param;
     }
     get field7() → dart.core::int? {
       if(!this.{main::C::_#C#field7#isSet}{dart.core::bool}) {
-        final dart.core::int? #t3 = 42;
+        final dart.core::int? #t1 = 42;
         if(this.{main::C::_#C#field7#isSet}{dart.core::bool})
           throw new dart._internal::LateError::fieldADI("field7");
-        this.{main::C::_#C#field7} = #t3;
+        this.{main::C::_#C#field7} = #t1;
         this.{main::C::_#C#field7#isSet} = true;
       }
       return this.{main::C::_#C#field7}{dart.core::int?};
     }
     get field8() → dart.core::int?
       return this.{main::C::_#C#field8#isSet}{dart.core::bool} ?{dart.core::int?} this.{main::C::_#C#field8}{dart.core::int?} : throw new dart._internal::LateError::fieldNI("field8");
-    set field8(dart.core::int? #t4) → void
+    set field8(dart.core::int? field8#param) → void
       if(this.{main::C::_#C#field8#isSet}{dart.core::bool})
         throw new dart._internal::LateError::fieldAI("field8");
       else {
         this.{main::C::_#C#field8#isSet} = true;
-        this.{main::C::_#C#field8} = #t4;
+        this.{main::C::_#C#field8} = field8#param;
       }
     static get field9() → dart.core::int? {
       if(!main::C::_#field9#isSet) {
@@ -64,34 +64,34 @@
       }
       return main::C::_#field9;
     }
-    static set field9(dart.core::int? #t5) → void {
+    static set field9(dart.core::int? field9#param) → void {
       main::C::_#field9#isSet = true;
-      main::C::_#field9 = #t5;
+      main::C::_#field9 = field9#param;
     }
     static get field10() → dart.core::int?
       return main::C::_#field10#isSet ?{dart.core::int?} main::C::_#field10 : throw new dart._internal::LateError::fieldNI("field10");
-    static set field10(dart.core::int? #t6) → void {
+    static set field10(dart.core::int? field10#param) → void {
       main::C::_#field10#isSet = true;
-      main::C::_#field10 = #t6;
+      main::C::_#field10 = field10#param;
     }
     static get field11() → dart.core::int? {
       if(!main::C::_#field11#isSet) {
-        final dart.core::int? #t7 = 42;
+        final dart.core::int? #t2 = 42;
         if(main::C::_#field11#isSet)
           throw new dart._internal::LateError::fieldADI("field11");
-        main::C::_#field11 = #t7;
+        main::C::_#field11 = #t2;
         main::C::_#field11#isSet = true;
       }
       return main::C::_#field11;
     }
     static get field12() → dart.core::int?
       return main::C::_#field12#isSet ?{dart.core::int?} main::C::_#field12 : throw new dart._internal::LateError::fieldNI("field12");
-    static set field12(dart.core::int? #t8) → void
+    static set field12(dart.core::int? field12#param) → void
       if(main::C::_#field12#isSet)
         throw new dart._internal::LateError::fieldAI("field12");
       else {
         main::C::_#field12#isSet = true;
-        main::C::_#field12 = #t8;
+        main::C::_#field12 = field12#param;
       }
   }
   static field dart.core::int? _#field1 = null;
@@ -109,34 +109,34 @@
     }
     return main::_#field1;
   }
-  static set field1(dart.core::int? #t9) → void {
+  static set field1(dart.core::int? field1#param) → void {
     main::_#field1#isSet = true;
-    main::_#field1 = #t9;
+    main::_#field1 = field1#param;
   }
   static get field2() → dart.core::int?
     return main::_#field2#isSet ?{dart.core::int?} main::_#field2 : throw new dart._internal::LateError::fieldNI("field2");
-  static set field2(dart.core::int? #t10) → void {
+  static set field2(dart.core::int? field2#param) → void {
     main::_#field2#isSet = true;
-    main::_#field2 = #t10;
+    main::_#field2 = field2#param;
   }
   static get field3() → dart.core::int? {
     if(!main::_#field3#isSet) {
-      final dart.core::int? #t11 = 42;
+      final dart.core::int? #t3 = 42;
       if(main::_#field3#isSet)
         throw new dart._internal::LateError::fieldADI("field3");
-      main::_#field3 = #t11;
+      main::_#field3 = #t3;
       main::_#field3#isSet = true;
     }
     return main::_#field3;
   }
   static get field4() → dart.core::int?
     return main::_#field4#isSet ?{dart.core::int?} main::_#field4 : throw new dart._internal::LateError::fieldNI("field4");
-  static set field4(dart.core::int? #t12) → void
+  static set field4(dart.core::int? field4#param) → void
     if(main::_#field4#isSet)
       throw new dart._internal::LateError::fieldAI("field4");
     else {
       main::_#field4#isSet = true;
-      main::_#field4 = #t12;
+      main::_#field4 = field4#param;
     }
   static method main() → dynamic {
     main::field1 = 43;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.2.expect
index 20d8f89..5390040 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_29.yaml.world.2.expect
@@ -28,34 +28,34 @@
       }
       return this.{main::C::_#C#field5}{dart.core::int?};
     }
-    set field5(dart.core::int? #t1) → void {
+    set field5(dart.core::int? field5#param) → void {
       this.{main::C::_#C#field5#isSet} = true;
-      this.{main::C::_#C#field5} = #t1;
+      this.{main::C::_#C#field5} = field5#param;
     }
     get field6() → dart.core::int?
       return this.{main::C::_#C#field6#isSet}{dart.core::bool} ?{dart.core::int?} this.{main::C::_#C#field6}{dart.core::int?} : throw new dart._internal::LateError::fieldNI("field6");
-    set field6(dart.core::int? #t2) → void {
+    set field6(dart.core::int? field6#param) → void {
       this.{main::C::_#C#field6#isSet} = true;
-      this.{main::C::_#C#field6} = #t2;
+      this.{main::C::_#C#field6} = field6#param;
     }
     get field7() → dart.core::int? {
       if(!this.{main::C::_#C#field7#isSet}{dart.core::bool}) {
-        final dart.core::int? #t3 = 42;
+        final dart.core::int? #t1 = 42;
         if(this.{main::C::_#C#field7#isSet}{dart.core::bool})
           throw new dart._internal::LateError::fieldADI("field7");
-        this.{main::C::_#C#field7} = #t3;
+        this.{main::C::_#C#field7} = #t1;
         this.{main::C::_#C#field7#isSet} = true;
       }
       return this.{main::C::_#C#field7}{dart.core::int?};
     }
     get field8() → dart.core::int?
       return this.{main::C::_#C#field8#isSet}{dart.core::bool} ?{dart.core::int?} this.{main::C::_#C#field8}{dart.core::int?} : throw new dart._internal::LateError::fieldNI("field8");
-    set field8(dart.core::int? #t4) → void
+    set field8(dart.core::int? field8#param) → void
       if(this.{main::C::_#C#field8#isSet}{dart.core::bool})
         throw new dart._internal::LateError::fieldAI("field8");
       else {
         this.{main::C::_#C#field8#isSet} = true;
-        this.{main::C::_#C#field8} = #t4;
+        this.{main::C::_#C#field8} = field8#param;
       }
     static get field9() → dart.core::int? {
       if(!main::C::_#field9#isSet) {
@@ -64,34 +64,34 @@
       }
       return main::C::_#field9;
     }
-    static set field9(dart.core::int? #t5) → void {
+    static set field9(dart.core::int? field9#param) → void {
       main::C::_#field9#isSet = true;
-      main::C::_#field9 = #t5;
+      main::C::_#field9 = field9#param;
     }
     static get field10() → dart.core::int?
       return main::C::_#field10#isSet ?{dart.core::int?} main::C::_#field10 : throw new dart._internal::LateError::fieldNI("field10");
-    static set field10(dart.core::int? #t6) → void {
+    static set field10(dart.core::int? field10#param) → void {
       main::C::_#field10#isSet = true;
-      main::C::_#field10 = #t6;
+      main::C::_#field10 = field10#param;
     }
     static get field11() → dart.core::int? {
       if(!main::C::_#field11#isSet) {
-        final dart.core::int? #t7 = 42;
+        final dart.core::int? #t2 = 42;
         if(main::C::_#field11#isSet)
           throw new dart._internal::LateError::fieldADI("field11");
-        main::C::_#field11 = #t7;
+        main::C::_#field11 = #t2;
         main::C::_#field11#isSet = true;
       }
       return main::C::_#field11;
     }
     static get field12() → dart.core::int?
       return main::C::_#field12#isSet ?{dart.core::int?} main::C::_#field12 : throw new dart._internal::LateError::fieldNI("field12");
-    static set field12(dart.core::int? #t8) → void
+    static set field12(dart.core::int? field12#param) → void
       if(main::C::_#field12#isSet)
         throw new dart._internal::LateError::fieldAI("field12");
       else {
         main::C::_#field12#isSet = true;
-        main::C::_#field12 = #t8;
+        main::C::_#field12 = field12#param;
       }
   }
   static field dart.core::int? _#field1 = null;
@@ -109,34 +109,34 @@
     }
     return main::_#field1;
   }
-  static set field1(dart.core::int? #t9) → void {
+  static set field1(dart.core::int? field1#param) → void {
     main::_#field1#isSet = true;
-    main::_#field1 = #t9;
+    main::_#field1 = field1#param;
   }
   static get field2() → dart.core::int?
     return main::_#field2#isSet ?{dart.core::int?} main::_#field2 : throw new dart._internal::LateError::fieldNI("field2");
-  static set field2(dart.core::int? #t10) → void {
+  static set field2(dart.core::int? field2#param) → void {
     main::_#field2#isSet = true;
-    main::_#field2 = #t10;
+    main::_#field2 = field2#param;
   }
   static get field3() → dart.core::int? {
     if(!main::_#field3#isSet) {
-      final dart.core::int? #t11 = 42;
+      final dart.core::int? #t3 = 42;
       if(main::_#field3#isSet)
         throw new dart._internal::LateError::fieldADI("field3");
-      main::_#field3 = #t11;
+      main::_#field3 = #t3;
       main::_#field3#isSet = true;
     }
     return main::_#field3;
   }
   static get field4() → dart.core::int?
     return main::_#field4#isSet ?{dart.core::int?} main::_#field4 : throw new dart._internal::LateError::fieldNI("field4");
-  static set field4(dart.core::int? #t12) → void
+  static set field4(dart.core::int? field4#param) → void
     if(main::_#field4#isSet)
       throw new dart._internal::LateError::fieldAI("field4");
     else {
       main::_#field4#isSet = true;
-      main::_#field4 = #t12;
+      main::_#field4 = field4#param;
     }
   static method main() → dynamic {
     main::field1 = 44;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.1.expect
index e94d83d..374b144 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.1.expect
@@ -46,34 +46,34 @@
     }
     return main::_#field1;
   }
-  static set field1(dart.core::int? #t1) → void {
+  static set field1(dart.core::int? field1#param) → void {
     main::_#field1#isSet = true;
-    main::_#field1 = #t1;
+    main::_#field1 = field1#param;
   }
   static get field2() → dart.core::int?
     return main::_#field2#isSet ?{dart.core::int?} main::_#field2 : throw new dart._internal::LateError::fieldNI("field2");
-  static set field2(dart.core::int? #t2) → void {
+  static set field2(dart.core::int? field2#param) → void {
     main::_#field2#isSet = true;
-    main::_#field2 = #t2;
+    main::_#field2 = field2#param;
   }
   static get field3() → dart.core::int? {
     if(!main::_#field3#isSet) {
-      final dart.core::int? #t3 = 42;
+      final dart.core::int? #t1 = 42;
       if(main::_#field3#isSet)
         throw new dart._internal::LateError::fieldADI("field3");
-      main::_#field3 = #t3;
+      main::_#field3 = #t1;
       main::_#field3#isSet = true;
     }
     return main::_#field3;
   }
   static get field4() → dart.core::int?
     return main::_#field4#isSet ?{dart.core::int?} main::_#field4 : throw new dart._internal::LateError::fieldNI("field4");
-  static set field4(dart.core::int? #t4) → void
+  static set field4(dart.core::int? field4#param) → void
     if(main::_#field4#isSet)
       throw new dart._internal::LateError::fieldAI("field4");
     else {
       main::_#field4#isSet = true;
-      main::_#field4 = #t4;
+      main::_#field4 = field4#param;
     }
   static get _extension#0|field5() → dart.core::int? {
     if(!main::_#_extension#0|field5#isSet) {
@@ -82,34 +82,34 @@
     }
     return main::_#_extension#0|field5;
   }
-  static set _extension#0|field5(dart.core::int? #t5) → void {
+  static set _extension#0|field5(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field5#param) → void {
     main::_#_extension#0|field5#isSet = true;
-    main::_#_extension#0|field5 = #t5;
+    main::_#_extension#0|field5 = library org-dartlang-test:///main.dart::_extension#0|field5#param;
   }
   static get _extension#0|field6() → dart.core::int?
     return main::_#_extension#0|field6#isSet ?{dart.core::int?} main::_#_extension#0|field6 : throw new dart._internal::LateError::fieldNI("field6");
-  static set _extension#0|field6(dart.core::int? #t6) → void {
+  static set _extension#0|field6(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field6#param) → void {
     main::_#_extension#0|field6#isSet = true;
-    main::_#_extension#0|field6 = #t6;
+    main::_#_extension#0|field6 = library org-dartlang-test:///main.dart::_extension#0|field6#param;
   }
   static get _extension#0|field7() → dart.core::int? {
     if(!main::_#_extension#0|field7#isSet) {
-      final dart.core::int? #t7 = 42;
+      final dart.core::int? #t2 = 42;
       if(main::_#_extension#0|field7#isSet)
         throw new dart._internal::LateError::fieldADI("field7");
-      main::_#_extension#0|field7 = #t7;
+      main::_#_extension#0|field7 = #t2;
       main::_#_extension#0|field7#isSet = true;
     }
     return main::_#_extension#0|field7;
   }
   static get _extension#0|field8() → dart.core::int?
     return main::_#_extension#0|field8#isSet ?{dart.core::int?} main::_#_extension#0|field8 : throw new dart._internal::LateError::fieldNI("field8");
-  static set _extension#0|field8(dart.core::int? #t8) → void
+  static set _extension#0|field8(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field8#param) → void
     if(main::_#_extension#0|field8#isSet)
       throw new dart._internal::LateError::fieldAI("field8");
     else {
       main::_#_extension#0|field8#isSet = true;
-      main::_#_extension#0|field8 = #t8;
+      main::_#_extension#0|field8 = library org-dartlang-test:///main.dart::_extension#0|field8#param;
     }
   static method main() → dynamic {
     main::field1 = 43;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.2.expect
index 94a763e..65c62a4 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_31.yaml.world.2.expect
@@ -46,34 +46,34 @@
     }
     return main::_#field1;
   }
-  static set field1(dart.core::int? #t1) → void {
+  static set field1(dart.core::int? field1#param) → void {
     main::_#field1#isSet = true;
-    main::_#field1 = #t1;
+    main::_#field1 = field1#param;
   }
   static get field2() → dart.core::int?
     return main::_#field2#isSet ?{dart.core::int?} main::_#field2 : throw new dart._internal::LateError::fieldNI("field2");
-  static set field2(dart.core::int? #t2) → void {
+  static set field2(dart.core::int? field2#param) → void {
     main::_#field2#isSet = true;
-    main::_#field2 = #t2;
+    main::_#field2 = field2#param;
   }
   static get field3() → dart.core::int? {
     if(!main::_#field3#isSet) {
-      final dart.core::int? #t3 = 42;
+      final dart.core::int? #t1 = 42;
       if(main::_#field3#isSet)
         throw new dart._internal::LateError::fieldADI("field3");
-      main::_#field3 = #t3;
+      main::_#field3 = #t1;
       main::_#field3#isSet = true;
     }
     return main::_#field3;
   }
   static get field4() → dart.core::int?
     return main::_#field4#isSet ?{dart.core::int?} main::_#field4 : throw new dart._internal::LateError::fieldNI("field4");
-  static set field4(dart.core::int? #t4) → void
+  static set field4(dart.core::int? field4#param) → void
     if(main::_#field4#isSet)
       throw new dart._internal::LateError::fieldAI("field4");
     else {
       main::_#field4#isSet = true;
-      main::_#field4 = #t4;
+      main::_#field4 = field4#param;
     }
   static get _extension#0|field5() → dart.core::int? {
     if(!main::_#_extension#0|field5#isSet) {
@@ -82,34 +82,34 @@
     }
     return main::_#_extension#0|field5;
   }
-  static set _extension#0|field5(dart.core::int? #t5) → void {
+  static set _extension#0|field5(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field5#param) → void {
     main::_#_extension#0|field5#isSet = true;
-    main::_#_extension#0|field5 = #t5;
+    main::_#_extension#0|field5 = library org-dartlang-test:///main.dart::_extension#0|field5#param;
   }
   static get _extension#0|field6() → dart.core::int?
     return main::_#_extension#0|field6#isSet ?{dart.core::int?} main::_#_extension#0|field6 : throw new dart._internal::LateError::fieldNI("field6");
-  static set _extension#0|field6(dart.core::int? #t6) → void {
+  static set _extension#0|field6(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field6#param) → void {
     main::_#_extension#0|field6#isSet = true;
-    main::_#_extension#0|field6 = #t6;
+    main::_#_extension#0|field6 = library org-dartlang-test:///main.dart::_extension#0|field6#param;
   }
   static get _extension#0|field7() → dart.core::int? {
     if(!main::_#_extension#0|field7#isSet) {
-      final dart.core::int? #t7 = 42;
+      final dart.core::int? #t2 = 42;
       if(main::_#_extension#0|field7#isSet)
         throw new dart._internal::LateError::fieldADI("field7");
-      main::_#_extension#0|field7 = #t7;
+      main::_#_extension#0|field7 = #t2;
       main::_#_extension#0|field7#isSet = true;
     }
     return main::_#_extension#0|field7;
   }
   static get _extension#0|field8() → dart.core::int?
     return main::_#_extension#0|field8#isSet ?{dart.core::int?} main::_#_extension#0|field8 : throw new dart._internal::LateError::fieldNI("field8");
-  static set _extension#0|field8(dart.core::int? #t8) → void
+  static set _extension#0|field8(dart.core::int? library org-dartlang-test:///main.dart::_extension#0|field8#param) → void
     if(main::_#_extension#0|field8#isSet)
       throw new dart._internal::LateError::fieldAI("field8");
     else {
       main::_#_extension#0|field8#isSet = true;
-      main::_#_extension#0|field8 = #t8;
+      main::_#_extension#0|field8 = library org-dartlang-test:///main.dart::_extension#0|field8#param;
     }
   static method main() → dynamic {
     main::field1 = 44;
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
index 2e5c180..e6e7693 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
@@ -33,9 +33,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -62,14 +62,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
index 9d91273..1134f3c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
@@ -33,9 +33,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -63,14 +63,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
index afef6e0..e52f835 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
@@ -34,9 +34,9 @@
     set y(dart.core::double* #v) → void
       return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C12.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C14.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #v.{dart.ffi::Pointer::address}{dart.core::int});
     @#C16
     static get /*isNonNullableByDefault*/ #sizeOf() → dart.core::int*
       return #C19.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -64,14 +64,14 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Double {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <dart.core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = dart.core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <dart.core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.1.expect
index bfa9c36..b6fc3dc 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.1.expect
@@ -5,9 +5,9 @@
   static field dart.core::bool _#field#isSet = false;
   static get field() → dart.core::int
     return lib1::_#field#isSet ?{dart.core::int} let final dart.core::int? #t1 = lib1::_#field in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("field");
-  static set field(dart.core::int #t2) → void {
+  static set field(dart.core::int field#param) → void {
     lib1::_#field#isSet = true;
-    lib1::_#field = #t2;
+    lib1::_#field = field#param;
   }
   static method method() → dynamic {
     dart.core::print("foo");
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.2.expect
index 20aeb39..47febef 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.2.expect
@@ -5,9 +5,9 @@
   static field dart.core::bool _#field#isSet = false;
   static get field() → dart.core::int
     return lib1::_#field#isSet ?{dart.core::int} let final dart.core::int? #t1 = lib1::_#field in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("field");
-  static set field(dart.core::int #t2) → void {
+  static set field(dart.core::int field#param) → void {
     lib1::_#field#isSet = true;
-    lib1::_#field = #t2;
+    lib1::_#field = field#param;
   }
   static method method() → dynamic {
     dart.core::print("foo");
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.3.expect
index c5f9982..c6a44c1 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_41.yaml.world.3.expect
@@ -5,9 +5,9 @@
   static field dart.core::bool _#field#isSet = false;
   static get field() → dart.core::int
     return lib1::_#field#isSet ?{dart.core::int} let final dart.core::int? #t1 = lib1::_#field in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("field");
-  static set field(dart.core::int #t2) → void {
+  static set field(dart.core::int field#param) → void {
     lib1::_#field#isSet = true;
-    lib1::_#field = #t2;
+    lib1::_#field = field#param;
   }
   static method method() → dynamic {
     dart.core::print("bar");
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.1.expect
index 3f3d73e..a86189c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.1.expect
@@ -82,26 +82,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 1
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = dart.ffi::Uint64 {}
   #C14 = 8
   #C15 = 4
-  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14]
+  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14]
   #C17 = "vm:prefer-inline"
   #C18 = dart.core::pragma {name:#C17, options:#C5}
   #C19 = 16
   #C20 = 12
-  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19]
+  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19, #C19, #C19]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 32
   #C27 = 24
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 40
   #C30 = 28
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.2.expect
index e241ee1..a9302fa 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_48_ffi.yaml.world.2.expect
@@ -82,26 +82,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = dart.ffi::Uint64 {}
   #C12 = 8
   #C13 = 4
-  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12]
+  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
   #C15 = 16
   #C16 = 12
-  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15]
+  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15, #C15, #C15]
   #C18 = "vm:prefer-inline"
   #C19 = dart.core::pragma {name:#C18, options:#C5}
   #C20 = 24
-  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20]
+  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20, #C20, #C20]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 48
   #C27 = 32
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 56
   #C30 = 36
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.1.expect
index 3f3d73e..a86189c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.1.expect
@@ -82,26 +82,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 1
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = dart.ffi::Uint64 {}
   #C14 = 8
   #C15 = 4
-  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14]
+  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14]
   #C17 = "vm:prefer-inline"
   #C18 = dart.core::pragma {name:#C17, options:#C5}
   #C19 = 16
   #C20 = 12
-  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19]
+  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19, #C19, #C19]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 32
   #C27 = 24
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 40
   #C30 = 28
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.2.expect
index e241ee1..a9302fa 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_49_ffi.yaml.world.2.expect
@@ -82,26 +82,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = dart.ffi::Uint64 {}
   #C12 = 8
   #C13 = 4
-  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12]
+  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
   #C15 = 16
   #C16 = 12
-  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15]
+  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15, #C15, #C15]
   #C18 = "vm:prefer-inline"
   #C19 = dart.core::pragma {name:#C18, options:#C5}
   #C20 = 24
-  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20]
+  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20, #C20, #C20]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 48
   #C27 = 32
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 56
   #C30 = 36
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index ffb841a..cf7f401 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -63,6 +63,7 @@
   ffi::FloatArray,
   ffi::FloatPointer,
   ffi::Handle,
+  ffi::Int,
   ffi::Int16,
   ffi::Int16Array,
   ffi::Int16Pointer,
@@ -76,8 +77,8 @@
   ffi::Int8Array,
   ffi::Int8Pointer,
   ffi::IntPtr,
-  ffi::IntPtrArray,
-  ffi::IntPtrPointer,
+  ffi::Long,
+  ffi::LongLong,
   ffi::NativeApi,
   ffi::NativeFunction,
   ffi::NativeFunctionPointer,
@@ -88,6 +89,9 @@
   ffi::Pointer,
   ffi::PointerArray,
   ffi::PointerPointer,
+  ffi::Short,
+  ffi::SignedChar,
+  ffi::Size,
   ffi::Struct,
   ffi::StructArray,
   ffi::StructPointer,
@@ -103,11 +107,18 @@
   ffi::Uint8,
   ffi::Uint8Array,
   ffi::Uint8Pointer,
+  ffi::UintPtr,
   ffi::Union,
   ffi::UnionArray,
   ffi::UnionPointer,
+  ffi::UnsignedChar,
+  ffi::UnsignedInt,
+  ffi::UnsignedLong,
+  ffi::UnsignedLongLong,
+  ffi::UnsignedShort,
   ffi::Unsized,
-  ffi::Void)
+  ffi::Void,
+  ffi::WChar)
 
   export "org-dartlang-test:///lib3.dart";
 
@@ -141,6 +152,7 @@
   ffi::FloatArray,
   ffi::FloatPointer,
   ffi::Handle,
+  ffi::Int,
   ffi::Int16,
   ffi::Int16Array,
   ffi::Int16Pointer,
@@ -154,8 +166,8 @@
   ffi::Int8Array,
   ffi::Int8Pointer,
   ffi::IntPtr,
-  ffi::IntPtrArray,
-  ffi::IntPtrPointer,
+  ffi::Long,
+  ffi::LongLong,
   ffi::NativeApi,
   ffi::NativeFunction,
   ffi::NativeFunctionPointer,
@@ -166,6 +178,9 @@
   ffi::Pointer,
   ffi::PointerArray,
   ffi::PointerPointer,
+  ffi::Short,
+  ffi::SignedChar,
+  ffi::Size,
   ffi::Struct,
   ffi::StructArray,
   ffi::StructPointer,
@@ -181,11 +196,18 @@
   ffi::Uint8,
   ffi::Uint8Array,
   ffi::Uint8Pointer,
+  ffi::UintPtr,
   ffi::Union,
   ffi::UnionArray,
   ffi::UnionPointer,
+  ffi::UnsignedChar,
+  ffi::UnsignedInt,
+  ffi::UnsignedLong,
+  ffi::UnsignedLongLong,
+  ffi::UnsignedShort,
   ffi::Unsized,
-  ffi::Void)
+  ffi::Void,
+  ffi::WChar)
 
   export "dart:ffi";
 
@@ -238,26 +260,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 1
-  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <dart.core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = dart.ffi::Uint64 {}
   #C14 = 8
   #C15 = 4
-  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14]
+  #C16 = <dart.core::int*>[#C14, #C14, #C15, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C15, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14]
   #C17 = "vm:prefer-inline"
   #C18 = dart.core::pragma {name:#C17, options:#C5}
   #C19 = 16
   #C20 = 12
-  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19]
+  #C21 = <dart.core::int*>[#C19, #C19, #C20, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C20, #C19, #C19, #C19, #C19, #C19, #C19, #C19, #C19]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 32
   #C27 = 24
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 40
   #C30 = 28
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index 40804c4..cb6c619 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -63,6 +63,7 @@
   ffi::FloatArray,
   ffi::FloatPointer,
   ffi::Handle,
+  ffi::Int,
   ffi::Int16,
   ffi::Int16Array,
   ffi::Int16Pointer,
@@ -76,8 +77,8 @@
   ffi::Int8Array,
   ffi::Int8Pointer,
   ffi::IntPtr,
-  ffi::IntPtrArray,
-  ffi::IntPtrPointer,
+  ffi::Long,
+  ffi::LongLong,
   ffi::NativeApi,
   ffi::NativeFunction,
   ffi::NativeFunctionPointer,
@@ -88,6 +89,9 @@
   ffi::Pointer,
   ffi::PointerArray,
   ffi::PointerPointer,
+  ffi::Short,
+  ffi::SignedChar,
+  ffi::Size,
   ffi::Struct,
   ffi::StructArray,
   ffi::StructPointer,
@@ -103,11 +107,18 @@
   ffi::Uint8,
   ffi::Uint8Array,
   ffi::Uint8Pointer,
+  ffi::UintPtr,
   ffi::Union,
   ffi::UnionArray,
   ffi::UnionPointer,
+  ffi::UnsignedChar,
+  ffi::UnsignedInt,
+  ffi::UnsignedLong,
+  ffi::UnsignedLongLong,
+  ffi::UnsignedShort,
   ffi::Unsized,
-  ffi::Void)
+  ffi::Void,
+  ffi::WChar)
 
   export "org-dartlang-test:///lib3.dart";
 
@@ -141,6 +152,7 @@
   ffi::FloatArray,
   ffi::FloatPointer,
   ffi::Handle,
+  ffi::Int,
   ffi::Int16,
   ffi::Int16Array,
   ffi::Int16Pointer,
@@ -154,8 +166,8 @@
   ffi::Int8Array,
   ffi::Int8Pointer,
   ffi::IntPtr,
-  ffi::IntPtrArray,
-  ffi::IntPtrPointer,
+  ffi::Long,
+  ffi::LongLong,
   ffi::NativeApi,
   ffi::NativeFunction,
   ffi::NativeFunctionPointer,
@@ -166,6 +178,9 @@
   ffi::Pointer,
   ffi::PointerArray,
   ffi::PointerPointer,
+  ffi::Short,
+  ffi::SignedChar,
+  ffi::Size,
   ffi::Struct,
   ffi::StructArray,
   ffi::StructPointer,
@@ -181,11 +196,18 @@
   ffi::Uint8,
   ffi::Uint8Array,
   ffi::Uint8Pointer,
+  ffi::UintPtr,
   ffi::Union,
   ffi::UnionArray,
   ffi::UnionPointer,
+  ffi::UnsignedChar,
+  ffi::UnsignedInt,
+  ffi::UnsignedLong,
+  ffi::UnsignedLongLong,
+  ffi::UnsignedShort,
   ffi::Unsized,
-  ffi::Void)
+  ffi::Void,
+  ffi::WChar)
 
   export "dart:ffi";
 
@@ -238,26 +260,26 @@
   #C7 = dart.core::pragma {name:#C1, options:#C6}
   #C8 = dart.ffi::Uint8 {}
   #C9 = 0
-  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <dart.core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = dart.ffi::Uint64 {}
   #C12 = 8
   #C13 = 4
-  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12]
+  #C14 = <dart.core::int*>[#C12, #C12, #C13, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C13, #C12, #C12, #C12, #C12, #C12, #C12, #C12, #C12]
   #C15 = 16
   #C16 = 12
-  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15]
+  #C17 = <dart.core::int*>[#C15, #C15, #C16, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C16, #C15, #C15, #C15, #C15, #C15, #C15, #C15, #C15]
   #C18 = "vm:prefer-inline"
   #C19 = dart.core::pragma {name:#C18, options:#C5}
   #C20 = 24
-  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20]
+  #C21 = <dart.core::int*>[#C20, #C20, #C15, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C15, #C20, #C20, #C20, #C20, #C20, #C20, #C20, #C20]
   #C22 = TypeLiteralConstant(lib::Y)
   #C23 = <dart.core::Type>[#C22, #C22, #C2]
   #C24 = dart.ffi::_FfiStructLayout {fieldTypes:#C23, packing:#C5}
   #C25 = dart.core::pragma {name:#C1, options:#C24}
   #C26 = 48
   #C27 = 32
-  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26]
+  #C28 = <dart.core::int*>[#C26, #C26, #C27, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C27, #C26, #C26, #C26, #C26, #C26, #C26, #C26, #C26]
   #C29 = 56
   #C30 = 36
-  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29]
+  #C31 = <dart.core::int*>[#C29, #C29, #C30, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C30, #C29, #C29, #C29, #C29, #C29, #C29, #C29, #C29]
 }
diff --git a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml
index ce316cc..27bb66c 100644
--- a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml
+++ b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml
@@ -5,7 +5,7 @@
 type: newworld
 worlds:
   - entry: main.dart
-    warnings: true
+    warnings: false
     checkEntries: false
     sources:
       .packages: |
@@ -21,7 +21,7 @@
     expectedLibraryCount: 1
 
   - entry: main.dart
-    warnings: true
+    warnings: false
     checkEntries: false
     worldType: updated
     expectInitializeFromDill: false
@@ -30,7 +30,7 @@
     expectedLibraryCount: 1
 
   - entry: main.dart
-    warnings: true
+    warnings: false
     checkEntries: false
     worldType: updated
     expectInitializeFromDill: false
diff --git a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.1.expect
index e826847..c9c3c86 100644
--- a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.1.expect
@@ -1,9 +1,4 @@
 main = lib::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   part main.dart;
diff --git a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.2.expect
index e826847..c9c3c86 100644
--- a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.2.expect
@@ -1,9 +1,4 @@
 main = lib::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   part main.dart;
diff --git a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.3.expect b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.3.expect
index e826847..c9c3c86 100644
--- a/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/part_as_package_entry_2.yaml.world.3.expect
@@ -1,9 +1,4 @@
 main = lib::main;
-//
-// Problems in component:
-//
-// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
-//
 library from "package:foo/lib.dart" as lib {
 
   part main.dart;
diff --git a/pkg/front_end/testcases/incremental/regress_46004.yaml.world.1.expect b/pkg/front_end/testcases/incremental/regress_46004.yaml.world.1.expect
index 9cb7f28..81904cb 100644
--- a/pkg/front_end/testcases/incremental/regress_46004.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/regress_46004.yaml.world.1.expect
@@ -12,11 +12,11 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get lpVtbl() → dart.ffi::Pointer<dart.ffi::IntPtr>
-      return dart.ffi::_fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set lpVtbl(dart.ffi::Pointer<dart.ffi::IntPtr> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get vtable() → dart.ffi::Pointer<dart.ffi::IntPtr>
-      return dart.ffi::Pointer::fromAddress<dart.ffi::IntPtr>(dart.ffi::IntPtrPointer|get#value(this.{lib::COMObject::lpVtbl}{dart.ffi::Pointer<dart.ffi::IntPtr>}));
+      return dart.ffi::Pointer::fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{lib::COMObject::lpVtbl}{dart.ffi::Pointer<dart.ffi::IntPtr>}, #C7));
     @#C10
     static get #sizeOf() → dart.core::int*
       return #C13.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -55,12 +55,12 @@
   #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = 0
-  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
+  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
   #C9 = "vm:prefer-inline"
   #C10 = dart.core::pragma {name:#C9, options:#C4}
   #C11 = 4
   #C12 = 8
-  #C13 = <dart.core::int*>[#C11, #C12, #C11, #C12, #C12, #C12, #C11, #C12, #C12, #C11, #C12, #C11, #C12, #C12, #C12, #C12, #C11, #C12]
+  #C13 = <dart.core::int*>[#C11, #C12, #C11, #C12, #C12, #C12, #C11, #C12, #C12, #C11, #C12, #C11, #C12, #C11, #C12, #C12, #C12, #C12, #C11, #C12]
   #C14 = TypeLiteralConstant(lib::COMObject)
   #C15 = <dart.core::Type>[#C14]
   #C16 = dart.ffi::_FfiStructLayout {fieldTypes:#C15, packing:#C4}
diff --git a/pkg/front_end/testcases/incremental/regress_46004.yaml.world.2.expect b/pkg/front_end/testcases/incremental/regress_46004.yaml.world.2.expect
index 9cb7f28..81904cb 100644
--- a/pkg/front_end/testcases/incremental/regress_46004.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/regress_46004.yaml.world.2.expect
@@ -12,11 +12,11 @@
       : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
       ;
     get lpVtbl() → dart.ffi::Pointer<dart.ffi::IntPtr>
-      return dart.ffi::_fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+      return dart.ffi::_fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
     set lpVtbl(dart.ffi::Pointer<dart.ffi::IntPtr> #externalFieldValue) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+      return dart.ffi::_storeAbiSpecificInt<dart.ffi::IntPtr>(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
     get vtable() → dart.ffi::Pointer<dart.ffi::IntPtr>
-      return dart.ffi::Pointer::fromAddress<dart.ffi::IntPtr>(dart.ffi::IntPtrPointer|get#value(this.{lib::COMObject::lpVtbl}{dart.ffi::Pointer<dart.ffi::IntPtr>}));
+      return dart.ffi::Pointer::fromAddress<dart.ffi::IntPtr>(dart.ffi::_loadAbiSpecificInt<dart.ffi::IntPtr>(this.{lib::COMObject::lpVtbl}{dart.ffi::Pointer<dart.ffi::IntPtr>}, #C7));
     @#C10
     static get #sizeOf() → dart.core::int*
       return #C13.{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
@@ -55,12 +55,12 @@
   #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
   #C6 = dart.core::pragma {name:#C1, options:#C5}
   #C7 = 0
-  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
+  #C8 = <dart.core::int*>[#C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7, #C7]
   #C9 = "vm:prefer-inline"
   #C10 = dart.core::pragma {name:#C9, options:#C4}
   #C11 = 4
   #C12 = 8
-  #C13 = <dart.core::int*>[#C11, #C12, #C11, #C12, #C12, #C12, #C11, #C12, #C12, #C11, #C12, #C11, #C12, #C12, #C12, #C12, #C11, #C12]
+  #C13 = <dart.core::int*>[#C11, #C12, #C11, #C12, #C12, #C12, #C11, #C12, #C12, #C11, #C12, #C11, #C12, #C11, #C12, #C12, #C12, #C12, #C11, #C12]
   #C14 = TypeLiteralConstant(lib::COMObject)
   #C15 = <dart.core::Type>[#C14]
   #C16 = dart.ffi::_FfiStructLayout {fieldTypes:#C15, packing:#C4}
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect b/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
index 844cd74..903cf4e 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
@@ -14,17 +14,17 @@
   lowered core::int? #local1;
   function #local1#get() → core::int
     return let final core::int? #t1 = #local1 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local1") : #t1{core::int};
-  function #local1#set(core::int #t2) → dynamic
-    return #local1 = #t2;
+  function #local1#set(core::int local1#param) → dynamic
+    return #local1 = local1#param;
   #local1#set(0){(core::int) → dynamic};
   self::expect(0, #local1#get(){() → core::int});
   #local1#set(#local1#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
   self::expect(2, #local1#get(){() → core::int});
   lowered core::int? #local2;
   function #local2#get() → core::int
-    return let final core::int? #t3 = #local2 in #t3 == null ?{core::int} #local2 = 1 : #t3{core::int};
-  function #local2#set(core::int #t4) → dynamic
-    return #local2 = #t4;
+    return let final core::int? #t2 = #local2 in #t2 == null ?{core::int} #local2 = 1 : #t2{core::int};
+  function #local2#set(core::int local2#param) → dynamic
+    return #local2 = local2#param;
   self::expect(1, #local2#get(){() → core::int});
   #local2#set(#local2#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
   self::expect(3, #local2#get(){() → core::int});
@@ -32,10 +32,10 @@
 static method error() → dynamic {
   lowered final core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t5 = #local in #t5 == null ?{core::int} throw new _in::LateError::localNI("local") : #t5{core::int};
-  function #local#set(core::int #t6) → dynamic
+    return let final core::int? #t3 = #local in #t3 == null ?{core::int} throw new _in::LateError::localNI("local") : #t3{core::int};
+  function #local#set(core::int local#param) → dynamic
     if(#local == null)
-      return #local = #t6;
+      return #local = local#param;
     else
       throw new _in::LateError::localAI("local");
   #local#set(invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
index 844cd74..903cf4e 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
@@ -14,17 +14,17 @@
   lowered core::int? #local1;
   function #local1#get() → core::int
     return let final core::int? #t1 = #local1 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local1") : #t1{core::int};
-  function #local1#set(core::int #t2) → dynamic
-    return #local1 = #t2;
+  function #local1#set(core::int local1#param) → dynamic
+    return #local1 = local1#param;
   #local1#set(0){(core::int) → dynamic};
   self::expect(0, #local1#get(){() → core::int});
   #local1#set(#local1#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
   self::expect(2, #local1#get(){() → core::int});
   lowered core::int? #local2;
   function #local2#get() → core::int
-    return let final core::int? #t3 = #local2 in #t3 == null ?{core::int} #local2 = 1 : #t3{core::int};
-  function #local2#set(core::int #t4) → dynamic
-    return #local2 = #t4;
+    return let final core::int? #t2 = #local2 in #t2 == null ?{core::int} #local2 = 1 : #t2{core::int};
+  function #local2#set(core::int local2#param) → dynamic
+    return #local2 = local2#param;
   self::expect(1, #local2#get(){() → core::int});
   #local2#set(#local2#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
   self::expect(3, #local2#get(){() → core::int});
@@ -32,10 +32,10 @@
 static method error() → dynamic {
   lowered final core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t5 = #local in #t5 == null ?{core::int} throw new _in::LateError::localNI("local") : #t5{core::int};
-  function #local#set(core::int #t6) → dynamic
+    return let final core::int? #t3 = #local in #t3 == null ?{core::int} throw new _in::LateError::localNI("local") : #t3{core::int};
+  function #local#set(core::int local#param) → dynamic
     if(#local == null)
-      return #local = #t6;
+      return #local = local#param;
     else
       throw new _in::LateError::localAI("local");
   #local#set(invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect b/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
index eb987a6..1092991 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
@@ -15,9 +15,9 @@
   lowered core::bool #local1#isSet = false;
   function #local1#get() → core::int
     return #local1#isSet ?{core::int} #local1{core::int} : throw new _in::LateError::localNI("local1");
-  function #local1#set(core::int #t1) → dynamic {
+  function #local1#set(core::int local1#param) → dynamic {
     #local1#isSet = true;
-    return #local1 = #t1;
+    return #local1 = local1#param;
   }
   #local1#set(0){(core::int) → dynamic};
   self::expect(0, #local1#get(){() → core::int});
@@ -32,9 +32,9 @@
     }
     return #local2{core::int};
   }
-  function #local2#set(core::int #t2) → dynamic {
+  function #local2#set(core::int local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t2;
+    return #local2 = local2#param;
   }
   self::expect(1, #local2#get(){() → core::int});
   #local2#set(#local2#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
@@ -45,12 +45,12 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t3) → dynamic
+  function #local#set(core::int local#param) → dynamic
     if(#local#isSet)
       throw new _in::LateError::localAI("local");
     else {
       #local#isSet = true;
-      return #local = #t3;
+      return #local = local#param;
     }
   #local#set(invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/compound.dart.weak.modular.expect
index eb987a6..1092991 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.weak.modular.expect
@@ -15,9 +15,9 @@
   lowered core::bool #local1#isSet = false;
   function #local1#get() → core::int
     return #local1#isSet ?{core::int} #local1{core::int} : throw new _in::LateError::localNI("local1");
-  function #local1#set(core::int #t1) → dynamic {
+  function #local1#set(core::int local1#param) → dynamic {
     #local1#isSet = true;
-    return #local1 = #t1;
+    return #local1 = local1#param;
   }
   #local1#set(0){(core::int) → dynamic};
   self::expect(0, #local1#get(){() → core::int});
@@ -32,9 +32,9 @@
     }
     return #local2{core::int};
   }
-  function #local2#set(core::int #t2) → dynamic {
+  function #local2#set(core::int local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t2;
+    return #local2 = local2#param;
   }
   self::expect(1, #local2#get(){() → core::int});
   #local2#set(#local2#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
@@ -45,12 +45,12 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t3) → dynamic
+  function #local#set(core::int local#param) → dynamic
     if(#local#isSet)
       throw new _in::LateError::localAI("local");
     else {
       #local#isSet = true;
-      return #local = #t3;
+      return #local = local#param;
     }
   #local#set(invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
index eb987a6..1092991 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
@@ -15,9 +15,9 @@
   lowered core::bool #local1#isSet = false;
   function #local1#get() → core::int
     return #local1#isSet ?{core::int} #local1{core::int} : throw new _in::LateError::localNI("local1");
-  function #local1#set(core::int #t1) → dynamic {
+  function #local1#set(core::int local1#param) → dynamic {
     #local1#isSet = true;
-    return #local1 = #t1;
+    return #local1 = local1#param;
   }
   #local1#set(0){(core::int) → dynamic};
   self::expect(0, #local1#get(){() → core::int});
@@ -32,9 +32,9 @@
     }
     return #local2{core::int};
   }
-  function #local2#set(core::int #t2) → dynamic {
+  function #local2#set(core::int local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t2;
+    return #local2 = local2#param;
   }
   self::expect(1, #local2#get(){() → core::int});
   #local2#set(#local2#get(){() → core::int}.{core::num::+}(2){(core::num) → core::int}){(core::int) → dynamic};
@@ -45,12 +45,12 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t3) → dynamic
+  function #local#set(core::int local#param) → dynamic
     if(#local#isSet)
       throw new _in::LateError::localAI("local");
     else {
       #local#isSet = true;
-      return #local = #t3;
+      return #local = local#param;
     }
   #local#set(invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.strong.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.strong.expect
index 78c816d..8a935f2 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.strong.expect
@@ -22,12 +22,12 @@
     ;
   get invariantField() → core::num
     return let final core::num? #t1 = this.{self::A::_#A#invariantField}{core::num?} in #t1 == null ?{core::num} throw new _in::LateError::fieldNI("invariantField") : #t1{core::num};
-  set invariantField(core::num #t2) → void
-    this.{self::A::_#A#invariantField} = #t2;
+  set invariantField(core::num invariantField#param) → void
+    this.{self::A::_#A#invariantField} = invariantField#param;
   get covariantField() → core::num
-    return let final core::num? #t3 = this.{self::A::_#A#covariantField}{core::num?} in #t3 == null ?{core::num} throw new _in::LateError::fieldNI("covariantField") : #t3{core::num};
-  set covariantField(covariant-by-declaration core::num #t4) → void
-    this.{self::A::_#A#covariantField} = #t4;
+    return let final core::num? #t2 = this.{self::A::_#A#covariantField}{core::num?} in #t2 == null ?{core::num} throw new _in::LateError::fieldNI("covariantField") : #t2{core::num};
+  set covariantField(covariant-by-declaration core::num covariantField#param) → void
+    this.{self::A::_#A#covariantField} = covariantField#param;
 }
 abstract class B extends core::Object implements self::A {
   synthetic constructor •() → self::B
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
index c2ac0b9..ee43c6f 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
@@ -24,15 +24,15 @@
     ;
   get invariantField() → core::num
     return this.{self::A::_#A#invariantField#isSet}{core::bool} ?{core::num} let final core::num? #t1 = this.{self::A::_#A#invariantField}{core::num?} in #t1{core::num} : throw new _in::LateError::fieldNI("invariantField");
-  set invariantField(core::num #t2) → void {
+  set invariantField(core::num invariantField#param) → void {
     this.{self::A::_#A#invariantField#isSet} = true;
-    this.{self::A::_#A#invariantField} = #t2;
+    this.{self::A::_#A#invariantField} = invariantField#param;
   }
   get covariantField() → core::num
-    return this.{self::A::_#A#covariantField#isSet}{core::bool} ?{core::num} let final core::num? #t3 = this.{self::A::_#A#covariantField}{core::num?} in #t3{core::num} : throw new _in::LateError::fieldNI("covariantField");
-  set covariantField(covariant-by-declaration core::num #t4) → void {
+    return this.{self::A::_#A#covariantField#isSet}{core::bool} ?{core::num} let final core::num? #t2 = this.{self::A::_#A#covariantField}{core::num?} in #t2{core::num} : throw new _in::LateError::fieldNI("covariantField");
+  set covariantField(covariant-by-declaration core::num covariantField#param) → void {
     this.{self::A::_#A#covariantField#isSet} = true;
-    this.{self::A::_#A#covariantField} = #t4;
+    this.{self::A::_#A#covariantField} = covariantField#param;
   }
 }
 abstract class B extends core::Object implements self::A {
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.modular.expect
index c2ac0b9..ee43c6f 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.modular.expect
@@ -24,15 +24,15 @@
     ;
   get invariantField() → core::num
     return this.{self::A::_#A#invariantField#isSet}{core::bool} ?{core::num} let final core::num? #t1 = this.{self::A::_#A#invariantField}{core::num?} in #t1{core::num} : throw new _in::LateError::fieldNI("invariantField");
-  set invariantField(core::num #t2) → void {
+  set invariantField(core::num invariantField#param) → void {
     this.{self::A::_#A#invariantField#isSet} = true;
-    this.{self::A::_#A#invariantField} = #t2;
+    this.{self::A::_#A#invariantField} = invariantField#param;
   }
   get covariantField() → core::num
-    return this.{self::A::_#A#covariantField#isSet}{core::bool} ?{core::num} let final core::num? #t3 = this.{self::A::_#A#covariantField}{core::num?} in #t3{core::num} : throw new _in::LateError::fieldNI("covariantField");
-  set covariantField(covariant-by-declaration core::num #t4) → void {
+    return this.{self::A::_#A#covariantField#isSet}{core::bool} ?{core::num} let final core::num? #t2 = this.{self::A::_#A#covariantField}{core::num?} in #t2{core::num} : throw new _in::LateError::fieldNI("covariantField");
+  set covariantField(covariant-by-declaration core::num covariantField#param) → void {
     this.{self::A::_#A#covariantField#isSet} = true;
-    this.{self::A::_#A#covariantField} = #t4;
+    this.{self::A::_#A#covariantField} = covariantField#param;
   }
 }
 abstract class B extends core::Object implements self::A {
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.outline.expect
index 9bc19d0..ef67ccc 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.outline.expect
@@ -21,9 +21,9 @@
   synthetic constructor •() → self::A
     ;
   get invariantField() → core::num;
-  set invariantField(core::num #t1) → void;
+  set invariantField(core::num invariantField#param) → void;
   get covariantField() → core::num;
-  set covariantField(covariant-by-declaration core::num #t2) → void;
+  set covariantField(covariant-by-declaration core::num covariantField#param) → void;
 }
 abstract class B extends core::Object implements self::A {
   synthetic constructor •() → self::B
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
index cc9b378..6d8023d 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
@@ -69,27 +69,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t1;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t2 = #local4 in #t2 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
+    return let final core::int? #t1 = #local4 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t1{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t3;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
+    return let final FutureOr<core::int>? #t2 = #local6 in #t2 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t2{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t5;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   #local2#set(value){(T%) → dynamic};
@@ -110,27 +110,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t6) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t6;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t7 = #local4 in #t7 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t7{core::int};
-  function #local4#set(core::int #t8) → dynamic
+    return let final core::int? #t3 = #local4 in #t3 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t3{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t8;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t10) → dynamic
+    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t10;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   if(b) {
@@ -154,10 +154,10 @@
 static field () → Null fieldCompound = () → Null {
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t11 = #local4 in #t11 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t11{core::int};
-  function #local4#set(core::int #t12) → dynamic
+    return let final core::int? #t5 = #local4 in #t5 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t5{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t12;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   #local4#set(0){(core::int) → dynamic};
@@ -170,27 +170,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t13) → dynamic
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t13;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t14 = #local4 in #t14 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t14{core::int};
-  function #local4#set(core::int #t15) → dynamic
+    return let final core::int? #t6 = #local4 in #t6 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t6{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t15;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t16 = #local6 in #t16 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t16{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t17) → dynamic
+    return let final FutureOr<core::int>? #t7 = #local6 in #t7 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t7{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t17;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   #local2#set(value){(self::methodDirect::T%) → dynamic};
@@ -211,27 +211,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t18) → dynamic
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t18;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t19 = #local4 in #t19 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t19{core::int};
-  function #local4#set(core::int #t20) → dynamic
+    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t20;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t21 = #local6 in #t21 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t21{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t22) → dynamic
+    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t22;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   if(b) {
@@ -255,10 +255,10 @@
 static method methodCompound() → dynamic {
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t23 = #local4 in #t23 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t23{core::int};
-  function #local4#set(core::int #t24) → dynamic
+    return let final core::int? #t10 = #local4 in #t10 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t10{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t24;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   #local4#set(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
index cc9b378..6d8023d 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
@@ -69,27 +69,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t1;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t2 = #local4 in #t2 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
+    return let final core::int? #t1 = #local4 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t1{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t3;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
+    return let final FutureOr<core::int>? #t2 = #local6 in #t2 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t2{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t5;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   #local2#set(value){(T%) → dynamic};
@@ -110,27 +110,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t6) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t6;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t7 = #local4 in #t7 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t7{core::int};
-  function #local4#set(core::int #t8) → dynamic
+    return let final core::int? #t3 = #local4 in #t3 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t3{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t8;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t10) → dynamic
+    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t10;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   if(b) {
@@ -154,10 +154,10 @@
 static field () → Null fieldCompound = () → Null {
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t11 = #local4 in #t11 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t11{core::int};
-  function #local4#set(core::int #t12) → dynamic
+    return let final core::int? #t5 = #local4 in #t5 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t5{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t12;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   #local4#set(0){(core::int) → dynamic};
@@ -170,27 +170,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t13) → dynamic
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t13;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t14 = #local4 in #t14 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t14{core::int};
-  function #local4#set(core::int #t15) → dynamic
+    return let final core::int? #t6 = #local4 in #t6 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t6{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t15;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t16 = #local6 in #t16 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t16{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t17) → dynamic
+    return let final FutureOr<core::int>? #t7 = #local6 in #t7 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t7{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t17;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   #local2#set(value){(self::methodDirect::T%) → dynamic};
@@ -211,27 +211,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t18) → dynamic
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t18;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t19 = #local4 in #t19 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t19{core::int};
-  function #local4#set(core::int #t20) → dynamic
+    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t20;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   lowered final FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t21 = #local6 in #t21 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t21{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t22) → dynamic
+    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6 == null)
-      return #local6 = #t22;
+      return #local6 = local6#param;
     else
       throw new _in::LateError::localAI("local6");
   if(b) {
@@ -255,10 +255,10 @@
 static method methodCompound() → dynamic {
   lowered final core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t23 = #local4 in #t23 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t23{core::int};
-  function #local4#set(core::int #t24) → dynamic
+    return let final core::int? #t10 = #local4 in #t10 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t10{core::int};
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4 == null)
-      return #local4 = #t24;
+      return #local4 = local4#param;
     else
       throw new _in::LateError::localAI("local4");
   #local4#set(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
index 28154dd..c598a45 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
@@ -69,34 +69,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t1;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t2;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t3;
+      return #local6 = local6#param;
     }
   #local2#set(value){(T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -116,34 +116,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t4) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t4;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t5) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t5;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t6) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t6;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(T%) → dynamic};
@@ -168,12 +168,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t7) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t7;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable '#local4' definitely assigned.
@@ -185,34 +185,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t8) → dynamic
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t9;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t10) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t10;
+      return #local6 = local6#param;
     }
   #local2#set(value){(self::methodDirect::T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -232,34 +232,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t11) → dynamic
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t11;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t12) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t12;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t13) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t13;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(self::methodConditional::T%) → dynamic};
@@ -284,12 +284,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t14) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t14;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable '#local4' definitely assigned.
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.modular.expect
index 28154dd..c598a45 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.modular.expect
@@ -69,34 +69,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t1;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t2;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t3;
+      return #local6 = local6#param;
     }
   #local2#set(value){(T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -116,34 +116,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t4) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t4;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t5) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t5;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t6) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t6;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(T%) → dynamic};
@@ -168,12 +168,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t7) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t7;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable '#local4' definitely assigned.
@@ -185,34 +185,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t8) → dynamic
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t9;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t10) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t10;
+      return #local6 = local6#param;
     }
   #local2#set(value){(self::methodDirect::T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -232,34 +232,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t11) → dynamic
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t11;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t12) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t12;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t13) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t13;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(self::methodConditional::T%) → dynamic};
@@ -284,12 +284,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t14) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t14;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable '#local4' definitely assigned.
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
index 28154dd..c598a45 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
@@ -69,34 +69,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t1;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t2;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t3;
+      return #local6 = local6#param;
     }
   #local2#set(value){(T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -116,34 +116,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t4) → dynamic
+  function #local2#set(T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t4;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t5) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t5;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t6) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t6;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(T%) → dynamic};
@@ -168,12 +168,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t7) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t7;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable '#local4' definitely assigned.
@@ -185,34 +185,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t8) → dynamic
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t9;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t10) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t10;
+      return #local6 = local6#param;
     }
   #local2#set(value){(self::methodDirect::T%) → dynamic};
   #local4#set(0){(core::int) → dynamic};
@@ -232,34 +232,34 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t11) → dynamic
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic
     if(#local2#isSet)
       throw new _in::LateError::localAI("local2");
     else {
       #local2#isSet = true;
-      return #local2 = #t11;
+      return #local2 = local2#param;
     }
   lowered final core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t12) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t12;
+      return #local4 = local4#param;
     }
   lowered final FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t13) → dynamic
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
     if(#local6#isSet)
       throw new _in::LateError::localAI("local6");
     else {
       #local6#isSet = true;
-      return #local6 = #t13;
+      return #local6 = local6#param;
     }
   if(b) {
     #local2#set(value){(self::methodConditional::T%) → dynamic};
@@ -284,12 +284,12 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t14) → dynamic
+  function #local4#set(core::int local4#param) → dynamic
     if(#local4#isSet)
       throw new _in::LateError::localAI("local4");
     else {
       #local4#isSet = true;
-      return #local4 = #t14;
+      return #local4 = local4#param;
     }
   #local4#set(0){(core::int) → dynamic};
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable '#local4' definitely assigned.
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
index b85ce55..5701988 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
@@ -102,22 +102,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t1;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t2 = #local4 in #t2 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    return #local4 = #t3;
+    return let final core::int? #t1 = #local4 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t1{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    return #local6 = #t5;
+    return let final FutureOr<core::int>? #t2 = #local6 in #t2 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t2{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -127,9 +127,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t6) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t6;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -157,22 +157,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t7) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t7;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
-  function #local4#set(core::int #t9) → dynamic
-    return #local4 = #t9;
+    return let final core::int? #t3 = #local4 in #t3 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t3{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t10 = #local6 in #t10 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t10{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t11) → dynamic
-    return #local6 = #t11;
+    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -182,9 +182,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t12) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t12;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -213,9 +213,9 @@
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t13 = #local4 in #t13 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t13{core::int};
-  function #local4#set(core::int #t14) → dynamic
-    return #local4 = #t14;
+    return let final core::int? #t5 = #local4 in #t5 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t5{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3.{core::num::+}(0){(core::num) → core::int};
@@ -229,22 +229,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t15) → dynamic {
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t15;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t16 = #local4 in #t16 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t16{core::int};
-  function #local4#set(core::int #t17) → dynamic
-    return #local4 = #t17;
+    return let final core::int? #t6 = #local4 in #t6 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t6{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t18 = #local6 in #t18 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t18{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t19) → dynamic
-    return #local6 = #t19;
+    return let final FutureOr<core::int>? #t7 = #local6 in #t7 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t7{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered self::methodDirect::T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → self::methodDirect::T% {
@@ -254,9 +254,9 @@
     }
     return #local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t20) → dynamic {
+  function #local7#set(self::methodDirect::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t20;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -284,22 +284,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t21) → dynamic {
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t21;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t22 = #local4 in #t22 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t22{core::int};
-  function #local4#set(core::int #t23) → dynamic
-    return #local4 = #t23;
+    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t24 = #local6 in #t24 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t24{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t25) → dynamic
-    return #local6 = #t25;
+    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered self::methodConditional::T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → self::methodConditional::T% {
@@ -309,9 +309,9 @@
     }
     return #local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t26) → dynamic {
+  function #local7#set(self::methodConditional::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t26;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -340,9 +340,9 @@
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t27 = #local4 in #t27 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t27{core::int};
-  function #local4#set(core::int #t28) → dynamic
-    return #local4 = #t28;
+    return let final core::int? #t10 = #local4 in #t10 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t10{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3.{core::num::+}(0){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
index b85ce55..5701988 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
@@ -102,22 +102,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t1;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t2 = #local4 in #t2 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    return #local4 = #t3;
+    return let final core::int? #t1 = #local4 in #t1 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t1{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    return #local6 = #t5;
+    return let final FutureOr<core::int>? #t2 = #local6 in #t2 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t2{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -127,9 +127,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t6) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t6;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -157,22 +157,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t7) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t7;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
-  function #local4#set(core::int #t9) → dynamic
-    return #local4 = #t9;
+    return let final core::int? #t3 = #local4 in #t3 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t3{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t10 = #local6 in #t10 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t10{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t11) → dynamic
-    return #local6 = #t11;
+    return let final FutureOr<core::int>? #t4 = #local6 in #t4 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t4{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -182,9 +182,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t12) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t12;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -213,9 +213,9 @@
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t13 = #local4 in #t13 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t13{core::int};
-  function #local4#set(core::int #t14) → dynamic
-    return #local4 = #t14;
+    return let final core::int? #t5 = #local4 in #t5 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t5{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3.{core::num::+}(0){(core::num) → core::int};
@@ -229,22 +229,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t15) → dynamic {
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t15;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t16 = #local4 in #t16 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t16{core::int};
-  function #local4#set(core::int #t17) → dynamic
-    return #local4 = #t17;
+    return let final core::int? #t6 = #local4 in #t6 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t6{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t18 = #local6 in #t18 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t18{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t19) → dynamic
-    return #local6 = #t19;
+    return let final FutureOr<core::int>? #t7 = #local6 in #t7 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t7{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered self::methodDirect::T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → self::methodDirect::T% {
@@ -254,9 +254,9 @@
     }
     return #local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t20) → dynamic {
+  function #local7#set(self::methodDirect::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t20;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -284,22 +284,22 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t21) → dynamic {
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t21;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t22 = #local4 in #t22 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t22{core::int};
-  function #local4#set(core::int #t23) → dynamic
-    return #local4 = #t23;
+    return let final core::int? #t8 = #local4 in #t8 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t8{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t24 = #local6 in #t24 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t24{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t25) → dynamic
-    return #local6 = #t25;
+    return let final FutureOr<core::int>? #t9 = #local6 in #t9 == null ?{FutureOr<core::int>} throw new _in::LateError::localNI("local6") : #t9{FutureOr<core::int>};
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic
+    return #local6 = local6#param;
   lowered self::methodConditional::T? #local7;
   lowered core::bool #local7#isSet = false;
   function #local7#get() → self::methodConditional::T% {
@@ -309,9 +309,9 @@
     }
     return #local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t26) → dynamic {
+  function #local7#set(self::methodConditional::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t26;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -340,9 +340,9 @@
   core::int local3;
   lowered core::int? #local4;
   function #local4#get() → core::int
-    return let final core::int? #t27 = #local4 in #t27 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t27{core::int};
-  function #local4#set(core::int #t28) → dynamic
-    return #local4 = #t28;
+    return let final core::int? #t10 = #local4 in #t10 == null ?{core::int} throw new _in::LateError::localNI("local4") : #t10{core::int};
+  function #local4#set(core::int local4#param) → dynamic
+    return #local4 = local4#param;
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3.{core::num::+}(0){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
index 5589982..405aa62 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
@@ -102,27 +102,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t1;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t2;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t3;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -133,9 +133,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t4) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t4;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -163,27 +163,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t5) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t5;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t6) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t6;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t7) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t7;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -194,9 +194,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t8) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t8;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -227,9 +227,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t9;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
@@ -244,27 +244,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t10) → dynamic {
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t10;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t11) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t11;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t12) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t12;
+    return #local6 = local6#param;
   }
   lowered self::methodDirect::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -275,9 +275,9 @@
     }
     return #local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t13) → dynamic {
+  function #local7#set(self::methodDirect::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t13;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -305,27 +305,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t14) → dynamic {
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t14;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t15) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t15;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t16) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t16;
+    return #local6 = local6#param;
   }
   lowered self::methodConditional::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -336,9 +336,9 @@
     }
     return #local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t17) → dynamic {
+  function #local7#set(self::methodConditional::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t17;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -369,9 +369,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t18) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t18;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.modular.expect
index 5589982..405aa62 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.modular.expect
@@ -102,27 +102,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t1;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t2;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t3;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -133,9 +133,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t4) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t4;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -163,27 +163,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t5) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t5;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t6) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t6;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t7) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t7;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -194,9 +194,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t8) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t8;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -227,9 +227,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t9;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
@@ -244,27 +244,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t10) → dynamic {
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t10;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t11) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t11;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t12) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t12;
+    return #local6 = local6#param;
   }
   lowered self::methodDirect::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -275,9 +275,9 @@
     }
     return #local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t13) → dynamic {
+  function #local7#set(self::methodDirect::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t13;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -305,27 +305,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t14) → dynamic {
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t14;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t15) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t15;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t16) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t16;
+    return #local6 = local6#param;
   }
   lowered self::methodConditional::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -336,9 +336,9 @@
     }
     return #local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t17) → dynamic {
+  function #local7#set(self::methodConditional::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t17;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -369,9 +369,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t18) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t18;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
index 5589982..405aa62 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
@@ -102,27 +102,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t1) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t1;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t2) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t2;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t3) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t3;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -133,9 +133,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t4) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t4;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -163,27 +163,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} #local2{T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(T% #t5) → dynamic {
+  function #local2#set(T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t5;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t6) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t6;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t7) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t7;
+    return #local6 = local6#param;
   }
   lowered T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -194,9 +194,9 @@
     }
     return #local7{T%};
   }
-  function #local7#set(T% #t8) → dynamic {
+  function #local7#set(T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t8;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -227,9 +227,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t9) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t9;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
@@ -244,27 +244,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} #local2{self::methodDirect::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodDirect::T% #t10) → dynamic {
+  function #local2#set(self::methodDirect::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t10;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t11) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t11;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t12) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t12;
+    return #local6 = local6#param;
   }
   lowered self::methodDirect::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -275,9 +275,9 @@
     }
     return #local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t13) → dynamic {
+  function #local7#set(self::methodDirect::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t13;
+    return #local7 = local7#param;
   }
   invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
@@ -305,27 +305,27 @@
   lowered core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} #local2{self::methodConditional::T%} : throw new _in::LateError::localNI("local2");
-  function #local2#set(self::methodConditional::T% #t14) → dynamic {
+  function #local2#set(self::methodConditional::T% local2#param) → dynamic {
     #local2#isSet = true;
-    return #local2 = #t14;
+    return #local2 = local2#param;
   }
   core::int local3;
   lowered core::int? #local4;
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t15) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t15;
+    return #local4 = local4#param;
   }
   FutureOr<core::int>local5;
   lowered FutureOr<core::int>? #local6;
   lowered core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
     return #local6#isSet ?{FutureOr<core::int>} #local6{FutureOr<core::int>} : throw new _in::LateError::localNI("local6");
-  function #local6#set(FutureOr<core::int>#t16) → dynamic {
+  function #local6#set(FutureOr<core::int>local6#param) → dynamic {
     #local6#isSet = true;
-    return #local6 = #t16;
+    return #local6 = local6#param;
   }
   lowered self::methodConditional::T? #local7;
   lowered core::bool #local7#isSet = false;
@@ -336,9 +336,9 @@
     }
     return #local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t17) → dynamic {
+  function #local7#set(self::methodConditional::T% local7#param) → dynamic {
     #local7#isSet = true;
-    return #local7 = #t17;
+    return #local7 = local7#param;
   }
   if(b) {
     local1 = value;
@@ -369,9 +369,9 @@
   lowered core::bool #local4#isSet = false;
   function #local4#get() → core::int
     return #local4#isSet ?{core::int} #local4{core::int} : throw new _in::LateError::localNI("local4");
-  function #local4#set(core::int #t18) → dynamic {
+  function #local4#set(core::int local4#param) → dynamic {
     #local4#isSet = true;
-    return #local4 = #t18;
+    return #local4 = local4#param;
   }
   local3 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
index 0231470..ca2862e 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
@@ -46,18 +46,18 @@
     ;
   get property4() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#property4}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t1{core::int};
-  set property4(core::int #t2) → void
-    this.{self::A::_#A#property4} = #t2;
+  set property4(core::int property4#param) → void
+    this.{self::A::_#A#property4} = property4#param;
   get property5() → core::int?
     return this.{self::A::_#A#property5#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#property5}{core::int?} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int? #t3) → void {
+  set property5(core::int? property5#param) → void {
     this.{self::A::_#A#property5#isSet} = true;
-    this.{self::A::_#A#property5} = #t3;
+    this.{self::A::_#A#property5} = property5#param;
   }
   get property6() → core::int
-    return let final core::int? #t4 = this.{self::A::_#A#property6}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t4{core::int};
-  set property6(covariant-by-declaration core::int #t5) → void
-    this.{self::A::_#A#property6} = #t5;
+    return let final core::int? #t2 = this.{self::A::_#A#property6}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t2{core::int};
+  set property6(covariant-by-declaration core::int property6#param) → void
+    this.{self::A::_#A#property6} = property6#param;
 }
 abstract class B1 extends core::Object {
   field core::int? _#B1#property4 = null;
@@ -68,27 +68,27 @@
     : self::B1::_#B1#property4 = property4, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return let final core::int? #t6 = this.{self::B1::_#B1#property4}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t6{core::int};
-  set property4(core::int #t7) → void
+    return let final core::int? #t3 = this.{self::B1::_#B1#property4}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t3{core::int};
+  set property4(core::int property4#param) → void
     if(this.{self::B1::_#B1#property4}{core::int?} == null)
-      this.{self::B1::_#B1#property4} = #t7;
+      this.{self::B1::_#B1#property4} = property4#param;
     else
       throw new _in::LateError::fieldAI("property4");
   get property5() → core::int
-    return let final core::int? #t8 = this.{self::B1::_#B1#property5}{core::int?} in #t8 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t8{core::int};
-  set property5(core::int #t9) → void
+    return let final core::int? #t4 = this.{self::B1::_#B1#property5}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t4{core::int};
+  set property5(core::int property5#param) → void
     if(this.{self::B1::_#B1#property5}{core::int?} == null)
-      this.{self::B1::_#B1#property5} = #t9;
+      this.{self::B1::_#B1#property5} = property5#param;
     else
       throw new _in::LateError::fieldAI("property5");
   get property6() → core::int?
     return this.{self::B1::_#B1#property6#isSet}{core::bool} ?{core::int?} this.{self::B1::_#B1#property6}{core::int?} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int? #t10) → void
+  set property6(core::int? property6#param) → void
     if(this.{self::B1::_#B1#property6#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property6");
     else {
       this.{self::B1::_#B1#property6#isSet} = true;
-      this.{self::B1::_#B1#property6} = #t10;
+      this.{self::B1::_#B1#property6} = property6#param;
     }
 }
 abstract class B2 extends core::Object implements self::B1 {
@@ -107,17 +107,17 @@
     : self::C1::_#C1#property4 = property4, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return let final core::int? #t11 = this.{self::C1::_#C1#property4}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t11{core::int};
-  set property4(core::int #t12) → void
-    this.{self::C1::_#C1#property4} = #t12;
+    return let final core::int? #t5 = this.{self::C1::_#C1#property4}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t5{core::int};
+  set property4(core::int property4#param) → void
+    this.{self::C1::_#C1#property4} = property4#param;
   get property5() → core::int
-    return let final core::int? #t13 = this.{self::C1::_#C1#property5}{core::int?} in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t13{core::int};
-  set property5(core::int #t14) → void
-    this.{self::C1::_#C1#property5} = #t14;
+    return let final core::int? #t6 = this.{self::C1::_#C1#property5}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t6{core::int};
+  set property5(core::int property5#param) → void
+    this.{self::C1::_#C1#property5} = property5#param;
   get property6() → core::int
-    return let final core::int? #t15 = this.{self::C1::_#C1#property6}{core::int?} in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t15{core::int};
-  set property6(core::int #t16) → void
-    this.{self::C1::_#C1#property6} = #t16;
+    return let final core::int? #t7 = this.{self::C1::_#C1#property6}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t7{core::int};
+  set property6(core::int property6#param) → void
+    this.{self::C1::_#C1#property6} = property6#param;
 }
 abstract class C2 extends core::Object implements self::C1 {
   synthetic constructor •() → self::C2
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
index 0231470..ca2862e 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
@@ -46,18 +46,18 @@
     ;
   get property4() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#property4}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t1{core::int};
-  set property4(core::int #t2) → void
-    this.{self::A::_#A#property4} = #t2;
+  set property4(core::int property4#param) → void
+    this.{self::A::_#A#property4} = property4#param;
   get property5() → core::int?
     return this.{self::A::_#A#property5#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#property5}{core::int?} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int? #t3) → void {
+  set property5(core::int? property5#param) → void {
     this.{self::A::_#A#property5#isSet} = true;
-    this.{self::A::_#A#property5} = #t3;
+    this.{self::A::_#A#property5} = property5#param;
   }
   get property6() → core::int
-    return let final core::int? #t4 = this.{self::A::_#A#property6}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t4{core::int};
-  set property6(covariant-by-declaration core::int #t5) → void
-    this.{self::A::_#A#property6} = #t5;
+    return let final core::int? #t2 = this.{self::A::_#A#property6}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t2{core::int};
+  set property6(covariant-by-declaration core::int property6#param) → void
+    this.{self::A::_#A#property6} = property6#param;
 }
 abstract class B1 extends core::Object {
   field core::int? _#B1#property4 = null;
@@ -68,27 +68,27 @@
     : self::B1::_#B1#property4 = property4, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return let final core::int? #t6 = this.{self::B1::_#B1#property4}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t6{core::int};
-  set property4(core::int #t7) → void
+    return let final core::int? #t3 = this.{self::B1::_#B1#property4}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t3{core::int};
+  set property4(core::int property4#param) → void
     if(this.{self::B1::_#B1#property4}{core::int?} == null)
-      this.{self::B1::_#B1#property4} = #t7;
+      this.{self::B1::_#B1#property4} = property4#param;
     else
       throw new _in::LateError::fieldAI("property4");
   get property5() → core::int
-    return let final core::int? #t8 = this.{self::B1::_#B1#property5}{core::int?} in #t8 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t8{core::int};
-  set property5(core::int #t9) → void
+    return let final core::int? #t4 = this.{self::B1::_#B1#property5}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t4{core::int};
+  set property5(core::int property5#param) → void
     if(this.{self::B1::_#B1#property5}{core::int?} == null)
-      this.{self::B1::_#B1#property5} = #t9;
+      this.{self::B1::_#B1#property5} = property5#param;
     else
       throw new _in::LateError::fieldAI("property5");
   get property6() → core::int?
     return this.{self::B1::_#B1#property6#isSet}{core::bool} ?{core::int?} this.{self::B1::_#B1#property6}{core::int?} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int? #t10) → void
+  set property6(core::int? property6#param) → void
     if(this.{self::B1::_#B1#property6#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property6");
     else {
       this.{self::B1::_#B1#property6#isSet} = true;
-      this.{self::B1::_#B1#property6} = #t10;
+      this.{self::B1::_#B1#property6} = property6#param;
     }
 }
 abstract class B2 extends core::Object implements self::B1 {
@@ -107,17 +107,17 @@
     : self::C1::_#C1#property4 = property4, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return let final core::int? #t11 = this.{self::C1::_#C1#property4}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t11{core::int};
-  set property4(core::int #t12) → void
-    this.{self::C1::_#C1#property4} = #t12;
+    return let final core::int? #t5 = this.{self::C1::_#C1#property4}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("property4") : #t5{core::int};
+  set property4(core::int property4#param) → void
+    this.{self::C1::_#C1#property4} = property4#param;
   get property5() → core::int
-    return let final core::int? #t13 = this.{self::C1::_#C1#property5}{core::int?} in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t13{core::int};
-  set property5(core::int #t14) → void
-    this.{self::C1::_#C1#property5} = #t14;
+    return let final core::int? #t6 = this.{self::C1::_#C1#property5}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("property5") : #t6{core::int};
+  set property5(core::int property5#param) → void
+    this.{self::C1::_#C1#property5} = property5#param;
   get property6() → core::int
-    return let final core::int? #t15 = this.{self::C1::_#C1#property6}{core::int?} in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t15{core::int};
-  set property6(core::int #t16) → void
-    this.{self::C1::_#C1#property6} = #t16;
+    return let final core::int? #t7 = this.{self::C1::_#C1#property6}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("property6") : #t7{core::int};
+  set property6(core::int property6#param) → void
+    this.{self::C1::_#C1#property6} = property6#param;
 }
 abstract class C2 extends core::Object implements self::C1 {
   synthetic constructor •() → self::C2
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
index 12210ba..2c82cd2 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
@@ -48,21 +48,21 @@
     ;
   get property4() → core::int
     return this.{self::A::_#A#property4#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#property4}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t2) → void {
+  set property4(core::int property4#param) → void {
     this.{self::A::_#A#property4#isSet} = true;
-    this.{self::A::_#A#property4} = #t2;
+    this.{self::A::_#A#property4} = property4#param;
   }
   get property5() → core::int?
     return this.{self::A::_#A#property5#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#property5}{core::int?} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int? #t3) → void {
+  set property5(core::int? property5#param) → void {
     this.{self::A::_#A#property5#isSet} = true;
-    this.{self::A::_#A#property5} = #t3;
+    this.{self::A::_#A#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::A::_#A#property6}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(covariant-by-declaration core::int #t5) → void {
+    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#property6}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(covariant-by-declaration core::int property6#param) → void {
     this.{self::A::_#A#property6#isSet} = true;
-    this.{self::A::_#A#property6} = #t5;
+    this.{self::A::_#A#property6} = property6#param;
   }
 }
 abstract class B1 extends core::Object {
@@ -76,31 +76,31 @@
     : self::B1::_#B1#property4#isSet = true, self::B1::_#B1#property4 = property4, self::B1::_#B1#property5#isSet = true, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::B1::_#B1#property4}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t7) → void
+    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::B1::_#B1#property4}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void
     if(this.{self::B1::_#B1#property4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property4");
     else {
       this.{self::B1::_#B1#property4#isSet} = true;
-      this.{self::B1::_#B1#property4} = #t7;
+      this.{self::B1::_#B1#property4} = property4#param;
     }
   get property5() → core::int
-    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t8 = this.{self::B1::_#B1#property5}{core::int?} in #t8{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t9) → void
+    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::B1::_#B1#property5}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void
     if(this.{self::B1::_#B1#property5#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property5");
     else {
       this.{self::B1::_#B1#property5#isSet} = true;
-      this.{self::B1::_#B1#property5} = #t9;
+      this.{self::B1::_#B1#property5} = property5#param;
     }
   get property6() → core::int?
     return this.{self::B1::_#B1#property6#isSet}{core::bool} ?{core::int?} this.{self::B1::_#B1#property6}{core::int?} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int? #t10) → void
+  set property6(core::int? property6#param) → void
     if(this.{self::B1::_#B1#property6#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property6");
     else {
       this.{self::B1::_#B1#property6#isSet} = true;
-      this.{self::B1::_#B1#property6} = #t10;
+      this.{self::B1::_#B1#property6} = property6#param;
     }
 }
 abstract class B2 extends core::Object implements self::B1 {
@@ -122,22 +122,22 @@
     : self::C1::_#C1#property4#isSet = true, self::C1::_#C1#property4 = property4, self::C1::_#C1#property5#isSet = true, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6#isSet = true, self::C1::_#C1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::C1::_#C1#property4}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t12) → void {
+    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C1::_#C1#property4}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void {
     this.{self::C1::_#C1#property4#isSet} = true;
-    this.{self::C1::_#C1#property4} = #t12;
+    this.{self::C1::_#C1#property4} = property4#param;
   }
   get property5() → core::int
-    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::C1::_#C1#property5}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t14) → void {
+    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::C1::_#C1#property5}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void {
     this.{self::C1::_#C1#property5#isSet} = true;
-    this.{self::C1::_#C1#property5} = #t14;
+    this.{self::C1::_#C1#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::C1::_#C1#property6}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int #t16) → void {
+    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::C1::_#C1#property6}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(core::int property6#param) → void {
     this.{self::C1::_#C1#property6#isSet} = true;
-    this.{self::C1::_#C1#property6} = #t16;
+    this.{self::C1::_#C1#property6} = property6#param;
   }
 }
 abstract class C2 extends core::Object implements self::C1 {
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.modular.expect
index 12210ba..2c82cd2 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.modular.expect
@@ -48,21 +48,21 @@
     ;
   get property4() → core::int
     return this.{self::A::_#A#property4#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#property4}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t2) → void {
+  set property4(core::int property4#param) → void {
     this.{self::A::_#A#property4#isSet} = true;
-    this.{self::A::_#A#property4} = #t2;
+    this.{self::A::_#A#property4} = property4#param;
   }
   get property5() → core::int?
     return this.{self::A::_#A#property5#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#property5}{core::int?} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int? #t3) → void {
+  set property5(core::int? property5#param) → void {
     this.{self::A::_#A#property5#isSet} = true;
-    this.{self::A::_#A#property5} = #t3;
+    this.{self::A::_#A#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::A::_#A#property6}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(covariant-by-declaration core::int #t5) → void {
+    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#property6}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(covariant-by-declaration core::int property6#param) → void {
     this.{self::A::_#A#property6#isSet} = true;
-    this.{self::A::_#A#property6} = #t5;
+    this.{self::A::_#A#property6} = property6#param;
   }
 }
 abstract class B1 extends core::Object {
@@ -76,31 +76,31 @@
     : self::B1::_#B1#property4#isSet = true, self::B1::_#B1#property4 = property4, self::B1::_#B1#property5#isSet = true, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::B1::_#B1#property4}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t7) → void
+    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::B1::_#B1#property4}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void
     if(this.{self::B1::_#B1#property4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property4");
     else {
       this.{self::B1::_#B1#property4#isSet} = true;
-      this.{self::B1::_#B1#property4} = #t7;
+      this.{self::B1::_#B1#property4} = property4#param;
     }
   get property5() → core::int
-    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t8 = this.{self::B1::_#B1#property5}{core::int?} in #t8{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t9) → void
+    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::B1::_#B1#property5}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void
     if(this.{self::B1::_#B1#property5#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property5");
     else {
       this.{self::B1::_#B1#property5#isSet} = true;
-      this.{self::B1::_#B1#property5} = #t9;
+      this.{self::B1::_#B1#property5} = property5#param;
     }
   get property6() → core::int?
     return this.{self::B1::_#B1#property6#isSet}{core::bool} ?{core::int?} this.{self::B1::_#B1#property6}{core::int?} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int? #t10) → void
+  set property6(core::int? property6#param) → void
     if(this.{self::B1::_#B1#property6#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property6");
     else {
       this.{self::B1::_#B1#property6#isSet} = true;
-      this.{self::B1::_#B1#property6} = #t10;
+      this.{self::B1::_#B1#property6} = property6#param;
     }
 }
 abstract class B2 extends core::Object implements self::B1 {
@@ -122,22 +122,22 @@
     : self::C1::_#C1#property4#isSet = true, self::C1::_#C1#property4 = property4, self::C1::_#C1#property5#isSet = true, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6#isSet = true, self::C1::_#C1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::C1::_#C1#property4}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t12) → void {
+    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C1::_#C1#property4}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void {
     this.{self::C1::_#C1#property4#isSet} = true;
-    this.{self::C1::_#C1#property4} = #t12;
+    this.{self::C1::_#C1#property4} = property4#param;
   }
   get property5() → core::int
-    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::C1::_#C1#property5}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t14) → void {
+    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::C1::_#C1#property5}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void {
     this.{self::C1::_#C1#property5#isSet} = true;
-    this.{self::C1::_#C1#property5} = #t14;
+    this.{self::C1::_#C1#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::C1::_#C1#property6}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int #t16) → void {
+    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::C1::_#C1#property6}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(core::int property6#param) → void {
     this.{self::C1::_#C1#property6#isSet} = true;
-    this.{self::C1::_#C1#property6} = #t16;
+    this.{self::C1::_#C1#property6} = property6#param;
   }
 }
 abstract class C2 extends core::Object implements self::C1 {
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.outline.expect
index 85eb6cb..3f51a7c2 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.outline.expect
@@ -45,11 +45,11 @@
   constructor •(core::int property4, core::int? property5, core::int property6) → self::A
     ;
   get property4() → core::int;
-  set property4(core::int #t1) → void;
+  set property4(core::int property4#param) → void;
   get property5() → core::int?;
-  set property5(core::int? #t2) → void;
+  set property5(core::int? property5#param) → void;
   get property6() → core::int;
-  set property6(covariant-by-declaration core::int #t3) → void;
+  set property6(covariant-by-declaration core::int property6#param) → void;
 }
 abstract class B1 extends core::Object {
   field core::int? _#B1#property4;
@@ -61,11 +61,11 @@
   constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
     ;
   get property4() → core::int;
-  set property4(core::int #t4) → void;
+  set property4(core::int property4#param) → void;
   get property5() → core::int;
-  set property5(core::int #t5) → void;
+  set property5(core::int property5#param) → void;
   get property6() → core::int?;
-  set property6(core::int? #t6) → void;
+  set property6(core::int? property6#param) → void;
 }
 abstract class B2 extends core::Object implements self::B1 {
   synthetic constructor •() → self::B2
@@ -84,11 +84,11 @@
   constructor •(core::int property4, core::int property5, core::int property6) → self::C1
     ;
   get property4() → core::int;
-  set property4(core::int #t7) → void;
+  set property4(core::int property4#param) → void;
   get property5() → core::int;
-  set property5(core::int #t8) → void;
+  set property5(core::int property5#param) → void;
   get property6() → core::int;
-  set property6(core::int #t9) → void;
+  set property6(core::int property6#param) → void;
 }
 abstract class C2 extends core::Object implements self::C1 {
   synthetic constructor •() → self::C2
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
index 12210ba..2c82cd2 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
@@ -48,21 +48,21 @@
     ;
   get property4() → core::int
     return this.{self::A::_#A#property4#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#property4}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t2) → void {
+  set property4(core::int property4#param) → void {
     this.{self::A::_#A#property4#isSet} = true;
-    this.{self::A::_#A#property4} = #t2;
+    this.{self::A::_#A#property4} = property4#param;
   }
   get property5() → core::int?
     return this.{self::A::_#A#property5#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#property5}{core::int?} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int? #t3) → void {
+  set property5(core::int? property5#param) → void {
     this.{self::A::_#A#property5#isSet} = true;
-    this.{self::A::_#A#property5} = #t3;
+    this.{self::A::_#A#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::A::_#A#property6}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(covariant-by-declaration core::int #t5) → void {
+    return this.{self::A::_#A#property6#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#property6}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(covariant-by-declaration core::int property6#param) → void {
     this.{self::A::_#A#property6#isSet} = true;
-    this.{self::A::_#A#property6} = #t5;
+    this.{self::A::_#A#property6} = property6#param;
   }
 }
 abstract class B1 extends core::Object {
@@ -76,31 +76,31 @@
     : self::B1::_#B1#property4#isSet = true, self::B1::_#B1#property4 = property4, self::B1::_#B1#property5#isSet = true, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::B1::_#B1#property4}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t7) → void
+    return this.{self::B1::_#B1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::B1::_#B1#property4}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void
     if(this.{self::B1::_#B1#property4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property4");
     else {
       this.{self::B1::_#B1#property4#isSet} = true;
-      this.{self::B1::_#B1#property4} = #t7;
+      this.{self::B1::_#B1#property4} = property4#param;
     }
   get property5() → core::int
-    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t8 = this.{self::B1::_#B1#property5}{core::int?} in #t8{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t9) → void
+    return this.{self::B1::_#B1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::B1::_#B1#property5}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void
     if(this.{self::B1::_#B1#property5#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property5");
     else {
       this.{self::B1::_#B1#property5#isSet} = true;
-      this.{self::B1::_#B1#property5} = #t9;
+      this.{self::B1::_#B1#property5} = property5#param;
     }
   get property6() → core::int?
     return this.{self::B1::_#B1#property6#isSet}{core::bool} ?{core::int?} this.{self::B1::_#B1#property6}{core::int?} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int? #t10) → void
+  set property6(core::int? property6#param) → void
     if(this.{self::B1::_#B1#property6#isSet}{core::bool})
       throw new _in::LateError::fieldAI("property6");
     else {
       this.{self::B1::_#B1#property6#isSet} = true;
-      this.{self::B1::_#B1#property6} = #t10;
+      this.{self::B1::_#B1#property6} = property6#param;
     }
 }
 abstract class B2 extends core::Object implements self::B1 {
@@ -122,22 +122,22 @@
     : self::C1::_#C1#property4#isSet = true, self::C1::_#C1#property4 = property4, self::C1::_#C1#property5#isSet = true, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6#isSet = true, self::C1::_#C1#property6 = property6, super core::Object::•()
     ;
   get property4() → core::int
-    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::C1::_#C1#property4}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("property4");
-  set property4(core::int #t12) → void {
+    return this.{self::C1::_#C1#property4#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C1::_#C1#property4}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("property4");
+  set property4(core::int property4#param) → void {
     this.{self::C1::_#C1#property4#isSet} = true;
-    this.{self::C1::_#C1#property4} = #t12;
+    this.{self::C1::_#C1#property4} = property4#param;
   }
   get property5() → core::int
-    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::C1::_#C1#property5}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("property5");
-  set property5(core::int #t14) → void {
+    return this.{self::C1::_#C1#property5#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::C1::_#C1#property5}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("property5");
+  set property5(core::int property5#param) → void {
     this.{self::C1::_#C1#property5#isSet} = true;
-    this.{self::C1::_#C1#property5} = #t14;
+    this.{self::C1::_#C1#property5} = property5#param;
   }
   get property6() → core::int
-    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::C1::_#C1#property6}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("property6");
-  set property6(core::int #t16) → void {
+    return this.{self::C1::_#C1#property6#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::C1::_#C1#property6}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("property6");
+  set property6(core::int property6#param) → void {
     this.{self::C1::_#C1#property6#isSet} = true;
-    this.{self::C1::_#C1#property6} = #t16;
+    this.{self::C1::_#C1#property6} = property6#param;
   }
 }
 abstract class C2 extends core::Object implements self::C1 {
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.expect
index 5f86747..f225d42 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.expect
@@ -9,7 +9,7 @@
   lowered core::int? #local;
   function #local#get() → core::int
     return let final core::int? #t1 = #local in #t1 == null ?{core::int} throw new _in::LateError::localNI("local") : #t1{core::int};
-  function #local#set(core::int #t2) → dynamic
-    return #local = #t2;
+  function #local#set(core::int local#param) → dynamic
+    return #local = local#param;
   #local#set(self::f<core::int>(0)){(core::int) → dynamic};
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.transformed.expect
index 5f86747..f225d42 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
   lowered core::int? #local;
   function #local#get() → core::int
     return let final core::int? #t1 = #local in #t1 == null ?{core::int} throw new _in::LateError::localNI("local") : #t1{core::int};
-  function #local#set(core::int #t2) → dynamic
-    return #local = #t2;
+  function #local#set(core::int local#param) → dynamic
+    return #local = local#param;
   #local#set(self::f<core::int>(0)){(core::int) → dynamic};
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
index 6d53db1..07d3c1b 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
@@ -10,9 +10,9 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t1) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t1;
+    return #local = local#param;
   }
   #local#set(self::f<core::int>(0)){(core::int) → dynamic};
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.modular.expect
index 6d53db1..07d3c1b 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.modular.expect
@@ -10,9 +10,9 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t1) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t1;
+    return #local = local#param;
   }
   #local#set(self::f<core::int>(0)){(core::int) → dynamic};
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
index 6d53db1..07d3c1b 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
@@ -10,9 +10,9 @@
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t1) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t1;
+    return #local = local#param;
   }
   #local#set(self::f<core::int>(0)){(core::int) → dynamic};
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect
index f6de289..8f158dd 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect
@@ -17,9 +17,9 @@
     ;
   get field() → core::int?
     return this.{self::B::_#B#field#isSet}{core::bool} ?{core::int?} this.{self::B::_#B#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::B::_#B#field#isSet} = true;
-    this.{self::B::_#B#field} = #t1;
+    this.{self::B::_#B#field} = field#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect
index f6de289..8f158dd 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect
@@ -17,9 +17,9 @@
     ;
   get field() → core::int?
     return this.{self::B::_#B#field#isSet}{core::bool} ?{core::int?} this.{self::B::_#B#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::B::_#B#field#isSet} = true;
-    this.{self::B::_#B#field} = #t1;
+    this.{self::B::_#B#field} = field#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect
index f6de289..8f158dd 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect
@@ -17,9 +17,9 @@
     ;
   get field() → core::int?
     return this.{self::B::_#B#field#isSet}{core::bool} ?{core::int?} this.{self::B::_#B#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::B::_#B#field#isSet} = true;
-    this.{self::B::_#B#field} = #t1;
+    this.{self::B::_#B#field} = field#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.modular.expect
index f6de289..8f158dd 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.modular.expect
@@ -17,9 +17,9 @@
     ;
   get field() → core::int?
     return this.{self::B::_#B#field#isSet}{core::bool} ?{core::int?} this.{self::B::_#B#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::B::_#B#field#isSet} = true;
-    this.{self::B::_#B#field} = #t1;
+    this.{self::B::_#B#field} = field#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.outline.expect
index c636c33..ba39148 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.outline.expect
@@ -13,7 +13,7 @@
   synthetic constructor •() → self::B
     ;
   get field() → core::int?;
-  set field(core::int? #t1) → void;
+  set field(core::int? field#param) → void;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect
index f6de289..8f158dd 100644
--- a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect
@@ -17,9 +17,9 @@
     ;
   get field() → core::int?
     return this.{self::B::_#B#field#isSet}{core::bool} ?{core::int?} this.{self::B::_#B#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::B::_#B#field#isSet} = true;
-    this.{self::B::_#B#field} = #t1;
+    this.{self::B::_#B#field} = field#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.expect
index abaed59..ca096ac 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.expect
@@ -23,8 +23,8 @@
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
     return let final core::int? #t1 = this.{self2::Class::_#Class#foo}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("foo") : #t1{core::int};
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void
-    this.{self2::Class::_#Class#foo} = #t2;
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void
+    this.{self2::Class::_#Class#foo} = foo#param;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.transformed.expect
index abaed59..ca096ac 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.strong.transformed.expect
@@ -23,8 +23,8 @@
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
     return let final core::int? #t1 = this.{self2::Class::_#Class#foo}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("foo") : #t1{core::int};
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void
-    this.{self2::Class::_#Class#foo} = #t2;
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void
+    this.{self2::Class::_#Class#foo} = foo#param;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
index 75e0cf4..a31a4de 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
@@ -24,9 +24,9 @@
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
     return this.{self2::Class::_#Class#foo#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self2::Class::_#Class#foo}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("foo");
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void {
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void {
     this.{self2::Class::_#Class#foo#isSet} = true;
-    this.{self2::Class::_#Class#foo} = #t2;
+    this.{self2::Class::_#Class#foo} = foo#param;
   }
 }
 
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.modular.expect
index 75e0cf4..a31a4de 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.modular.expect
@@ -24,9 +24,9 @@
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
     return this.{self2::Class::_#Class#foo#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self2::Class::_#Class#foo}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("foo");
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void {
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void {
     this.{self2::Class::_#Class#foo#isSet} = true;
-    this.{self2::Class::_#Class#foo} = #t2;
+    this.{self2::Class::_#Class#foo} = foo#param;
   }
 }
 
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.outline.expect
index c992638..9029f33 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.outline.expect
@@ -22,7 +22,7 @@
   constructor baz(core::int foo) → self2::Class
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int;
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t1) → void;
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void;
 }
 
 
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
index 75e0cf4..a31a4de 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
@@ -24,9 +24,9 @@
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
     return this.{self2::Class::_#Class#foo#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self2::Class::_#Class#foo}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("foo");
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void {
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int foo#param) → void {
     this.{self2::Class::_#Class#foo#isSet} = true;
-    this.{self2::Class::_#Class#foo} = #t2;
+    this.{self2::Class::_#Class#foo} = foo#param;
   }
 }
 
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
index df03fdf..5a5f135 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
@@ -18,8 +18,8 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} this.{self::Class::_#Class#field} = 10 : #t1{core::int};
-  set field(core::int #t2) → void
-    this.{self::Class::_#Class#field} = #t2;
+  set field(core::int field#param) → void
+    this.{self::Class::_#Class#field} = field#param;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
index df03fdf..5a5f135 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
@@ -18,8 +18,8 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} this.{self::Class::_#Class#field} = 10 : #t1{core::int};
-  set field(core::int #t2) → void
-    this.{self::Class::_#Class#field} = #t2;
+  set field(core::int field#param) → void
+    this.{self::Class::_#Class#field} = field#param;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
index ccb0618..1de629b 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
@@ -24,9 +24,9 @@
     }
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int};
   }
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.modular.expect
index ccb0618..1de629b 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.modular.expect
@@ -24,9 +24,9 @@
     }
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int};
   }
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.outline.expect
index 6ae21b7..9cab5c3 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int field = 42]) → self::Class
     ;
   get field() → core::int;
-  set field(core::int #t1) → void;
+  set field(core::int field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
index ccb0618..1de629b 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
@@ -24,9 +24,9 @@
     }
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int};
   }
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
index 8218ba0..1bdbe34 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
@@ -19,8 +19,8 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field") : #t1{core::int};
-  set field(core::int #t2) → void
-    this.{self::Class::_#Class#field} = #t2;
+  set field(core::int field#param) → void
+    this.{self::Class::_#Class#field} = field#param;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
index 8218ba0..1bdbe34 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
@@ -19,8 +19,8 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field") : #t1{core::int};
-  set field(core::int #t2) → void
-    this.{self::Class::_#Class#field} = #t2;
+  set field(core::int field#param) → void
+    this.{self::Class::_#Class#field} = field#param;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
index b2fdacb..29a974d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.modular.expect
index b2fdacb..29a974d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.modular.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.outline.expect
index b454862..7029e3d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int field = 42]) → self::Class
     ;
   get field() → core::int;
-  set field(core::int #t1) → void;
+  set field(core::int field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
index b2fdacb..29a974d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void {
+  set field(core::int field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t2;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
index 33596c4..a7a63df 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
@@ -19,9 +19,9 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field") : #t1{core::int};
-  set field(core::int #t2) → void
+  set field(core::int field#param) → void
     if(this.{self::Class::_#Class#field}{core::int?} == null)
-      this.{self::Class::_#Class#field} = #t2;
+      this.{self::Class::_#Class#field} = field#param;
     else
       throw new _in::LateError::fieldAI("field");
 }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
index 33596c4..a7a63df 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
@@ -19,9 +19,9 @@
     ;
   get field() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field") : #t1{core::int};
-  set field(core::int #t2) → void
+  set field(core::int field#param) → void
     if(this.{self::Class::_#Class#field}{core::int?} == null)
-      this.{self::Class::_#Class#field} = #t2;
+      this.{self::Class::_#Class#field} = field#param;
     else
       throw new _in::LateError::fieldAI("field");
 }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
index 463e342..466dc3f 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void
+  set field(core::int field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t2;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.modular.expect
index 463e342..466dc3f 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.modular.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void
+  set field(core::int field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t2;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.outline.expect
index b454862..7029e3d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int field = 42]) → self::Class
     ;
   get field() → core::int;
-  set field(core::int #t1) → void;
+  set field(core::int field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
index 463e342..466dc3f 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field");
-  set field(core::int #t2) → void
+  set field(core::int field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t2;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
index 5a147d7..018d49d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
@@ -24,9 +24,9 @@
     }
     return this.{self::Class::_#Class#field}{core::int?};
   }
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
index 5a147d7..018d49d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -24,9 +24,9 @@
     }
     return this.{self::Class::_#Class#field}{core::int?};
   }
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
index 5a147d7..018d49d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.expect
@@ -24,9 +24,9 @@
     }
     return this.{self::Class::_#Class#field}{core::int?};
   }
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.modular.expect
index 5a147d7..018d49d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.modular.expect
@@ -24,9 +24,9 @@
     }
     return this.{self::Class::_#Class#field}{core::int?};
   }
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.outline.expect
index dfec80d..f4bf6ec 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int? field = 42]) → self::Class
     ;
   get field() → core::int?;
-  set field(core::int? #t1) → void;
+  set field(core::int? field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
index 5a147d7..018d49d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -24,9 +24,9 @@
     }
     return this.{self::Class::_#Class#field}{core::int?};
   }
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
index 58f7272..5d23ef8 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
index 58f7272..5d23ef8 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
index 58f7272..5d23ef8 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.modular.expect
index 58f7272..5d23ef8 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.modular.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.outline.expect
index 4c71a87..543b136 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int? field = 42]) → self::Class
     ;
   get field() → core::int?;
-  set field(core::int? #t1) → void;
+  set field(core::int? field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
index 58f7272..5d23ef8 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -20,9 +20,9 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void {
+  set field(core::int? field#param) → void {
     this.{self::Class::_#Class#field#isSet} = true;
-    this.{self::Class::_#Class#field} = #t1;
+    this.{self::Class::_#Class#field} = field#param;
   }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
index 8bbbcaf..6f2de7c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void
+  set field(core::int? field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t1;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
index 8bbbcaf..6f2de7c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void
+  set field(core::int? field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t1;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
index 8bbbcaf..6f2de7c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void
+  set field(core::int? field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t1;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.modular.expect
index 8bbbcaf..6f2de7c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.modular.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void
+  set field(core::int? field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t1;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.outline.expect
index 4c71a87..543b136 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.outline.expect
@@ -14,7 +14,7 @@
   constructor constructor4([core::int? field = 42]) → self::Class
     ;
   get field() → core::int?;
-  set field(core::int? #t1) → void;
+  set field(core::int? field#param) → void;
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
index 8bbbcaf..6f2de7c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
@@ -20,12 +20,12 @@
     ;
   get field() → core::int?
     return this.{self::Class::_#Class#field#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#field}{core::int?} : throw new _in::LateError::fieldNI("field");
-  set field(core::int? #t1) → void
+  set field(core::int? field#param) → void
     if(this.{self::Class::_#Class#field#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field");
     else {
       this.{self::Class::_#Class#field#isSet} = true;
-      this.{self::Class::_#Class#field} = #t1;
+      this.{self::Class::_#Class#field} = field#param;
     }
 }
 class Subclass extends self::Class {
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect
index 5064c1b..24cfe6f 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.expect
@@ -13,10 +13,10 @@
     ;
   get p1() → core::num
     return let final core::num? #t1 = this.{self::C::_#C#p1}{core::num?} in #t1 == null ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi}{core::num} : #t1{core::num};
-  set p1(core::num #t2) → void
-    this.{self::C::_#C#p1} = #t2;
+  set p1(core::num p1#param) → void
+    this.{self::C::_#C#p1} = p1#param;
   get p2() → core::num
-    return let final core::num? #t3 = this.{self::C::_#C#p2}{core::num?} in #t3 == null ?{core::num} let final core::num #t4 = this.{self::C::pi}{core::num} in this.{self::C::_#C#p2}{core::num?} == null ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateError::fieldADI("p2") : #t3{core::num};
+    return let final core::num? #t2 = this.{self::C::_#C#p2}{core::num?} in #t2 == null ?{core::num} let final core::num #t3 = this.{self::C::pi}{core::num} in this.{self::C::_#C#p2}{core::num?} == null ?{core::num} this.{self::C::_#C#p2} = #t3 : throw new _in::LateError::fieldADI("p2") : #t2{core::num};
 }
 static method main() → dynamic {
   self::expect(3.14, new self::C::•().{self::C::p1}{core::num});
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect
index 5064c1b..24cfe6f 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.strong.transformed.expect
@@ -13,10 +13,10 @@
     ;
   get p1() → core::num
     return let final core::num? #t1 = this.{self::C::_#C#p1}{core::num?} in #t1 == null ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi}{core::num} : #t1{core::num};
-  set p1(core::num #t2) → void
-    this.{self::C::_#C#p1} = #t2;
+  set p1(core::num p1#param) → void
+    this.{self::C::_#C#p1} = p1#param;
   get p2() → core::num
-    return let final core::num? #t3 = this.{self::C::_#C#p2}{core::num?} in #t3 == null ?{core::num} let final core::num #t4 = this.{self::C::pi}{core::num} in this.{self::C::_#C#p2}{core::num?} == null ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateError::fieldADI("p2") : #t3{core::num};
+    return let final core::num? #t2 = this.{self::C::_#C#p2}{core::num?} in #t2 == null ?{core::num} let final core::num #t3 = this.{self::C::pi}{core::num} in this.{self::C::_#C#p2}{core::num?} == null ?{core::num} this.{self::C::_#C#p2} = #t3 : throw new _in::LateError::fieldADI("p2") : #t2{core::num};
 }
 static method main() → dynamic {
   self::expect(3.14, new self::C::•().{self::C::p1}{core::num});
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
index 32f6e7c..8502e1d 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
@@ -19,19 +19,19 @@
     }
     return let final core::num? #t1 = this.{self::C::_#C#p1}{core::num?} in #t1{core::num};
   }
-  set p1(core::num #t2) → void {
+  set p1(core::num p1#param) → void {
     this.{self::C::_#C#p1#isSet} = true;
-    this.{self::C::_#C#p1} = #t2;
+    this.{self::C::_#C#p1} = p1#param;
   }
   get p2() → core::num {
     if(!this.{self::C::_#C#p2#isSet}{core::bool}) {
-      final core::num #t3 = this.{self::C::pi}{core::num};
+      final core::num #t2 = this.{self::C::pi}{core::num};
       if(this.{self::C::_#C#p2#isSet}{core::bool})
         throw new _in::LateError::fieldADI("p2");
-      this.{self::C::_#C#p2} = #t3;
+      this.{self::C::_#C#p2} = #t2;
       this.{self::C::_#C#p2#isSet} = true;
     }
-    return let final core::num? #t4 = this.{self::C::_#C#p2}{core::num?} in #t4{core::num};
+    return let final core::num? #t3 = this.{self::C::_#C#p2}{core::num?} in #t3{core::num};
   }
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.modular.expect
index 32f6e7c..8502e1d 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.modular.expect
@@ -19,19 +19,19 @@
     }
     return let final core::num? #t1 = this.{self::C::_#C#p1}{core::num?} in #t1{core::num};
   }
-  set p1(core::num #t2) → void {
+  set p1(core::num p1#param) → void {
     this.{self::C::_#C#p1#isSet} = true;
-    this.{self::C::_#C#p1} = #t2;
+    this.{self::C::_#C#p1} = p1#param;
   }
   get p2() → core::num {
     if(!this.{self::C::_#C#p2#isSet}{core::bool}) {
-      final core::num #t3 = this.{self::C::pi}{core::num};
+      final core::num #t2 = this.{self::C::pi}{core::num};
       if(this.{self::C::_#C#p2#isSet}{core::bool})
         throw new _in::LateError::fieldADI("p2");
-      this.{self::C::_#C#p2} = #t3;
+      this.{self::C::_#C#p2} = #t2;
       this.{self::C::_#C#p2#isSet} = true;
     }
-    return let final core::num? #t4 = this.{self::C::_#C#p2}{core::num?} in #t4{core::num};
+    return let final core::num? #t3 = this.{self::C::_#C#p2}{core::num?} in #t3{core::num};
   }
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.outline.expect
index 215d735..81f199b 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.outline.expect
@@ -11,7 +11,7 @@
   synthetic constructor •() → self::C
     ;
   get p1() → core::num;
-  set p1(core::num #t1) → void;
+  set p1(core::num p1#param) → void;
   get p2() → core::num;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
index 32f6e7c..8502e1d 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
@@ -19,19 +19,19 @@
     }
     return let final core::num? #t1 = this.{self::C::_#C#p1}{core::num?} in #t1{core::num};
   }
-  set p1(core::num #t2) → void {
+  set p1(core::num p1#param) → void {
     this.{self::C::_#C#p1#isSet} = true;
-    this.{self::C::_#C#p1} = #t2;
+    this.{self::C::_#C#p1} = p1#param;
   }
   get p2() → core::num {
     if(!this.{self::C::_#C#p2#isSet}{core::bool}) {
-      final core::num #t3 = this.{self::C::pi}{core::num};
+      final core::num #t2 = this.{self::C::pi}{core::num};
       if(this.{self::C::_#C#p2#isSet}{core::bool})
         throw new _in::LateError::fieldADI("p2");
-      this.{self::C::_#C#p2} = #t3;
+      this.{self::C::_#C#p2} = #t2;
       this.{self::C::_#C#p2#isSet} = true;
     }
-    return let final core::num? #t4 = this.{self::C::_#C#p2}{core::num?} in #t4{core::num};
+    return let final core::num? #t3 = this.{self::C::_#C#p2}{core::num?} in #t3{core::num};
   }
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect
index 149d652..284bc957 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.expect
@@ -13,45 +13,45 @@
     ;
   static get s() → dynamic
     return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateError::fieldNI("s");
-  static set s(dynamic #t1) → void
+  static set s(dynamic s#param) → void
     if(self::C::_#s#isSet)
       throw new _in::LateError::fieldAI("s");
     else {
       self::C::_#s#isSet = true;
-      self::C::_#s = #t1;
+      self::C::_#s = s#param;
     }
   get v() → dynamic
     return this.{self::C::_#C#v#isSet}{core::bool} ?{dynamic} this.{self::C::_#C#v}{dynamic} : throw new _in::LateError::fieldNI("v");
-  set v(dynamic #t2) → void
+  set v(dynamic v#param) → void
     if(this.{self::C::_#C#v#isSet}{core::bool})
       throw new _in::LateError::fieldAI("v");
     else {
       this.{self::C::_#C#v#isSet} = true;
-      this.{self::C::_#C#v} = #t2;
+      this.{self::C::_#C#v} = v#param;
     }
 }
 static field dynamic _#g = null;
 static field core::bool _#g#isSet = false;
 static get g() → dynamic
   return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateError::fieldNI("g");
-static set g(dynamic #t3) → void
+static set g(dynamic g#param) → void
   if(self::_#g#isSet)
     throw new _in::LateError::fieldAI("g");
   else {
     self::_#g#isSet = true;
-    self::_#g = #t3;
+    self::_#g = g#param;
   }
 static method main() → dynamic {
   lowered final dynamic #l;
   lowered core::bool #l#isSet = false;
   function #l#get() → dynamic
     return #l#isSet ?{dynamic} #l : throw new _in::LateError::localNI("l");
-  function #l#set(dynamic #t4) → dynamic
+  function #l#set(dynamic l#param) → dynamic
     if(#l#isSet)
       throw new _in::LateError::localAI("l");
     else {
       #l#isSet = true;
-      return #l = #t4;
+      return #l = l#param;
     }
   self::g = "Lily";
   self::C::s = "was";
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect
index 149d652..284bc957 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.strong.transformed.expect
@@ -13,45 +13,45 @@
     ;
   static get s() → dynamic
     return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateError::fieldNI("s");
-  static set s(dynamic #t1) → void
+  static set s(dynamic s#param) → void
     if(self::C::_#s#isSet)
       throw new _in::LateError::fieldAI("s");
     else {
       self::C::_#s#isSet = true;
-      self::C::_#s = #t1;
+      self::C::_#s = s#param;
     }
   get v() → dynamic
     return this.{self::C::_#C#v#isSet}{core::bool} ?{dynamic} this.{self::C::_#C#v}{dynamic} : throw new _in::LateError::fieldNI("v");
-  set v(dynamic #t2) → void
+  set v(dynamic v#param) → void
     if(this.{self::C::_#C#v#isSet}{core::bool})
       throw new _in::LateError::fieldAI("v");
     else {
       this.{self::C::_#C#v#isSet} = true;
-      this.{self::C::_#C#v} = #t2;
+      this.{self::C::_#C#v} = v#param;
     }
 }
 static field dynamic _#g = null;
 static field core::bool _#g#isSet = false;
 static get g() → dynamic
   return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateError::fieldNI("g");
-static set g(dynamic #t3) → void
+static set g(dynamic g#param) → void
   if(self::_#g#isSet)
     throw new _in::LateError::fieldAI("g");
   else {
     self::_#g#isSet = true;
-    self::_#g = #t3;
+    self::_#g = g#param;
   }
 static method main() → dynamic {
   lowered final dynamic #l;
   lowered core::bool #l#isSet = false;
   function #l#get() → dynamic
     return #l#isSet ?{dynamic} #l : throw new _in::LateError::localNI("l");
-  function #l#set(dynamic #t4) → dynamic
+  function #l#set(dynamic l#param) → dynamic
     if(#l#isSet)
       throw new _in::LateError::localAI("l");
     else {
       #l#isSet = true;
-      return #l = #t4;
+      return #l = l#param;
     }
   self::g = "Lily";
   self::C::s = "was";
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect
index 149d652..284bc957 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.expect
@@ -13,45 +13,45 @@
     ;
   static get s() → dynamic
     return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateError::fieldNI("s");
-  static set s(dynamic #t1) → void
+  static set s(dynamic s#param) → void
     if(self::C::_#s#isSet)
       throw new _in::LateError::fieldAI("s");
     else {
       self::C::_#s#isSet = true;
-      self::C::_#s = #t1;
+      self::C::_#s = s#param;
     }
   get v() → dynamic
     return this.{self::C::_#C#v#isSet}{core::bool} ?{dynamic} this.{self::C::_#C#v}{dynamic} : throw new _in::LateError::fieldNI("v");
-  set v(dynamic #t2) → void
+  set v(dynamic v#param) → void
     if(this.{self::C::_#C#v#isSet}{core::bool})
       throw new _in::LateError::fieldAI("v");
     else {
       this.{self::C::_#C#v#isSet} = true;
-      this.{self::C::_#C#v} = #t2;
+      this.{self::C::_#C#v} = v#param;
     }
 }
 static field dynamic _#g = null;
 static field core::bool _#g#isSet = false;
 static get g() → dynamic
   return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateError::fieldNI("g");
-static set g(dynamic #t3) → void
+static set g(dynamic g#param) → void
   if(self::_#g#isSet)
     throw new _in::LateError::fieldAI("g");
   else {
     self::_#g#isSet = true;
-    self::_#g = #t3;
+    self::_#g = g#param;
   }
 static method main() → dynamic {
   lowered final dynamic #l;
   lowered core::bool #l#isSet = false;
   function #l#get() → dynamic
     return #l#isSet ?{dynamic} #l : throw new _in::LateError::localNI("l");
-  function #l#set(dynamic #t4) → dynamic
+  function #l#set(dynamic l#param) → dynamic
     if(#l#isSet)
       throw new _in::LateError::localAI("l");
     else {
       #l#isSet = true;
-      return #l = #t4;
+      return #l = l#param;
     }
   self::g = "Lily";
   self::C::s = "was";
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.modular.expect
index 149d652..284bc957 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.modular.expect
@@ -13,45 +13,45 @@
     ;
   static get s() → dynamic
     return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateError::fieldNI("s");
-  static set s(dynamic #t1) → void
+  static set s(dynamic s#param) → void
     if(self::C::_#s#isSet)
       throw new _in::LateError::fieldAI("s");
     else {
       self::C::_#s#isSet = true;
-      self::C::_#s = #t1;
+      self::C::_#s = s#param;
     }
   get v() → dynamic
     return this.{self::C::_#C#v#isSet}{core::bool} ?{dynamic} this.{self::C::_#C#v}{dynamic} : throw new _in::LateError::fieldNI("v");
-  set v(dynamic #t2) → void
+  set v(dynamic v#param) → void
     if(this.{self::C::_#C#v#isSet}{core::bool})
       throw new _in::LateError::fieldAI("v");
     else {
       this.{self::C::_#C#v#isSet} = true;
-      this.{self::C::_#C#v} = #t2;
+      this.{self::C::_#C#v} = v#param;
     }
 }
 static field dynamic _#g = null;
 static field core::bool _#g#isSet = false;
 static get g() → dynamic
   return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateError::fieldNI("g");
-static set g(dynamic #t3) → void
+static set g(dynamic g#param) → void
   if(self::_#g#isSet)
     throw new _in::LateError::fieldAI("g");
   else {
     self::_#g#isSet = true;
-    self::_#g = #t3;
+    self::_#g = g#param;
   }
 static method main() → dynamic {
   lowered final dynamic #l;
   lowered core::bool #l#isSet = false;
   function #l#get() → dynamic
     return #l#isSet ?{dynamic} #l : throw new _in::LateError::localNI("l");
-  function #l#set(dynamic #t4) → dynamic
+  function #l#set(dynamic l#param) → dynamic
     if(#l#isSet)
       throw new _in::LateError::localAI("l");
     else {
       #l#isSet = true;
-      return #l = #t4;
+      return #l = l#param;
     }
   self::g = "Lily";
   self::C::s = "was";
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.outline.expect
index fc0f631..4ad01ae 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.outline.expect
@@ -10,14 +10,14 @@
   synthetic constructor •() → self::C
     ;
   static get s() → dynamic;
-  static set s(dynamic #t1) → void;
+  static set s(dynamic s#param) → void;
   get v() → dynamic;
-  set v(dynamic #t2) → void;
+  set v(dynamic v#param) → void;
 }
 static field dynamic _#g;
 static field core::bool _#g#isSet;
 static get g() → dynamic;
-static set g(dynamic #t3) → void;
+static set g(dynamic g#param) → void;
 static method main() → dynamic
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect
index 149d652..284bc957 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373b.dart.weak.transformed.expect
@@ -13,45 +13,45 @@
     ;
   static get s() → dynamic
     return self::C::_#s#isSet ?{dynamic} self::C::_#s : throw new _in::LateError::fieldNI("s");
-  static set s(dynamic #t1) → void
+  static set s(dynamic s#param) → void
     if(self::C::_#s#isSet)
       throw new _in::LateError::fieldAI("s");
     else {
       self::C::_#s#isSet = true;
-      self::C::_#s = #t1;
+      self::C::_#s = s#param;
     }
   get v() → dynamic
     return this.{self::C::_#C#v#isSet}{core::bool} ?{dynamic} this.{self::C::_#C#v}{dynamic} : throw new _in::LateError::fieldNI("v");
-  set v(dynamic #t2) → void
+  set v(dynamic v#param) → void
     if(this.{self::C::_#C#v#isSet}{core::bool})
       throw new _in::LateError::fieldAI("v");
     else {
       this.{self::C::_#C#v#isSet} = true;
-      this.{self::C::_#C#v} = #t2;
+      this.{self::C::_#C#v} = v#param;
     }
 }
 static field dynamic _#g = null;
 static field core::bool _#g#isSet = false;
 static get g() → dynamic
   return self::_#g#isSet ?{dynamic} self::_#g : throw new _in::LateError::fieldNI("g");
-static set g(dynamic #t3) → void
+static set g(dynamic g#param) → void
   if(self::_#g#isSet)
     throw new _in::LateError::fieldAI("g");
   else {
     self::_#g#isSet = true;
-    self::_#g = #t3;
+    self::_#g = g#param;
   }
 static method main() → dynamic {
   lowered final dynamic #l;
   lowered core::bool #l#isSet = false;
   function #l#get() → dynamic
     return #l#isSet ?{dynamic} #l : throw new _in::LateError::localNI("l");
-  function #l#set(dynamic #t4) → dynamic
+  function #l#set(dynamic l#param) → dynamic
     if(#l#isSet)
       throw new _in::LateError::localAI("l");
     else {
       #l#isSet = true;
-      return #l = #t4;
+      return #l = l#param;
     }
   self::g = "Lily";
   self::C::s = "was";
diff --git a/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.expect
index e8923f9..4aa89eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.expect
@@ -14,9 +14,9 @@
     lowered core::bool #value#isSet = false;
     function #value#get() → self::A::T%
       return #value#isSet ?{self::A::T%} #value{self::A::T%} : throw new _in::LateError::localNI("value");
-    function #value#set(self::A::T% #t1) → dynamic {
+    function #value#set(self::A::T% value#param) → dynamic {
       #value#isSet = true;
-      return #value = #t1;
+      return #value = value#param;
     }
     () → dynamic result = () → dynamic => this.{self::A::bar}(#value#get(){() → self::A::T%}){(self::A::T%) → dynamic};
     (() → Null {
diff --git a/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.transformed.expect
index e8923f9..4aa89eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40601.dart.strong.transformed.expect
@@ -14,9 +14,9 @@
     lowered core::bool #value#isSet = false;
     function #value#get() → self::A::T%
       return #value#isSet ?{self::A::T%} #value{self::A::T%} : throw new _in::LateError::localNI("value");
-    function #value#set(self::A::T% #t1) → dynamic {
+    function #value#set(self::A::T% value#param) → dynamic {
       #value#isSet = true;
-      return #value = #t1;
+      return #value = value#param;
     }
     () → dynamic result = () → dynamic => this.{self::A::bar}(#value#get(){() → self::A::T%}){(self::A::T%) → dynamic};
     (() → Null {
diff --git a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.expect
index e8923f9..4aa89eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.expect
@@ -14,9 +14,9 @@
     lowered core::bool #value#isSet = false;
     function #value#get() → self::A::T%
       return #value#isSet ?{self::A::T%} #value{self::A::T%} : throw new _in::LateError::localNI("value");
-    function #value#set(self::A::T% #t1) → dynamic {
+    function #value#set(self::A::T% value#param) → dynamic {
       #value#isSet = true;
-      return #value = #t1;
+      return #value = value#param;
     }
     () → dynamic result = () → dynamic => this.{self::A::bar}(#value#get(){() → self::A::T%}){(self::A::T%) → dynamic};
     (() → Null {
diff --git a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.modular.expect
index e8923f9..4aa89eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.modular.expect
@@ -14,9 +14,9 @@
     lowered core::bool #value#isSet = false;
     function #value#get() → self::A::T%
       return #value#isSet ?{self::A::T%} #value{self::A::T%} : throw new _in::LateError::localNI("value");
-    function #value#set(self::A::T% #t1) → dynamic {
+    function #value#set(self::A::T% value#param) → dynamic {
       #value#isSet = true;
-      return #value = #t1;
+      return #value = value#param;
     }
     () → dynamic result = () → dynamic => this.{self::A::bar}(#value#get(){() → self::A::T%}){(self::A::T%) → dynamic};
     (() → Null {
diff --git a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.transformed.expect
index e8923f9..4aa89eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40601.dart.weak.transformed.expect
@@ -14,9 +14,9 @@
     lowered core::bool #value#isSet = false;
     function #value#get() → self::A::T%
       return #value#isSet ?{self::A::T%} #value{self::A::T%} : throw new _in::LateError::localNI("value");
-    function #value#set(self::A::T% #t1) → dynamic {
+    function #value#set(self::A::T% value#param) → dynamic {
       #value#isSet = true;
-      return #value = #t1;
+      return #value = value#param;
     }
     () → dynamic result = () → dynamic => this.{self::A::bar}(#value#get(){() → self::A::T%}){(self::A::T%) → dynamic};
     (() → Null {
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect
index ccb488e..3704da3 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect
@@ -10,9 +10,9 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::C::_#C#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(covariant-by-declaration core::int #t2) → void
+  set x(covariant-by-declaration core::int x#param) → void
     if(this.{self::C::_#C#x}{core::int?} == null)
-      this.{self::C::_#C#x} = #t2;
+      this.{self::C::_#C#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
 }
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect
index ccb488e..3704da3 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect
@@ -10,9 +10,9 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::C::_#C#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(covariant-by-declaration core::int #t2) → void
+  set x(covariant-by-declaration core::int x#param) → void
     if(this.{self::C::_#C#x}{core::int?} == null)
-      this.{self::C::_#C#x} = #t2;
+      this.{self::C::_#C#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
 }
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
index a37d11f..5bc7ad7 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
@@ -11,12 +11,12 @@
     ;
   get x() → core::int
     return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::C::_#C#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-declaration core::int #t2) → void
+  set x(covariant-by-declaration core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t2;
+      this.{self::C::_#C#x} = x#param;
     }
 }
 class D extends self::C {
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.modular.expect
index a37d11f..5bc7ad7 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.modular.expect
@@ -11,12 +11,12 @@
     ;
   get x() → core::int
     return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::C::_#C#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-declaration core::int #t2) → void
+  set x(covariant-by-declaration core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t2;
+      this.{self::C::_#C#x} = x#param;
     }
 }
 class D extends self::C {
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.outline.expect
index b50e707..e16466c 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.outline.expect
@@ -8,7 +8,7 @@
   synthetic constructor •() → self::C
     ;
   get x() → core::int;
-  set x(covariant-by-declaration core::int #t1) → void;
+  set x(covariant-by-declaration core::int x#param) → void;
 }
 class D extends self::C {
   synthetic constructor •() → self::D
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
index a37d11f..5bc7ad7 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
@@ -11,12 +11,12 @@
     ;
   get x() → core::int
     return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::C::_#C#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-declaration core::int #t2) → void
+  set x(covariant-by-declaration core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t2;
+      this.{self::C::_#C#x} = x#param;
     }
 }
 class D extends self::C {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect
index ef8f0a6..a00dee1 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.expect
@@ -20,8 +20,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{test::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{test::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{test::A::_#A#x} = x#param;
 }
 class _B extends core::Object implements test::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect
index ef8f0a6..a00dee1 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.strong.transformed.expect
@@ -20,8 +20,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{test::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{test::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{test::A::_#A#x} = x#param;
 }
 class _B extends core::Object implements test::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
index c3f8ab3..8fe41f3 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
@@ -21,9 +21,9 @@
     ;
   get x() → core::int
     return this.{test::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{test::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{test::A::_#A#x#isSet} = true;
-    this.{test::A::_#A#x} = #t2;
+    this.{test::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements test::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.modular.expect
index c3f8ab3..8fe41f3 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.modular.expect
@@ -21,9 +21,9 @@
     ;
   get x() → core::int
     return this.{test::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{test::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{test::A::_#A#x#isSet} = true;
-    this.{test::A::_#A#x} = #t2;
+    this.{test::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements test::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.outline.expect
index 9fe236dd..88d9351 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.outline.expect
@@ -16,7 +16,7 @@
   synthetic constructor •() → self2::A
     ;
   get x() → core::int;
-  set x(core::int #t1) → void;
+  set x(core::int x#param) → void;
 }
 class _B extends core::Object implements self2::A {
   field core::int x;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
index c3f8ab3..8fe41f3 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
@@ -21,9 +21,9 @@
     ;
   get x() → core::int
     return this.{test::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{test::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{test::A::_#A#x#isSet} = true;
-    this.{test::A::_#A#x} = #t2;
+    this.{test::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements test::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect
index e8817ef..6fc0c73 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.expect
@@ -10,8 +10,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{self::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{self::A::_#A#x} = x#param;
 }
 class _B extends core::Object implements self::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect
index e8817ef..6fc0c73 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{self::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{self::A::_#A#x} = x#param;
 }
 class _B extends core::Object implements self::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
index 0c45d0a..f5f3c3c 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
@@ -11,9 +11,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements self::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.modular.expect
index 0c45d0a..f5f3c3c 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.modular.expect
@@ -11,9 +11,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements self::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.outline.expect
index 976a20f..80d31eb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.outline.expect
@@ -8,7 +8,7 @@
   synthetic constructor •() → self::A
     ;
   get x() → core::int;
-  set x(core::int #t1) → void;
+  set x(core::int x#param) → void;
 }
 class _B extends core::Object implements self::A {
   field core::int x;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
index 0c45d0a..f5f3c3c 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
@@ -11,9 +11,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class _B extends core::Object implements self::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.expect
index de82c1f..37756b5 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.expect
@@ -30,8 +30,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{iss::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{iss::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{iss::A::_#A#x} = x#param;
 }
 class B extends core::Object implements iss::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
index 3487b8a..07d36fd 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
@@ -30,8 +30,8 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{iss::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{iss::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{iss::A::_#A#x} = x#param;
 }
 class B extends core::Object implements iss::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
index 105770f..8fe6ee7 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
@@ -35,9 +35,9 @@
     ;
   get x() → core::int
     return this.{iss::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{iss::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{iss::A::_#A#x#isSet} = true;
-    this.{iss::A::_#A#x} = #t2;
+    this.{iss::A::_#A#x} = x#param;
   }
 }
 class B extends core::Object implements iss::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.outline.expect
index d7ce4ef..ae337d4 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.outline.expect
@@ -30,7 +30,7 @@
   synthetic constructor •() → iss::A
     ;
   get x() → core::int;
-  set x(core::int #t1) → void;
+  set x(core::int x#param) → void;
 }
 class B extends core::Object implements iss::A {
   field core::int x;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
index d06c920..fdea894 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
@@ -35,9 +35,9 @@
     ;
   get x() → core::int
     return this.{iss::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{iss::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{iss::A::_#A#x#isSet} = true;
-    this.{iss::A::_#A#x} = #t2;
+    this.{iss::A::_#A#x} = x#param;
   }
 }
 class B extends core::Object implements iss::A {
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.expect
index f4abe91..bc63dfb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.expect
@@ -15,9 +15,9 @@
     }
     return self::C::_#s;
   }
-  static set s(core::String? #t1) → void {
+  static set s(core::String? s#param) → void {
     self::C::_#s#isSet = true;
-    self::C::_#s = #t1;
+    self::C::_#s = s#param;
   }
 }
 static field core::bool _called = false;
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.transformed.expect
index f4abe91..bc63dfb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.strong.transformed.expect
@@ -15,9 +15,9 @@
     }
     return self::C::_#s;
   }
-  static set s(core::String? #t1) → void {
+  static set s(core::String? s#param) → void {
     self::C::_#s#isSet = true;
-    self::C::_#s = #t1;
+    self::C::_#s = s#param;
   }
 }
 static field core::bool _called = false;
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.expect
index f4abe91..bc63dfb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.expect
@@ -15,9 +15,9 @@
     }
     return self::C::_#s;
   }
-  static set s(core::String? #t1) → void {
+  static set s(core::String? s#param) → void {
     self::C::_#s#isSet = true;
-    self::C::_#s = #t1;
+    self::C::_#s = s#param;
   }
 }
 static field core::bool _called = false;
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.modular.expect
index f4abe91..bc63dfb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.modular.expect
@@ -15,9 +15,9 @@
     }
     return self::C::_#s;
   }
-  static set s(core::String? #t1) → void {
+  static set s(core::String? s#param) → void {
     self::C::_#s#isSet = true;
-    self::C::_#s = #t1;
+    self::C::_#s = s#param;
   }
 }
 static field core::bool _called = false;
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.outline.expect
index 636ec1c..079f3b2 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.outline.expect
@@ -8,7 +8,7 @@
   synthetic constructor •() → self::C
     ;
   static get s() → core::String?;
-  static set s(core::String? #t1) → void;
+  static set s(core::String? s#param) → void;
 }
 static field core::bool _called;
 static method init(core::String val) → core::String
diff --git a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.transformed.expect
index f4abe91..bc63dfb 100644
--- a/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41922.dart.weak.transformed.expect
@@ -15,9 +15,9 @@
     }
     return self::C::_#s;
   }
-  static set s(core::String? #t1) → void {
+  static set s(core::String? s#param) → void {
     self::C::_#s#isSet = true;
-    self::C::_#s = #t1;
+    self::C::_#s = s#param;
   }
 }
 static field core::bool _called = false;
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect
index 16c8e79..336fcf6 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect
@@ -11,9 +11,9 @@
     ;
   get x() → self::A::T%
     return this.{self::A::_#A#x#isSet}{core::bool} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x}{self::A::T?} in #t1{self::A::T%} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-class self::A::T% #t2) → void {
+  set x(covariant-by-class self::A::T% x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect
index 16c8e79..336fcf6 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect
@@ -11,9 +11,9 @@
     ;
   get x() → self::A::T%
     return this.{self::A::_#A#x#isSet}{core::bool} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x}{self::A::T?} in #t1{self::A::T%} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-class self::A::T% #t2) → void {
+  set x(covariant-by-class self::A::T% x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect
index 16c8e79..336fcf6 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect
@@ -11,9 +11,9 @@
     ;
   get x() → self::A::T%
     return this.{self::A::_#A#x#isSet}{core::bool} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x}{self::A::T?} in #t1{self::A::T%} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-class self::A::T% #t2) → void {
+  set x(covariant-by-class self::A::T% x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.modular.expect
index 16c8e79..336fcf6 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.modular.expect
@@ -11,9 +11,9 @@
     ;
   get x() → self::A::T%
     return this.{self::A::_#A#x#isSet}{core::bool} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x}{self::A::T?} in #t1{self::A::T%} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-class self::A::T% #t2) → void {
+  set x(covariant-by-class self::A::T% x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.outline.expect
index e556e89..73875f5 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.outline.expect
@@ -8,7 +8,7 @@
   synthetic constructor •() → self::A<self::A::T%>
     ;
   get x() → self::A::T%;
-  set x(covariant-by-class self::A::T% #t1) → void;
+  set x(covariant-by-class self::A::T% x#param) → void;
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
   covariant-by-class field self::B::T? _y;
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect
index 16c8e79..336fcf6 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect
@@ -11,9 +11,9 @@
     ;
   get x() → self::A::T%
     return this.{self::A::_#A#x#isSet}{core::bool} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x}{self::A::T?} in #t1{self::A::T%} : throw new _in::LateError::fieldNI("x");
-  set x(covariant-by-class self::A::T% #t2) → void {
+  set x(covariant-by-class self::A::T% x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 class B<T extends core::Object? = dynamic> extends core::Object {
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
index 66a67c4..bc55772 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
@@ -7,11 +7,11 @@
   lowered () →? core::int #recursiveInitLocal;
   function #recursiveInitLocal#get() → () → core::int
     return let final () →? core::int #t1 = #recursiveInitLocal in #t1 == null ?{() → core::int} throw new _in::LateError::localNI("recursiveInitLocal") : #t1{() → core::int};
-  function #recursiveInitLocal#set(() → core::int #t2) → dynamic
-    return #recursiveInitLocal = #t2;
+  function #recursiveInitLocal#set(() → core::int recursiveInitLocal#param) → dynamic
+    return #recursiveInitLocal = recursiveInitLocal#param;
   lowered final core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t3 = #local in #t3 == null ?{core::int} let final core::int #t4 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int} in #local == null ?{core::int} #local = #t4 : throw new _in::LateError::localADI("local") : #t3{core::int};
+    return let final core::int? #t2 = #local in #t2 == null ?{core::int} let final core::int #t3 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int} in #local == null ?{core::int} #local = #t3 : throw new _in::LateError::localADI("local") : #t2{core::int};
   core::bool doRecursiveInitLocal = true;
   #recursiveInitLocal#set(() → core::int {
     core::print("Executing initializer");
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
index 66a67c4..bc55772 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
@@ -7,11 +7,11 @@
   lowered () →? core::int #recursiveInitLocal;
   function #recursiveInitLocal#get() → () → core::int
     return let final () →? core::int #t1 = #recursiveInitLocal in #t1 == null ?{() → core::int} throw new _in::LateError::localNI("recursiveInitLocal") : #t1{() → core::int};
-  function #recursiveInitLocal#set(() → core::int #t2) → dynamic
-    return #recursiveInitLocal = #t2;
+  function #recursiveInitLocal#set(() → core::int recursiveInitLocal#param) → dynamic
+    return #recursiveInitLocal = recursiveInitLocal#param;
   lowered final core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t3 = #local in #t3 == null ?{core::int} let final core::int #t4 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int} in #local == null ?{core::int} #local = #t4 : throw new _in::LateError::localADI("local") : #t3{core::int};
+    return let final core::int? #t2 = #local in #t2 == null ?{core::int} let final core::int #t3 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int} in #local == null ?{core::int} #local = #t3 : throw new _in::LateError::localADI("local") : #t2{core::int};
   core::bool doRecursiveInitLocal = true;
   #recursiveInitLocal#set(() → core::int {
     core::print("Executing initializer");
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
index 57a90e0..0858a5e 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
@@ -8,18 +8,18 @@
   lowered core::bool #recursiveInitLocal#isSet = false;
   function #recursiveInitLocal#get() → () → core::int
     return #recursiveInitLocal#isSet ?{() → core::int} #recursiveInitLocal{() → core::int} : throw new _in::LateError::localNI("recursiveInitLocal");
-  function #recursiveInitLocal#set(() → core::int #t1) → dynamic {
+  function #recursiveInitLocal#set(() → core::int recursiveInitLocal#param) → dynamic {
     #recursiveInitLocal#isSet = true;
-    return #recursiveInitLocal = #t1;
+    return #recursiveInitLocal = recursiveInitLocal#param;
   }
   lowered final core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int {
     if(!#local#isSet) {
-      final core::int #t2 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
+      final core::int #t1 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
       if(#local#isSet)
         throw new _in::LateError::localADI("local");
-      #local = #t2;
+      #local = #t1;
       #local#isSet = true;
     }
     return #local{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.modular.expect
index 57a90e0..0858a5e 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.modular.expect
@@ -8,18 +8,18 @@
   lowered core::bool #recursiveInitLocal#isSet = false;
   function #recursiveInitLocal#get() → () → core::int
     return #recursiveInitLocal#isSet ?{() → core::int} #recursiveInitLocal{() → core::int} : throw new _in::LateError::localNI("recursiveInitLocal");
-  function #recursiveInitLocal#set(() → core::int #t1) → dynamic {
+  function #recursiveInitLocal#set(() → core::int recursiveInitLocal#param) → dynamic {
     #recursiveInitLocal#isSet = true;
-    return #recursiveInitLocal = #t1;
+    return #recursiveInitLocal = recursiveInitLocal#param;
   }
   lowered final core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int {
     if(!#local#isSet) {
-      final core::int #t2 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
+      final core::int #t1 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
       if(#local#isSet)
         throw new _in::LateError::localADI("local");
-      #local = #t2;
+      #local = #t1;
       #local#isSet = true;
     }
     return #local{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
index 57a90e0..0858a5e 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
@@ -8,18 +8,18 @@
   lowered core::bool #recursiveInitLocal#isSet = false;
   function #recursiveInitLocal#get() → () → core::int
     return #recursiveInitLocal#isSet ?{() → core::int} #recursiveInitLocal{() → core::int} : throw new _in::LateError::localNI("recursiveInitLocal");
-  function #recursiveInitLocal#set(() → core::int #t1) → dynamic {
+  function #recursiveInitLocal#set(() → core::int recursiveInitLocal#param) → dynamic {
     #recursiveInitLocal#isSet = true;
-    return #recursiveInitLocal = #t1;
+    return #recursiveInitLocal = recursiveInitLocal#param;
   }
   lowered final core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int {
     if(!#local#isSet) {
-      final core::int #t2 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
+      final core::int #t1 = #recursiveInitLocal#get(){() → () → core::int}(){() → core::int};
       if(#local#isSet)
         throw new _in::LateError::localADI("local");
-      #local = #t2;
+      #local = #t1;
       #local#isSet = true;
     }
     return #local{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
index 9500bf5..5966501 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
@@ -23,44 +23,44 @@
   get instanceField() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#instanceField}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t1{core::int};
   @#C1
-  set instanceField(core::int #t2) → void
-    this.{self::A::_#A#instanceField} = #t2;
+  set instanceField(core::int instanceField#param) → void
+    this.{self::A::_#A#instanceField} = instanceField#param;
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t3{core::int};
+    return let final core::int? #t2 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t2{core::int};
   @#C1
-  set finalInstanceField(core::int #t4) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::A::_#A#finalInstanceField}{core::int?} == null)
-      this.{self::A::_#A#finalInstanceField} = #t4;
+      this.{self::A::_#A#finalInstanceField} = finalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceField");
   @#C1
   get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t5 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t5 == null ?{core::int} let final core::int #t6 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t6 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t5{core::int};
+    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t3 == null ?{core::int} let final core::int #t4 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t4 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t3{core::int};
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t7 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t7{core::num};
+    return let final core::num? #t5 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t5 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t5{core::num};
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void
-    this.{self::A::_#A#covariantInstanceField} = #t8;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void
+    this.{self::A::_#A#covariantInstanceField} = covariantInstanceField#param;
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t9 = self::A::_#staticField in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t9{core::int};
+    return let final core::int? #t6 = self::A::_#staticField in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t6{core::int};
   @#C1
-  static set staticField(core::int #t10) → void
-    self::A::_#staticField = #t10;
+  static set staticField(core::int staticField#param) → void
+    self::A::_#staticField = staticField#param;
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t11 = self::A::_#finalStaticField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t11{core::int};
+    return let final core::int? #t7 = self::A::_#finalStaticField in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t7{core::int};
   @#C1
-  static set finalStaticField(core::int #t12) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::A::_#finalStaticField == null)
-      self::A::_#finalStaticField = #t12;
+      self::A::_#finalStaticField = finalStaticField#param;
     else
       throw new _in::LateError::fieldAI("finalStaticField");
   @#C1
   static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t13 = self::A::_#finalStaticFieldWithInitializer in #t13 == null ?{core::int} let final core::int #t14 = 0 in self::A::_#finalStaticFieldWithInitializer == null ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t13{core::int};
+    return let final core::int? #t8 = self::A::_#finalStaticFieldWithInitializer in #t8 == null ?{core::int} let final core::int #t9 = 0 in self::A::_#finalStaticFieldWithInitializer == null ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t9 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t8{core::int};
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   field core::int? _#B#instanceField = null;
@@ -72,46 +72,46 @@
   static field core::int? _#finalStaticFieldWithInitializer = null;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t15 = this.{self::B::_#B#instanceField}{core::int?} in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t15{core::int};
+    return let final core::int? #t10 = this.{self::B::_#B#instanceField}{core::int?} in #t10 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t10{core::int};
   @#C1
-  set instanceField(core::int #t16) → void
-    this.{self::B::_#B#instanceField} = #t16;
+  set instanceField(core::int instanceField#param) → void
+    this.{self::B::_#B#instanceField} = instanceField#param;
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t17 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t17{core::int};
+    return let final core::int? #t11 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t11{core::int};
   @#C1
-  set finalInstanceField(core::int #t18) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::B::_#B#finalInstanceField}{core::int?} == null)
-      this.{self::B::_#B#finalInstanceField} = #t18;
+      this.{self::B::_#B#finalInstanceField} = finalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceField");
   @#C1
   get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t19 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t19 == null ?{core::int} let final core::int #t20 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t20 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t19{core::int};
+    return let final core::int? #t12 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t12 == null ?{core::int} let final core::int #t13 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t13 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t12{core::int};
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t21 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t21{core::num};
+    return let final core::num? #t14 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t14 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t14{core::num};
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t22) → void
-    this.{self::B::_#B#covariantInstanceField} = #t22;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void
+    this.{self::B::_#B#covariantInstanceField} = covariantInstanceField#param;
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t23 = self::B::_#staticField in #t23 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t23{core::int};
+    return let final core::int? #t15 = self::B::_#staticField in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t15{core::int};
   @#C1
-  static set staticField(core::int #t24) → void
-    self::B::_#staticField = #t24;
+  static set staticField(core::int staticField#param) → void
+    self::B::_#staticField = staticField#param;
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t25 = self::B::_#finalStaticField in #t25 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t25{core::int};
+    return let final core::int? #t16 = self::B::_#finalStaticField in #t16 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t16{core::int};
   @#C1
-  static set finalStaticField(core::int #t26) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::B::_#finalStaticField == null)
-      self::B::_#finalStaticField = #t26;
+      self::B::_#finalStaticField = finalStaticField#param;
     else
       throw new _in::LateError::fieldAI("finalStaticField");
   @#C1
   static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t27 = self::B::_#finalStaticFieldWithInitializer in #t27 == null ?{core::int} let final core::int #t28 = 0 in self::B::_#finalStaticFieldWithInitializer == null ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t28 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t27{core::int};
+    return let final core::int? #t17 = self::B::_#finalStaticFieldWithInitializer in #t17 == null ?{core::int} let final core::int #t18 = 0 in self::B::_#finalStaticFieldWithInitializer == null ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t18 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t17{core::int};
 }
 extension Extension on self::A {
   static field extensionStaticField = self::_#Extension|extensionStaticField;
@@ -131,40 +131,40 @@
 static field core::int? _#Extension|finalExtensionStaticFieldWithInitializer = null;
 @#C1
 static get topLevelField() → core::int
-  return let final core::int? #t29 = self::_#topLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t29{core::int};
+  return let final core::int? #t19 = self::_#topLevelField in #t19 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t19{core::int};
 @#C1
-static set topLevelField(core::int #t30) → void
-  self::_#topLevelField = #t30;
+static set topLevelField(core::int topLevelField#param) → void
+  self::_#topLevelField = topLevelField#param;
 @#C1
 static get finalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#finalTopLevelField in #t31 == null ?{core::int} throw new _in::LateError::fieldNI("finalTopLevelField") : #t31{core::int};
+  return let final core::int? #t20 = self::_#finalTopLevelField in #t20 == null ?{core::int} throw new _in::LateError::fieldNI("finalTopLevelField") : #t20{core::int};
 @#C1
-static set finalTopLevelField(core::int #t32) → void
+static set finalTopLevelField(core::int finalTopLevelField#param) → void
   if(self::_#finalTopLevelField == null)
-    self::_#finalTopLevelField = #t32;
+    self::_#finalTopLevelField = finalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("finalTopLevelField");
 @#C1
 static get finalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t33 = self::_#finalTopLevelFieldWithInitializer in #t33 == null ?{core::int} let final core::int #t34 = 0 in self::_#finalTopLevelFieldWithInitializer == null ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t34 : throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer") : #t33{core::int};
+  return let final core::int? #t21 = self::_#finalTopLevelFieldWithInitializer in #t21 == null ?{core::int} let final core::int #t22 = 0 in self::_#finalTopLevelFieldWithInitializer == null ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t22 : throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer") : #t21{core::int};
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35 == null ?{core::int} throw new _in::LateError::fieldNI("extensionStaticField") : #t35{core::int};
+  return let final core::int? #t23 = self::_#Extension|extensionStaticField in #t23 == null ?{core::int} throw new _in::LateError::fieldNI("extensionStaticField") : #t23{core::int};
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void
-  self::_#Extension|extensionStaticField = #t36;
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void
+  self::_#Extension|extensionStaticField = Extension|extensionStaticField#param;
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37 == null ?{core::int} throw new _in::LateError::fieldNI("finalExtensionStaticField") : #t37{core::int};
+  return let final core::int? #t24 = self::_#Extension|finalExtensionStaticField in #t24 == null ?{core::int} throw new _in::LateError::fieldNI("finalExtensionStaticField") : #t24{core::int};
 @#C1
-static set Extension|finalExtensionStaticField(core::int #t38) → void
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void
   if(self::_#Extension|finalExtensionStaticField == null)
-    self::_#Extension|finalExtensionStaticField = #t38;
+    self::_#Extension|finalExtensionStaticField = Extension|finalExtensionStaticField#param;
   else
     throw new _in::LateError::fieldAI("finalExtensionStaticField");
 @#C1
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int
-  return let final core::int? #t39 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t39 == null ?{core::int} let final core::int #t40 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer == null ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t40 : throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer") : #t39{core::int};
+  return let final core::int? #t25 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t25 == null ?{core::int} let final core::int #t26 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer == null ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t26 : throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer") : #t25{core::int};
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
index 5c3dc32..68c30b5 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
@@ -23,44 +23,44 @@
   get instanceField() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#instanceField}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t1{core::int};
   @#C1
-  set instanceField(core::int #t2) → void
-    this.{self::A::_#A#instanceField} = #t2;
+  set instanceField(core::int instanceField#param) → void
+    this.{self::A::_#A#instanceField} = instanceField#param;
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t3{core::int};
+    return let final core::int? #t2 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t2{core::int};
   @#C1
-  set finalInstanceField(core::int #t4) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::A::_#A#finalInstanceField}{core::int?} == null)
-      this.{self::A::_#A#finalInstanceField} = #t4;
+      this.{self::A::_#A#finalInstanceField} = finalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceField");
   @#C1
   get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t5 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t5 == null ?{core::int} let final core::int #t6 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t6 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t5{core::int};
+    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t3 == null ?{core::int} let final core::int #t4 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t4 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t3{core::int};
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t7 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t7{core::num};
+    return let final core::num? #t5 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t5 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t5{core::num};
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void
-    this.{self::A::_#A#covariantInstanceField} = #t8;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void
+    this.{self::A::_#A#covariantInstanceField} = covariantInstanceField#param;
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t9 = self::A::_#staticField in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t9{core::int};
+    return let final core::int? #t6 = self::A::_#staticField in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t6{core::int};
   @#C1
-  static set staticField(core::int #t10) → void
-    self::A::_#staticField = #t10;
+  static set staticField(core::int staticField#param) → void
+    self::A::_#staticField = staticField#param;
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t11 = self::A::_#finalStaticField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t11{core::int};
+    return let final core::int? #t7 = self::A::_#finalStaticField in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t7{core::int};
   @#C1
-  static set finalStaticField(core::int #t12) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::A::_#finalStaticField == null)
-      self::A::_#finalStaticField = #t12;
+      self::A::_#finalStaticField = finalStaticField#param;
     else
       throw new _in::LateError::fieldAI("finalStaticField");
   @#C1
   static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t13 = self::A::_#finalStaticFieldWithInitializer in #t13 == null ?{core::int} let final core::int #t14 = 0 in self::A::_#finalStaticFieldWithInitializer == null ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t13{core::int};
+    return let final core::int? #t8 = self::A::_#finalStaticFieldWithInitializer in #t8 == null ?{core::int} let final core::int #t9 = 0 in self::A::_#finalStaticFieldWithInitializer == null ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t9 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t8{core::int};
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   field core::int? _#B#instanceField = null;
@@ -72,46 +72,46 @@
   static field core::int? _#finalStaticFieldWithInitializer = null;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t15 = this.{self::B::_#B#instanceField}{core::int?} in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t15{core::int};
+    return let final core::int? #t10 = this.{self::B::_#B#instanceField}{core::int?} in #t10 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t10{core::int};
   @#C1
-  set instanceField(core::int #t16) → void
-    this.{self::B::_#B#instanceField} = #t16;
+  set instanceField(core::int instanceField#param) → void
+    this.{self::B::_#B#instanceField} = instanceField#param;
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t17 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t17{core::int};
+    return let final core::int? #t11 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("finalInstanceField") : #t11{core::int};
   @#C1
-  set finalInstanceField(core::int #t18) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::B::_#B#finalInstanceField}{core::int?} == null)
-      this.{self::B::_#B#finalInstanceField} = #t18;
+      this.{self::B::_#B#finalInstanceField} = finalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceField");
   @#C1
   get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t19 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t19 == null ?{core::int} let final core::int #t20 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t20 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t19{core::int};
+    return let final core::int? #t12 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t12 == null ?{core::int} let final core::int #t13 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} == null ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t13 : throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer") : #t12{core::int};
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t21 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t21{core::num};
+    return let final core::num? #t14 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t14 == null ?{core::num} throw new _in::LateError::fieldNI("covariantInstanceField") : #t14{core::num};
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t22) → void
-    this.{self::B::_#B#covariantInstanceField} = #t22;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void
+    this.{self::B::_#B#covariantInstanceField} = covariantInstanceField#param;
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t23 = self::B::_#staticField in #t23 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t23{core::int};
+    return let final core::int? #t15 = self::B::_#staticField in #t15 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t15{core::int};
   @#C1
-  static set staticField(core::int #t24) → void
-    self::B::_#staticField = #t24;
+  static set staticField(core::int staticField#param) → void
+    self::B::_#staticField = staticField#param;
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t25 = self::B::_#finalStaticField in #t25 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t25{core::int};
+    return let final core::int? #t16 = self::B::_#finalStaticField in #t16 == null ?{core::int} throw new _in::LateError::fieldNI("finalStaticField") : #t16{core::int};
   @#C1
-  static set finalStaticField(core::int #t26) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::B::_#finalStaticField == null)
-      self::B::_#finalStaticField = #t26;
+      self::B::_#finalStaticField = finalStaticField#param;
     else
       throw new _in::LateError::fieldAI("finalStaticField");
   @#C1
   static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t27 = self::B::_#finalStaticFieldWithInitializer in #t27 == null ?{core::int} let final core::int #t28 = 0 in self::B::_#finalStaticFieldWithInitializer == null ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t28 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t27{core::int};
+    return let final core::int? #t17 = self::B::_#finalStaticFieldWithInitializer in #t17 == null ?{core::int} let final core::int #t18 = 0 in self::B::_#finalStaticFieldWithInitializer == null ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t18 : throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer") : #t17{core::int};
 }
 extension Extension on self::A {
   static field extensionStaticField = self::_#Extension|extensionStaticField;
@@ -131,40 +131,40 @@
 static field core::int? _#Extension|finalExtensionStaticFieldWithInitializer = null;
 @#C1
 static get topLevelField() → core::int
-  return let final core::int? #t29 = self::_#topLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t29{core::int};
+  return let final core::int? #t19 = self::_#topLevelField in #t19 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t19{core::int};
 @#C1
-static set topLevelField(core::int #t30) → void
-  self::_#topLevelField = #t30;
+static set topLevelField(core::int topLevelField#param) → void
+  self::_#topLevelField = topLevelField#param;
 @#C1
 static get finalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#finalTopLevelField in #t31 == null ?{core::int} throw new _in::LateError::fieldNI("finalTopLevelField") : #t31{core::int};
+  return let final core::int? #t20 = self::_#finalTopLevelField in #t20 == null ?{core::int} throw new _in::LateError::fieldNI("finalTopLevelField") : #t20{core::int};
 @#C1
-static set finalTopLevelField(core::int #t32) → void
+static set finalTopLevelField(core::int finalTopLevelField#param) → void
   if(self::_#finalTopLevelField == null)
-    self::_#finalTopLevelField = #t32;
+    self::_#finalTopLevelField = finalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("finalTopLevelField");
 @#C1
 static get finalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t33 = self::_#finalTopLevelFieldWithInitializer in #t33 == null ?{core::int} let final core::int #t34 = 0 in self::_#finalTopLevelFieldWithInitializer == null ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t34 : throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer") : #t33{core::int};
+  return let final core::int? #t21 = self::_#finalTopLevelFieldWithInitializer in #t21 == null ?{core::int} let final core::int #t22 = 0 in self::_#finalTopLevelFieldWithInitializer == null ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t22 : throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer") : #t21{core::int};
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35 == null ?{core::int} throw new _in::LateError::fieldNI("extensionStaticField") : #t35{core::int};
+  return let final core::int? #t23 = self::_#Extension|extensionStaticField in #t23 == null ?{core::int} throw new _in::LateError::fieldNI("extensionStaticField") : #t23{core::int};
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void
-  self::_#Extension|extensionStaticField = #t36;
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void
+  self::_#Extension|extensionStaticField = Extension|extensionStaticField#param;
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37 == null ?{core::int} throw new _in::LateError::fieldNI("finalExtensionStaticField") : #t37{core::int};
+  return let final core::int? #t24 = self::_#Extension|finalExtensionStaticField in #t24 == null ?{core::int} throw new _in::LateError::fieldNI("finalExtensionStaticField") : #t24{core::int};
 @#C1
-static set Extension|finalExtensionStaticField(core::int #t38) → void
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void
   if(self::_#Extension|finalExtensionStaticField == null)
-    self::_#Extension|finalExtensionStaticField = #t38;
+    self::_#Extension|finalExtensionStaticField = Extension|finalExtensionStaticField#param;
   else
     throw new _in::LateError::fieldAI("finalExtensionStaticField");
 @#C1
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int
-  return let final core::int? #t39 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t39 == null ?{core::int} let final core::int #t40 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer == null ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t40 : throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer") : #t39{core::int};
+  return let final core::int? #t25 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t25 == null ?{core::int} let final core::int #t26 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer == null ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t26 : throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer") : #t25{core::int};
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
index 784ff0c..061a612 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
@@ -30,69 +30,69 @@
   get instanceField() → core::int
     return this.{self::A::_#A#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::A::_#A#instanceField#isSet} = true;
-    this.{self::A::_#A#instanceField} = #t2;
+    this.{self::A::_#A#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t4) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::A::_#A#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::A::_#A#finalInstanceField#isSet} = true;
-      this.{self::A::_#A#finalInstanceField} = #t4;
+      this.{self::A::_#A#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t5 = 0;
+      final core::int #t3 = 0;
       if(this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t5;
+      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t3;
       this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t6 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t6{core::int};
+    return let final core::int? #t4 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t4{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t7{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t5 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t5{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::A::_#A#covariantInstanceField#isSet} = true;
-    this.{self::A::_#A#covariantInstanceField} = #t8;
+    this.{self::A::_#A#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t9 = self::A::_#staticField in #t9{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t6 = self::A::_#staticField in #t6{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t10) → void {
+  static set staticField(core::int staticField#param) → void {
     self::A::_#staticField#isSet = true;
-    self::A::_#staticField = #t10;
+    self::A::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t11 = self::A::_#finalStaticField in #t11{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t7 = self::A::_#finalStaticField in #t7{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t12) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::A::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::A::_#finalStaticField#isSet = true;
-      self::A::_#finalStaticField = #t12;
+      self::A::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::A::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(self::A::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::A::_#finalStaticFieldWithInitializer = #t13;
+      self::A::_#finalStaticFieldWithInitializer = #t8;
       self::A::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t14 = self::A::_#finalStaticFieldWithInitializer in #t14{core::int};
+    return let final core::int? #t9 = self::A::_#finalStaticFieldWithInitializer in #t9{core::int};
   }
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
@@ -112,71 +112,71 @@
   static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   @#C1
   get instanceField() → core::int
-    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::B::_#B#instanceField}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("instanceField");
+    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t10 = this.{self::B::_#B#instanceField}{core::int?} in #t10{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t16) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::B::_#B#instanceField#isSet} = true;
-    this.{self::B::_#B#instanceField} = #t16;
+    this.{self::B::_#B#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t17 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t17{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t18) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::B::_#B#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::B::_#B#finalInstanceField#isSet} = true;
-      this.{self::B::_#B#finalInstanceField} = #t18;
+      this.{self::B::_#B#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t19 = 0;
+      final core::int #t12 = 0;
       if(this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t19;
+      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t12;
       this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t20 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t20{core::int};
+    return let final core::int? #t13 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t13{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t21{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t14 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t14{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t22) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::B::_#B#covariantInstanceField#isSet} = true;
-    this.{self::B::_#B#covariantInstanceField} = #t22;
+    this.{self::B::_#B#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t23 = self::B::_#staticField in #t23{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t15 = self::B::_#staticField in #t15{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t24) → void {
+  static set staticField(core::int staticField#param) → void {
     self::B::_#staticField#isSet = true;
-    self::B::_#staticField = #t24;
+    self::B::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t25 = self::B::_#finalStaticField in #t25{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t16 = self::B::_#finalStaticField in #t16{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t26) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::B::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::B::_#finalStaticField#isSet = true;
-      self::B::_#finalStaticField = #t26;
+      self::B::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::B::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t27 = 0;
+      final core::int #t17 = 0;
       if(self::B::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::B::_#finalStaticFieldWithInitializer = #t27;
+      self::B::_#finalStaticFieldWithInitializer = #t17;
       self::B::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t28 = self::B::_#finalStaticFieldWithInitializer in #t28{core::int};
+    return let final core::int? #t18 = self::B::_#finalStaticFieldWithInitializer in #t18{core::int};
   }
 }
 extension Extension on self::A {
@@ -206,63 +206,63 @@
 static field core::bool _#Extension|finalExtensionStaticFieldWithInitializer#isSet = false;
 @#C1
 static get topLevelField() → core::int
-  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t29 = self::_#topLevelField in #t29{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t19 = self::_#topLevelField in #t19{core::int} : throw new _in::LateError::fieldNI("topLevelField");
 @#C1
-static set topLevelField(core::int #t30) → void {
+static set topLevelField(core::int topLevelField#param) → void {
   self::_#topLevelField#isSet = true;
-  self::_#topLevelField = #t30;
+  self::_#topLevelField = topLevelField#param;
 }
 @#C1
 static get finalTopLevelField() → core::int
-  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t31 = self::_#finalTopLevelField in #t31{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
+  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t20 = self::_#finalTopLevelField in #t20{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
 @#C1
-static set finalTopLevelField(core::int #t32) → void
+static set finalTopLevelField(core::int finalTopLevelField#param) → void
   if(self::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     self::_#finalTopLevelField#isSet = true;
-    self::_#finalTopLevelField = #t32;
+    self::_#finalTopLevelField = finalTopLevelField#param;
   }
 @#C1
 static get finalTopLevelFieldWithInitializer() → core::int {
   if(!self::_#finalTopLevelFieldWithInitializer#isSet) {
-    final core::int #t33 = 0;
+    final core::int #t21 = 0;
     if(self::_#finalTopLevelFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer");
-    self::_#finalTopLevelFieldWithInitializer = #t33;
+    self::_#finalTopLevelFieldWithInitializer = #t21;
     self::_#finalTopLevelFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t34 = self::_#finalTopLevelFieldWithInitializer in #t34{core::int};
+  return let final core::int? #t22 = self::_#finalTopLevelFieldWithInitializer in #t22{core::int};
 }
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
+  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t23 = self::_#Extension|extensionStaticField in #t23{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void {
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void {
   self::_#Extension|extensionStaticField#isSet = true;
-  self::_#Extension|extensionStaticField = #t36;
+  self::_#Extension|extensionStaticField = Extension|extensionStaticField#param;
 }
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
+  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t24 = self::_#Extension|finalExtensionStaticField in #t24{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
 @#C1
-static set Extension|finalExtensionStaticField(core::int #t38) → void
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void
   if(self::_#Extension|finalExtensionStaticField#isSet)
     throw new _in::LateError::fieldAI("finalExtensionStaticField");
   else {
     self::_#Extension|finalExtensionStaticField#isSet = true;
-    self::_#Extension|finalExtensionStaticField = #t38;
+    self::_#Extension|finalExtensionStaticField = Extension|finalExtensionStaticField#param;
   }
 @#C1
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int {
   if(!self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet) {
-    final core::int #t39 = 0;
+    final core::int #t25 = 0;
     if(self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer");
-    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t39;
+    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t25;
     self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t40 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t40{core::int};
+  return let final core::int? #t26 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t26{core::int};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.modular.expect
index 784ff0c..061a612 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.modular.expect
@@ -30,69 +30,69 @@
   get instanceField() → core::int
     return this.{self::A::_#A#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::A::_#A#instanceField#isSet} = true;
-    this.{self::A::_#A#instanceField} = #t2;
+    this.{self::A::_#A#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t4) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::A::_#A#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::A::_#A#finalInstanceField#isSet} = true;
-      this.{self::A::_#A#finalInstanceField} = #t4;
+      this.{self::A::_#A#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t5 = 0;
+      final core::int #t3 = 0;
       if(this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t5;
+      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t3;
       this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t6 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t6{core::int};
+    return let final core::int? #t4 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t4{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t7{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t5 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t5{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::A::_#A#covariantInstanceField#isSet} = true;
-    this.{self::A::_#A#covariantInstanceField} = #t8;
+    this.{self::A::_#A#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t9 = self::A::_#staticField in #t9{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t6 = self::A::_#staticField in #t6{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t10) → void {
+  static set staticField(core::int staticField#param) → void {
     self::A::_#staticField#isSet = true;
-    self::A::_#staticField = #t10;
+    self::A::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t11 = self::A::_#finalStaticField in #t11{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t7 = self::A::_#finalStaticField in #t7{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t12) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::A::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::A::_#finalStaticField#isSet = true;
-      self::A::_#finalStaticField = #t12;
+      self::A::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::A::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(self::A::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::A::_#finalStaticFieldWithInitializer = #t13;
+      self::A::_#finalStaticFieldWithInitializer = #t8;
       self::A::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t14 = self::A::_#finalStaticFieldWithInitializer in #t14{core::int};
+    return let final core::int? #t9 = self::A::_#finalStaticFieldWithInitializer in #t9{core::int};
   }
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
@@ -112,71 +112,71 @@
   static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   @#C1
   get instanceField() → core::int
-    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::B::_#B#instanceField}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("instanceField");
+    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t10 = this.{self::B::_#B#instanceField}{core::int?} in #t10{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t16) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::B::_#B#instanceField#isSet} = true;
-    this.{self::B::_#B#instanceField} = #t16;
+    this.{self::B::_#B#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t17 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t17{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t18) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::B::_#B#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::B::_#B#finalInstanceField#isSet} = true;
-      this.{self::B::_#B#finalInstanceField} = #t18;
+      this.{self::B::_#B#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t19 = 0;
+      final core::int #t12 = 0;
       if(this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t19;
+      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t12;
       this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t20 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t20{core::int};
+    return let final core::int? #t13 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t13{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t21{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t14 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t14{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t22) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::B::_#B#covariantInstanceField#isSet} = true;
-    this.{self::B::_#B#covariantInstanceField} = #t22;
+    this.{self::B::_#B#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t23 = self::B::_#staticField in #t23{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t15 = self::B::_#staticField in #t15{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t24) → void {
+  static set staticField(core::int staticField#param) → void {
     self::B::_#staticField#isSet = true;
-    self::B::_#staticField = #t24;
+    self::B::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t25 = self::B::_#finalStaticField in #t25{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t16 = self::B::_#finalStaticField in #t16{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t26) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::B::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::B::_#finalStaticField#isSet = true;
-      self::B::_#finalStaticField = #t26;
+      self::B::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::B::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t27 = 0;
+      final core::int #t17 = 0;
       if(self::B::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::B::_#finalStaticFieldWithInitializer = #t27;
+      self::B::_#finalStaticFieldWithInitializer = #t17;
       self::B::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t28 = self::B::_#finalStaticFieldWithInitializer in #t28{core::int};
+    return let final core::int? #t18 = self::B::_#finalStaticFieldWithInitializer in #t18{core::int};
   }
 }
 extension Extension on self::A {
@@ -206,63 +206,63 @@
 static field core::bool _#Extension|finalExtensionStaticFieldWithInitializer#isSet = false;
 @#C1
 static get topLevelField() → core::int
-  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t29 = self::_#topLevelField in #t29{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t19 = self::_#topLevelField in #t19{core::int} : throw new _in::LateError::fieldNI("topLevelField");
 @#C1
-static set topLevelField(core::int #t30) → void {
+static set topLevelField(core::int topLevelField#param) → void {
   self::_#topLevelField#isSet = true;
-  self::_#topLevelField = #t30;
+  self::_#topLevelField = topLevelField#param;
 }
 @#C1
 static get finalTopLevelField() → core::int
-  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t31 = self::_#finalTopLevelField in #t31{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
+  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t20 = self::_#finalTopLevelField in #t20{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
 @#C1
-static set finalTopLevelField(core::int #t32) → void
+static set finalTopLevelField(core::int finalTopLevelField#param) → void
   if(self::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     self::_#finalTopLevelField#isSet = true;
-    self::_#finalTopLevelField = #t32;
+    self::_#finalTopLevelField = finalTopLevelField#param;
   }
 @#C1
 static get finalTopLevelFieldWithInitializer() → core::int {
   if(!self::_#finalTopLevelFieldWithInitializer#isSet) {
-    final core::int #t33 = 0;
+    final core::int #t21 = 0;
     if(self::_#finalTopLevelFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer");
-    self::_#finalTopLevelFieldWithInitializer = #t33;
+    self::_#finalTopLevelFieldWithInitializer = #t21;
     self::_#finalTopLevelFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t34 = self::_#finalTopLevelFieldWithInitializer in #t34{core::int};
+  return let final core::int? #t22 = self::_#finalTopLevelFieldWithInitializer in #t22{core::int};
 }
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
+  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t23 = self::_#Extension|extensionStaticField in #t23{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void {
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void {
   self::_#Extension|extensionStaticField#isSet = true;
-  self::_#Extension|extensionStaticField = #t36;
+  self::_#Extension|extensionStaticField = Extension|extensionStaticField#param;
 }
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
+  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t24 = self::_#Extension|finalExtensionStaticField in #t24{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
 @#C1
-static set Extension|finalExtensionStaticField(core::int #t38) → void
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void
   if(self::_#Extension|finalExtensionStaticField#isSet)
     throw new _in::LateError::fieldAI("finalExtensionStaticField");
   else {
     self::_#Extension|finalExtensionStaticField#isSet = true;
-    self::_#Extension|finalExtensionStaticField = #t38;
+    self::_#Extension|finalExtensionStaticField = Extension|finalExtensionStaticField#param;
   }
 @#C1
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int {
   if(!self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet) {
-    final core::int #t39 = 0;
+    final core::int #t25 = 0;
     if(self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer");
-    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t39;
+    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t25;
     self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t40 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t40{core::int};
+  return let final core::int? #t26 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t26{core::int};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.outline.expect
index 282fc21..6f107ab 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.outline.expect
@@ -27,25 +27,25 @@
   @self::Annotation::•()
   get instanceField() → core::int;
   @self::Annotation::•()
-  set instanceField(core::int #t1) → void;
+  set instanceField(core::int instanceField#param) → void;
   @self::Annotation::•()
   get finalInstanceField() → core::int;
   @self::Annotation::•()
-  set finalInstanceField(core::int #t2) → void;
+  set finalInstanceField(core::int finalInstanceField#param) → void;
   @self::Annotation::•()
   get finalInstanceFieldWithInitializer() → core::int;
   @self::Annotation::•()
   get covariantInstanceField() → core::num;
   @self::Annotation::•()
-  set covariantInstanceField(covariant-by-declaration core::num #t3) → void;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void;
   @self::Annotation::•()
   static get staticField() → core::int;
   @self::Annotation::•()
-  static set staticField(core::int #t4) → void;
+  static set staticField(core::int staticField#param) → void;
   @self::Annotation::•()
   static get finalStaticField() → core::int;
   @self::Annotation::•()
-  static set finalStaticField(core::int #t5) → void;
+  static set finalStaticField(core::int finalStaticField#param) → void;
   @self::Annotation::•()
   static get finalStaticFieldWithInitializer() → core::int;
 }
@@ -67,25 +67,25 @@
   @self::Annotation::•()
   get instanceField() → core::int;
   @self::Annotation::•()
-  set instanceField(core::int #t6) → void;
+  set instanceField(core::int instanceField#param) → void;
   @self::Annotation::•()
   get finalInstanceField() → core::int;
   @self::Annotation::•()
-  set finalInstanceField(core::int #t7) → void;
+  set finalInstanceField(core::int finalInstanceField#param) → void;
   @self::Annotation::•()
   get finalInstanceFieldWithInitializer() → core::int;
   @self::Annotation::•()
   get covariantInstanceField() → core::num;
   @self::Annotation::•()
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void;
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void;
   @self::Annotation::•()
   static get staticField() → core::int;
   @self::Annotation::•()
-  static set staticField(core::int #t9) → void;
+  static set staticField(core::int staticField#param) → void;
   @self::Annotation::•()
   static get finalStaticField() → core::int;
   @self::Annotation::•()
-  static set finalStaticField(core::int #t10) → void;
+  static set finalStaticField(core::int finalStaticField#param) → void;
   @self::Annotation::•()
   static get finalStaticFieldWithInitializer() → core::int;
 }
@@ -117,21 +117,21 @@
 @self::Annotation::•()
 static get topLevelField() → core::int;
 @self::Annotation::•()
-static set topLevelField(core::int #t11) → void;
+static set topLevelField(core::int topLevelField#param) → void;
 @self::Annotation::•()
 static get finalTopLevelField() → core::int;
 @self::Annotation::•()
-static set finalTopLevelField(core::int #t12) → void;
+static set finalTopLevelField(core::int finalTopLevelField#param) → void;
 @self::Annotation::•()
 static get finalTopLevelFieldWithInitializer() → core::int;
 @self::Annotation::•()
 static get Extension|extensionStaticField() → core::int;
 @self::Annotation::•()
-static set Extension|extensionStaticField(core::int #t13) → void;
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void;
 @self::Annotation::•()
 static get Extension|finalExtensionStaticField() → core::int;
 @self::Annotation::•()
-static set Extension|finalExtensionStaticField(core::int #t14) → void;
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void;
 @self::Annotation::•()
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
index 784ff0c..061a612 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
@@ -30,69 +30,69 @@
   get instanceField() → core::int
     return this.{self::A::_#A#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::A::_#A#instanceField#isSet} = true;
-    this.{self::A::_#A#instanceField} = #t2;
+    this.{self::A::_#A#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::A::_#A#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::A::_#A#finalInstanceField}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t4) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::A::_#A#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::A::_#A#finalInstanceField#isSet} = true;
-      this.{self::A::_#A#finalInstanceField} = #t4;
+      this.{self::A::_#A#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t5 = 0;
+      final core::int #t3 = 0;
       if(this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t5;
+      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t3;
       this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t6 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t6{core::int};
+    return let final core::int? #t4 = this.{self::A::_#A#finalInstanceFieldWithInitializer}{core::int?} in #t4{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t7{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::A::_#A#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t5 = this.{self::A::_#A#covariantInstanceField}{core::num?} in #t5{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t8) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::A::_#A#covariantInstanceField#isSet} = true;
-    this.{self::A::_#A#covariantInstanceField} = #t8;
+    this.{self::A::_#A#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t9 = self::A::_#staticField in #t9{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t6 = self::A::_#staticField in #t6{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t10) → void {
+  static set staticField(core::int staticField#param) → void {
     self::A::_#staticField#isSet = true;
-    self::A::_#staticField = #t10;
+    self::A::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t11 = self::A::_#finalStaticField in #t11{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t7 = self::A::_#finalStaticField in #t7{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t12) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::A::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::A::_#finalStaticField#isSet = true;
-      self::A::_#finalStaticField = #t12;
+      self::A::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::A::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(self::A::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::A::_#finalStaticFieldWithInitializer = #t13;
+      self::A::_#finalStaticFieldWithInitializer = #t8;
       self::A::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t14 = self::A::_#finalStaticFieldWithInitializer in #t14{core::int};
+    return let final core::int? #t9 = self::A::_#finalStaticFieldWithInitializer in #t9{core::int};
   }
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
@@ -112,71 +112,71 @@
   static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   @#C1
   get instanceField() → core::int
-    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t15 = this.{self::B::_#B#instanceField}{core::int?} in #t15{core::int} : throw new _in::LateError::fieldNI("instanceField");
+    return this.{self::B::_#B#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t10 = this.{self::B::_#B#instanceField}{core::int?} in #t10{core::int} : throw new _in::LateError::fieldNI("instanceField");
   @#C1
-  set instanceField(core::int #t16) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{self::B::_#B#instanceField#isSet} = true;
-    this.{self::B::_#B#instanceField} = #t16;
+    this.{self::B::_#B#instanceField} = instanceField#param;
   }
   @#C1
   get finalInstanceField() → core::int
-    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t17 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t17{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
+    return this.{self::B::_#B#finalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::B::_#B#finalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("finalInstanceField");
   @#C1
-  set finalInstanceField(core::int #t18) → void
+  set finalInstanceField(core::int finalInstanceField#param) → void
     if(this.{self::B::_#B#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{self::B::_#B#finalInstanceField#isSet} = true;
-      this.{self::B::_#B#finalInstanceField} = #t18;
+      this.{self::B::_#B#finalInstanceField} = finalInstanceField#param;
     }
   @#C1
   get finalInstanceFieldWithInitializer() → core::int {
     if(!this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool}) {
-      final core::int #t19 = 0;
+      final core::int #t12 = 0;
       if(this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}{core::bool})
         throw new _in::LateError::fieldADI("finalInstanceFieldWithInitializer");
-      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t19;
+      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t12;
       this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet} = true;
     }
-    return let final core::int? #t20 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t20{core::int};
+    return let final core::int? #t13 = this.{self::B::_#B#finalInstanceFieldWithInitializer}{core::int?} in #t13{core::int};
   }
   @#C1
   get covariantInstanceField() → core::num
-    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t21{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
+    return this.{self::B::_#B#covariantInstanceField#isSet}{core::bool} ?{core::num} let final core::num? #t14 = this.{self::B::_#B#covariantInstanceField}{core::num?} in #t14{core::num} : throw new _in::LateError::fieldNI("covariantInstanceField");
   @#C1
-  set covariantInstanceField(covariant-by-declaration core::num #t22) → void {
+  set covariantInstanceField(covariant-by-declaration core::num covariantInstanceField#param) → void {
     this.{self::B::_#B#covariantInstanceField#isSet} = true;
-    this.{self::B::_#B#covariantInstanceField} = #t22;
+    this.{self::B::_#B#covariantInstanceField} = covariantInstanceField#param;
   }
   @#C1
   static get staticField() → core::int
-    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t23 = self::B::_#staticField in #t23{core::int} : throw new _in::LateError::fieldNI("staticField");
+    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t15 = self::B::_#staticField in #t15{core::int} : throw new _in::LateError::fieldNI("staticField");
   @#C1
-  static set staticField(core::int #t24) → void {
+  static set staticField(core::int staticField#param) → void {
     self::B::_#staticField#isSet = true;
-    self::B::_#staticField = #t24;
+    self::B::_#staticField = staticField#param;
   }
   @#C1
   static get finalStaticField() → core::int
-    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t25 = self::B::_#finalStaticField in #t25{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
+    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t16 = self::B::_#finalStaticField in #t16{core::int} : throw new _in::LateError::fieldNI("finalStaticField");
   @#C1
-  static set finalStaticField(core::int #t26) → void
+  static set finalStaticField(core::int finalStaticField#param) → void
     if(self::B::_#finalStaticField#isSet)
       throw new _in::LateError::fieldAI("finalStaticField");
     else {
       self::B::_#finalStaticField#isSet = true;
-      self::B::_#finalStaticField = #t26;
+      self::B::_#finalStaticField = finalStaticField#param;
     }
   @#C1
   static get finalStaticFieldWithInitializer() → core::int {
     if(!self::B::_#finalStaticFieldWithInitializer#isSet) {
-      final core::int #t27 = 0;
+      final core::int #t17 = 0;
       if(self::B::_#finalStaticFieldWithInitializer#isSet)
         throw new _in::LateError::fieldADI("finalStaticFieldWithInitializer");
-      self::B::_#finalStaticFieldWithInitializer = #t27;
+      self::B::_#finalStaticFieldWithInitializer = #t17;
       self::B::_#finalStaticFieldWithInitializer#isSet = true;
     }
-    return let final core::int? #t28 = self::B::_#finalStaticFieldWithInitializer in #t28{core::int};
+    return let final core::int? #t18 = self::B::_#finalStaticFieldWithInitializer in #t18{core::int};
   }
 }
 extension Extension on self::A {
@@ -206,63 +206,63 @@
 static field core::bool _#Extension|finalExtensionStaticFieldWithInitializer#isSet = false;
 @#C1
 static get topLevelField() → core::int
-  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t29 = self::_#topLevelField in #t29{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t19 = self::_#topLevelField in #t19{core::int} : throw new _in::LateError::fieldNI("topLevelField");
 @#C1
-static set topLevelField(core::int #t30) → void {
+static set topLevelField(core::int topLevelField#param) → void {
   self::_#topLevelField#isSet = true;
-  self::_#topLevelField = #t30;
+  self::_#topLevelField = topLevelField#param;
 }
 @#C1
 static get finalTopLevelField() → core::int
-  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t31 = self::_#finalTopLevelField in #t31{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
+  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t20 = self::_#finalTopLevelField in #t20{core::int} : throw new _in::LateError::fieldNI("finalTopLevelField");
 @#C1
-static set finalTopLevelField(core::int #t32) → void
+static set finalTopLevelField(core::int finalTopLevelField#param) → void
   if(self::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     self::_#finalTopLevelField#isSet = true;
-    self::_#finalTopLevelField = #t32;
+    self::_#finalTopLevelField = finalTopLevelField#param;
   }
 @#C1
 static get finalTopLevelFieldWithInitializer() → core::int {
   if(!self::_#finalTopLevelFieldWithInitializer#isSet) {
-    final core::int #t33 = 0;
+    final core::int #t21 = 0;
     if(self::_#finalTopLevelFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalTopLevelFieldWithInitializer");
-    self::_#finalTopLevelFieldWithInitializer = #t33;
+    self::_#finalTopLevelFieldWithInitializer = #t21;
     self::_#finalTopLevelFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t34 = self::_#finalTopLevelFieldWithInitializer in #t34{core::int};
+  return let final core::int? #t22 = self::_#finalTopLevelFieldWithInitializer in #t22{core::int};
 }
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
+  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t23 = self::_#Extension|extensionStaticField in #t23{core::int} : throw new _in::LateError::fieldNI("extensionStaticField");
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void {
+static set Extension|extensionStaticField(core::int Extension|extensionStaticField#param) → void {
   self::_#Extension|extensionStaticField#isSet = true;
-  self::_#Extension|extensionStaticField = #t36;
+  self::_#Extension|extensionStaticField = Extension|extensionStaticField#param;
 }
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
+  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t24 = self::_#Extension|finalExtensionStaticField in #t24{core::int} : throw new _in::LateError::fieldNI("finalExtensionStaticField");
 @#C1
-static set Extension|finalExtensionStaticField(core::int #t38) → void
+static set Extension|finalExtensionStaticField(core::int Extension|finalExtensionStaticField#param) → void
   if(self::_#Extension|finalExtensionStaticField#isSet)
     throw new _in::LateError::fieldAI("finalExtensionStaticField");
   else {
     self::_#Extension|finalExtensionStaticField#isSet = true;
-    self::_#Extension|finalExtensionStaticField = #t38;
+    self::_#Extension|finalExtensionStaticField = Extension|finalExtensionStaticField#param;
   }
 @#C1
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int {
   if(!self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet) {
-    final core::int #t39 = 0;
+    final core::int #t25 = 0;
     if(self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet)
       throw new _in::LateError::fieldADI("finalExtensionStaticFieldWithInitializer");
-    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t39;
+    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t25;
     self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet = true;
   }
-  return let final core::int? #t40 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t40{core::int};
+  return let final core::int? #t26 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t26{core::int};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.expect
index a356dda..8bd9eb6 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.expect
@@ -16,8 +16,8 @@
     ;
   get nonNullableInstanceField() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField}{core::int?} in #t1 == null ?{core::int} this.{self::A::_#A#nonNullableInstanceField} = 0 : #t1{core::int};
-  set nonNullableInstanceField(core::int #t2) → void
-    this.{self::A::_#A#nonNullableInstanceField} = #t2;
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void
+    this.{self::A::_#A#nonNullableInstanceField} = nonNullableInstanceField#param;
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}{core::bool}) {
       this.{self::A::_#A#nullableInstanceField} = self::method();
@@ -25,14 +25,14 @@
     }
     return this.{self::A::_#A#nullableInstanceField}{core::int?};
   }
-  set nullableInstanceField(core::int? #t3) → void {
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void {
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nullableInstanceField} = #t3;
+    this.{self::A::_#A#nullableInstanceField} = nullableInstanceField#param;
   }
   static get nonNullableStaticField() → core::int
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4 == null ?{core::int} self::A::_#nonNullableStaticField = 0 : #t4{core::int};
-  static set nonNullableStaticField(core::int #t5) → void
-    self::A::_#nonNullableStaticField = #t5;
+    return let final core::int? #t2 = self::A::_#nonNullableStaticField in #t2 == null ?{core::int} self::A::_#nonNullableStaticField = 0 : #t2{core::int};
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void
+    self::A::_#nonNullableStaticField = nonNullableStaticField#param;
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
       self::A::_#nullableStaticField = self::method();
@@ -40,9 +40,9 @@
     }
     return self::A::_#nullableStaticField;
   }
-  static set nullableStaticField(core::int? #t6) → void {
+  static set nullableStaticField(core::int? nullableStaticField#param) → void {
     self::A::_#nullableStaticField#isSet = true;
-    self::A::_#nullableStaticField = #t6;
+    self::A::_#nullableStaticField = nullableStaticField#param;
   }
 }
 class B extends self::A {
@@ -63,9 +63,9 @@
 static method method() → core::int?
   return null;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7 == null ?{core::int} self::_#nonNullableTopLevelField = 0 : #t7{core::int};
-static set nonNullableTopLevelField(core::int #t8) → void
-  self::_#nonNullableTopLevelField = #t8;
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3 == null ?{core::int} self::_#nonNullableTopLevelField = 0 : #t3{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     self::_#nullableTopLevelField = self::method();
@@ -73,8 +73,8 @@
   }
   return self::_#nullableTopLevelField;
 }
-static set nullableTopLevelField(core::int? #t9) → void {
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void {
   self::_#nullableTopLevelField#isSet = true;
-  self::_#nullableTopLevelField = #t9;
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.transformed.expect
index a356dda..8bd9eb6 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.strong.transformed.expect
@@ -16,8 +16,8 @@
     ;
   get nonNullableInstanceField() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField}{core::int?} in #t1 == null ?{core::int} this.{self::A::_#A#nonNullableInstanceField} = 0 : #t1{core::int};
-  set nonNullableInstanceField(core::int #t2) → void
-    this.{self::A::_#A#nonNullableInstanceField} = #t2;
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void
+    this.{self::A::_#A#nonNullableInstanceField} = nonNullableInstanceField#param;
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}{core::bool}) {
       this.{self::A::_#A#nullableInstanceField} = self::method();
@@ -25,14 +25,14 @@
     }
     return this.{self::A::_#A#nullableInstanceField}{core::int?};
   }
-  set nullableInstanceField(core::int? #t3) → void {
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void {
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nullableInstanceField} = #t3;
+    this.{self::A::_#A#nullableInstanceField} = nullableInstanceField#param;
   }
   static get nonNullableStaticField() → core::int
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4 == null ?{core::int} self::A::_#nonNullableStaticField = 0 : #t4{core::int};
-  static set nonNullableStaticField(core::int #t5) → void
-    self::A::_#nonNullableStaticField = #t5;
+    return let final core::int? #t2 = self::A::_#nonNullableStaticField in #t2 == null ?{core::int} self::A::_#nonNullableStaticField = 0 : #t2{core::int};
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void
+    self::A::_#nonNullableStaticField = nonNullableStaticField#param;
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
       self::A::_#nullableStaticField = self::method();
@@ -40,9 +40,9 @@
     }
     return self::A::_#nullableStaticField;
   }
-  static set nullableStaticField(core::int? #t6) → void {
+  static set nullableStaticField(core::int? nullableStaticField#param) → void {
     self::A::_#nullableStaticField#isSet = true;
-    self::A::_#nullableStaticField = #t6;
+    self::A::_#nullableStaticField = nullableStaticField#param;
   }
 }
 class B extends self::A {
@@ -63,9 +63,9 @@
 static method method() → core::int?
   return null;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7 == null ?{core::int} self::_#nonNullableTopLevelField = 0 : #t7{core::int};
-static set nonNullableTopLevelField(core::int #t8) → void
-  self::_#nonNullableTopLevelField = #t8;
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3 == null ?{core::int} self::_#nonNullableTopLevelField = 0 : #t3{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     self::_#nullableTopLevelField = self::method();
@@ -73,8 +73,8 @@
   }
   return self::_#nullableTopLevelField;
 }
-static set nullableTopLevelField(core::int? #t9) → void {
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void {
   self::_#nullableTopLevelField#isSet = true;
-  self::_#nullableTopLevelField = #t9;
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
index bb1a104..8ea522d 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
@@ -21,9 +21,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField}{core::int?} in #t1{core::int};
   }
-  set nonNullableInstanceField(core::int #t2) → void {
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void {
     this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nonNullableInstanceField} = #t2;
+    this.{self::A::_#A#nonNullableInstanceField} = nonNullableInstanceField#param;
   }
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}{core::bool}) {
@@ -32,20 +32,20 @@
     }
     return this.{self::A::_#A#nullableInstanceField}{core::int?};
   }
-  set nullableInstanceField(core::int? #t3) → void {
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void {
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nullableInstanceField} = #t3;
+    this.{self::A::_#A#nullableInstanceField} = nullableInstanceField#param;
   }
   static get nonNullableStaticField() → core::int {
     if(!self::A::_#nonNullableStaticField#isSet) {
       self::A::_#nonNullableStaticField = 0;
       self::A::_#nonNullableStaticField#isSet = true;
     }
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4{core::int};
+    return let final core::int? #t2 = self::A::_#nonNullableStaticField in #t2{core::int};
   }
-  static set nonNullableStaticField(core::int #t5) → void {
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void {
     self::A::_#nonNullableStaticField#isSet = true;
-    self::A::_#nonNullableStaticField = #t5;
+    self::A::_#nonNullableStaticField = nonNullableStaticField#param;
   }
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
@@ -54,9 +54,9 @@
     }
     return self::A::_#nullableStaticField;
   }
-  static set nullableStaticField(core::int? #t6) → void {
+  static set nullableStaticField(core::int? nullableStaticField#param) → void {
     self::A::_#nullableStaticField#isSet = true;
-    self::A::_#nullableStaticField = #t6;
+    self::A::_#nullableStaticField = nullableStaticField#param;
   }
 }
 class B extends self::A {
@@ -81,11 +81,11 @@
     self::_#nonNullableTopLevelField = 0;
     self::_#nonNullableTopLevelField#isSet = true;
   }
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7{core::int};
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3{core::int};
 }
-static set nonNullableTopLevelField(core::int #t8) → void {
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void {
   self::_#nonNullableTopLevelField#isSet = true;
-  self::_#nonNullableTopLevelField = #t8;
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 }
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
@@ -94,8 +94,8 @@
   }
   return self::_#nullableTopLevelField;
 }
-static set nullableTopLevelField(core::int? #t9) → void {
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void {
   self::_#nullableTopLevelField#isSet = true;
-  self::_#nullableTopLevelField = #t9;
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.modular.expect
index bb1a104..8ea522d 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.modular.expect
@@ -21,9 +21,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField}{core::int?} in #t1{core::int};
   }
-  set nonNullableInstanceField(core::int #t2) → void {
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void {
     this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nonNullableInstanceField} = #t2;
+    this.{self::A::_#A#nonNullableInstanceField} = nonNullableInstanceField#param;
   }
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}{core::bool}) {
@@ -32,20 +32,20 @@
     }
     return this.{self::A::_#A#nullableInstanceField}{core::int?};
   }
-  set nullableInstanceField(core::int? #t3) → void {
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void {
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nullableInstanceField} = #t3;
+    this.{self::A::_#A#nullableInstanceField} = nullableInstanceField#param;
   }
   static get nonNullableStaticField() → core::int {
     if(!self::A::_#nonNullableStaticField#isSet) {
       self::A::_#nonNullableStaticField = 0;
       self::A::_#nonNullableStaticField#isSet = true;
     }
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4{core::int};
+    return let final core::int? #t2 = self::A::_#nonNullableStaticField in #t2{core::int};
   }
-  static set nonNullableStaticField(core::int #t5) → void {
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void {
     self::A::_#nonNullableStaticField#isSet = true;
-    self::A::_#nonNullableStaticField = #t5;
+    self::A::_#nonNullableStaticField = nonNullableStaticField#param;
   }
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
@@ -54,9 +54,9 @@
     }
     return self::A::_#nullableStaticField;
   }
-  static set nullableStaticField(core::int? #t6) → void {
+  static set nullableStaticField(core::int? nullableStaticField#param) → void {
     self::A::_#nullableStaticField#isSet = true;
-    self::A::_#nullableStaticField = #t6;
+    self::A::_#nullableStaticField = nullableStaticField#param;
   }
 }
 class B extends self::A {
@@ -81,11 +81,11 @@
     self::_#nonNullableTopLevelField = 0;
     self::_#nonNullableTopLevelField#isSet = true;
   }
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7{core::int};
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3{core::int};
 }
-static set nonNullableTopLevelField(core::int #t8) → void {
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void {
   self::_#nonNullableTopLevelField#isSet = true;
-  self::_#nonNullableTopLevelField = #t8;
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 }
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
@@ -94,8 +94,8 @@
   }
   return self::_#nullableTopLevelField;
 }
-static set nullableTopLevelField(core::int? #t9) → void {
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void {
   self::_#nullableTopLevelField#isSet = true;
-  self::_#nullableTopLevelField = #t9;
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.outline.expect
index 11774df..10c0fc6 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.outline.expect
@@ -14,13 +14,13 @@
   synthetic constructor •() → self::A
     ;
   get nonNullableInstanceField() → core::int;
-  set nonNullableInstanceField(core::int #t1) → void;
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void;
   get nullableInstanceField() → core::int?;
-  set nullableInstanceField(core::int? #t2) → void;
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void;
   static get nonNullableStaticField() → core::int;
-  static set nonNullableStaticField(core::int #t3) → void;
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void;
   static get nullableStaticField() → core::int?;
-  static set nullableStaticField(core::int? #t4) → void;
+  static set nullableStaticField(core::int? nullableStaticField#param) → void;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
@@ -41,8 +41,8 @@
 static method method() → core::int?
   ;
 static get nonNullableTopLevelField() → core::int;
-static set nonNullableTopLevelField(core::int #t5) → void;
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void;
 static get nullableTopLevelField() → core::int?;
-static set nullableTopLevelField(core::int? #t6) → void;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
index bb1a104..8ea522d 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
@@ -21,9 +21,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField}{core::int?} in #t1{core::int};
   }
-  set nonNullableInstanceField(core::int #t2) → void {
+  set nonNullableInstanceField(core::int nonNullableInstanceField#param) → void {
     this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nonNullableInstanceField} = #t2;
+    this.{self::A::_#A#nonNullableInstanceField} = nonNullableInstanceField#param;
   }
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}{core::bool}) {
@@ -32,20 +32,20 @@
     }
     return this.{self::A::_#A#nullableInstanceField}{core::int?};
   }
-  set nullableInstanceField(core::int? #t3) → void {
+  set nullableInstanceField(core::int? nullableInstanceField#param) → void {
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
-    this.{self::A::_#A#nullableInstanceField} = #t3;
+    this.{self::A::_#A#nullableInstanceField} = nullableInstanceField#param;
   }
   static get nonNullableStaticField() → core::int {
     if(!self::A::_#nonNullableStaticField#isSet) {
       self::A::_#nonNullableStaticField = 0;
       self::A::_#nonNullableStaticField#isSet = true;
     }
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4{core::int};
+    return let final core::int? #t2 = self::A::_#nonNullableStaticField in #t2{core::int};
   }
-  static set nonNullableStaticField(core::int #t5) → void {
+  static set nonNullableStaticField(core::int nonNullableStaticField#param) → void {
     self::A::_#nonNullableStaticField#isSet = true;
-    self::A::_#nonNullableStaticField = #t5;
+    self::A::_#nonNullableStaticField = nonNullableStaticField#param;
   }
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
@@ -54,9 +54,9 @@
     }
     return self::A::_#nullableStaticField;
   }
-  static set nullableStaticField(core::int? #t6) → void {
+  static set nullableStaticField(core::int? nullableStaticField#param) → void {
     self::A::_#nullableStaticField#isSet = true;
-    self::A::_#nullableStaticField = #t6;
+    self::A::_#nullableStaticField = nullableStaticField#param;
   }
 }
 class B extends self::A {
@@ -81,11 +81,11 @@
     self::_#nonNullableTopLevelField = 0;
     self::_#nonNullableTopLevelField#isSet = true;
   }
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7{core::int};
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3{core::int};
 }
-static set nonNullableTopLevelField(core::int #t8) → void {
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void {
   self::_#nonNullableTopLevelField#isSet = true;
-  self::_#nonNullableTopLevelField = #t8;
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 }
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
@@ -94,8 +94,8 @@
   }
   return self::_#nullableTopLevelField;
 }
-static set nullableTopLevelField(core::int? #t9) → void {
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void {
   self::_#nullableTopLevelField#isSet = true;
-  self::_#nullableTopLevelField = #t9;
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
index 7d0e4e3..da328ed 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
@@ -16,42 +16,42 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
-    self::Class::_#lateStaticField1 = #t2;
+  static set lateStaticField1(core::int lateStaticField1#param) → void
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
-    self::Class::_#lateStaticField2 = #t4;
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} self::Class::_#lateStaticField2 = 42 : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
     self::Class::lateStaticField2 = 43;
     self::expect(43, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     }
-    return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t7{self::Class::T%};
+    return let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t4{self::Class::T%};
   }
-  set lateGenericField1(covariant-by-class self::Class::T% #t8) → void {
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField1} = #t8;
+    this.{self::Class::_#Class#lateGenericField1} = lateGenericField1#param;
   }
   get lateGenericField2() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField2#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField2} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     }
-    return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t9{self::Class::T%};
+    return let final self::Class::T? #t5 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t5{self::Class::T%};
   }
-  set lateGenericField2(covariant-by-class self::Class::T% #t10) → void {
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField2} = #t10;
+    this.{self::Class::_#Class#lateGenericField2} = lateGenericField2#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int});
@@ -77,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11 == null ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
-static set lateTopLevelField1(core::int #t12) → void
-  self::_#lateTopLevelField1 = #t12;
+  return let final core::int? #t6 = self::_#lateTopLevelField1 in #t6 == null ?{core::int} self::_#lateTopLevelField1 = 123 : #t6{core::int};
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13 == null ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
-static set Extension|lateExtensionField1(core::int #t14) → void
-  self::_#Extension|lateExtensionField1 = #t14;
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField1 in #t7 == null ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t7{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15 == null ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
-static set Extension|lateExtensionField2(core::int #t16) → void
-  self::_#Extension|lateExtensionField2 = #t16;
+  return let final core::int? #t8 = self::_#Extension|lateExtensionField2 in #t8 == null ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t8{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
index 7d0e4e3..da328ed 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
@@ -16,42 +16,42 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
-    self::Class::_#lateStaticField1 = #t2;
+  static set lateStaticField1(core::int lateStaticField1#param) → void
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
-    self::Class::_#lateStaticField2 = #t4;
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} self::Class::_#lateStaticField2 = 42 : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
     self::Class::lateStaticField2 = 43;
     self::expect(43, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     }
-    return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t7{self::Class::T%};
+    return let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t4{self::Class::T%};
   }
-  set lateGenericField1(covariant-by-class self::Class::T% #t8) → void {
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField1} = #t8;
+    this.{self::Class::_#Class#lateGenericField1} = lateGenericField1#param;
   }
   get lateGenericField2() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField2#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField2} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     }
-    return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t9{self::Class::T%};
+    return let final self::Class::T? #t5 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t5{self::Class::T%};
   }
-  set lateGenericField2(covariant-by-class self::Class::T% #t10) → void {
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField2} = #t10;
+    this.{self::Class::_#Class#lateGenericField2} = lateGenericField2#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int});
@@ -77,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11 == null ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
-static set lateTopLevelField1(core::int #t12) → void
-  self::_#lateTopLevelField1 = #t12;
+  return let final core::int? #t6 = self::_#lateTopLevelField1 in #t6 == null ?{core::int} self::_#lateTopLevelField1 = 123 : #t6{core::int};
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13 == null ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
-static set Extension|lateExtensionField1(core::int #t14) → void
-  self::_#Extension|lateExtensionField1 = #t14;
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField1 in #t7 == null ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t7{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15 == null ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
-static set Extension|lateExtensionField2(core::int #t16) → void
-  self::_#Extension|lateExtensionField2 = #t16;
+  return let final core::int? #t8 = self::_#Extension|lateExtensionField2 in #t8 == null ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t8{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
index 8d1c620..5d41a8a 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
@@ -24,20 +24,20 @@
     }
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int};
   }
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int {
     if(!self::Class::_#lateStaticField2#isSet) {
       self::Class::_#lateStaticField2 = 42;
       self::Class::_#lateStaticField2#isSet = true;
     }
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int};
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int};
   }
-  static set lateStaticField2(core::int #t4) → void {
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -49,33 +49,33 @@
       this.{self::Class::_#Class#lateInstanceField} = 16;
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int};
   }
-  set lateInstanceField(core::int #t6) → void {
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     }
-    return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t7{self::Class::T%};
+    return let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t4{self::Class::T%};
   }
-  set lateGenericField1(covariant-by-class self::Class::T% #t8) → void {
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField1} = #t8;
+    this.{self::Class::_#Class#lateGenericField1} = lateGenericField1#param;
   }
   get lateGenericField2() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField2#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField2} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     }
-    return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t9{self::Class::T%};
+    return let final self::Class::T? #t5 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t5{self::Class::T%};
   }
-  set lateGenericField2(covariant-by-class self::Class::T% #t10) → void {
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField2} = #t10;
+    this.{self::Class::_#Class#lateGenericField2} = lateGenericField2#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int});
@@ -110,33 +110,33 @@
     self::_#lateTopLevelField1 = 123;
     self::_#lateTopLevelField1#isSet = true;
   }
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11{core::int};
+  return let final core::int? #t6 = self::_#lateTopLevelField1 in #t6{core::int};
 }
-static set lateTopLevelField1(core::int #t12) → void {
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t12;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static get Extension|lateExtensionField1() → core::int {
   if(!self::_#Extension|lateExtensionField1#isSet) {
     self::_#Extension|lateExtensionField1 = 87;
     self::_#Extension|lateExtensionField1#isSet = true;
   }
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField1 in #t7{core::int};
 }
-static set Extension|lateExtensionField1(core::int #t14) → void {
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t14;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int {
   if(!self::_#Extension|lateExtensionField2#isSet) {
     self::_#Extension|lateExtensionField2 = 42;
     self::_#Extension|lateExtensionField2#isSet = true;
   }
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15{core::int};
+  return let final core::int? #t8 = self::_#Extension|lateExtensionField2 in #t8{core::int};
 }
-static set Extension|lateExtensionField2(core::int #t16) → void {
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t16;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.modular.expect
index 8d1c620..5d41a8a 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.modular.expect
@@ -24,20 +24,20 @@
     }
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int};
   }
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int {
     if(!self::Class::_#lateStaticField2#isSet) {
       self::Class::_#lateStaticField2 = 42;
       self::Class::_#lateStaticField2#isSet = true;
     }
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int};
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int};
   }
-  static set lateStaticField2(core::int #t4) → void {
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -49,33 +49,33 @@
       this.{self::Class::_#Class#lateInstanceField} = 16;
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int};
   }
-  set lateInstanceField(core::int #t6) → void {
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     }
-    return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t7{self::Class::T%};
+    return let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t4{self::Class::T%};
   }
-  set lateGenericField1(covariant-by-class self::Class::T% #t8) → void {
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField1} = #t8;
+    this.{self::Class::_#Class#lateGenericField1} = lateGenericField1#param;
   }
   get lateGenericField2() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField2#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField2} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     }
-    return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t9{self::Class::T%};
+    return let final self::Class::T? #t5 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t5{self::Class::T%};
   }
-  set lateGenericField2(covariant-by-class self::Class::T% #t10) → void {
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField2} = #t10;
+    this.{self::Class::_#Class#lateGenericField2} = lateGenericField2#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int});
@@ -110,33 +110,33 @@
     self::_#lateTopLevelField1 = 123;
     self::_#lateTopLevelField1#isSet = true;
   }
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11{core::int};
+  return let final core::int? #t6 = self::_#lateTopLevelField1 in #t6{core::int};
 }
-static set lateTopLevelField1(core::int #t12) → void {
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t12;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static get Extension|lateExtensionField1() → core::int {
   if(!self::_#Extension|lateExtensionField1#isSet) {
     self::_#Extension|lateExtensionField1 = 87;
     self::_#Extension|lateExtensionField1#isSet = true;
   }
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField1 in #t7{core::int};
 }
-static set Extension|lateExtensionField1(core::int #t14) → void {
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t14;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int {
   if(!self::_#Extension|lateExtensionField2#isSet) {
     self::_#Extension|lateExtensionField2 = 42;
     self::_#Extension|lateExtensionField2#isSet = true;
   }
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15{core::int};
+  return let final core::int? #t8 = self::_#Extension|lateExtensionField2 in #t8{core::int};
 }
-static set Extension|lateExtensionField2(core::int #t16) → void {
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t16;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.outline.expect
index c20e857..d8734f1 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.outline.expect
@@ -17,17 +17,17 @@
   constructor •(self::Class::T% field) → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int;
-  static set lateStaticField1(core::int #t1) → void;
+  static set lateStaticField1(core::int lateStaticField1#param) → void;
   static get lateStaticField2() → core::int;
-  static set lateStaticField2(core::int #t2) → void;
+  static set lateStaticField2(core::int lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   get lateInstanceField() → core::int;
-  set lateInstanceField(core::int #t3) → void;
+  set lateInstanceField(core::int lateInstanceField#param) → void;
   get lateGenericField1() → self::Class::T%;
-  set lateGenericField1(covariant-by-class self::Class::T% #t4) → void;
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void;
   get lateGenericField2() → self::Class::T%;
-  set lateGenericField2(covariant-by-class self::Class::T% #t5) → void;
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void;
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic
     ;
 }
@@ -49,11 +49,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField1() → core::int;
-static set lateTopLevelField1(core::int #t6) → void;
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void;
 static get Extension|lateExtensionField1() → core::int;
-static set Extension|lateExtensionField1(core::int #t7) → void;
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void;
 static get Extension|lateExtensionField2() → core::int;
-static set Extension|lateExtensionField2(core::int #t8) → void;
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
index 8d1c620..5d41a8a 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
@@ -24,20 +24,20 @@
     }
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int};
   }
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int {
     if(!self::Class::_#lateStaticField2#isSet) {
       self::Class::_#lateStaticField2 = 42;
       self::Class::_#lateStaticField2#isSet = true;
     }
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int};
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int};
   }
-  static set lateStaticField2(core::int #t4) → void {
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -49,33 +49,33 @@
       this.{self::Class::_#Class#lateInstanceField} = 16;
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int};
   }
-  set lateInstanceField(core::int #t6) → void {
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     }
-    return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t7{self::Class::T%};
+    return let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericField1}{self::Class::T?} in #t4{self::Class::T%};
   }
-  set lateGenericField1(covariant-by-class self::Class::T% #t8) → void {
+  set lateGenericField1(covariant-by-class self::Class::T% lateGenericField1#param) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField1} = #t8;
+    this.{self::Class::_#Class#lateGenericField1} = lateGenericField1#param;
   }
   get lateGenericField2() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField2#isSet}{core::bool}) {
       this.{self::Class::_#Class#lateGenericField2} = this.{self::Class::field}{self::Class::T%};
       this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     }
-    return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t9{self::Class::T%};
+    return let final self::Class::T? #t5 = this.{self::Class::_#Class#lateGenericField2}{self::Class::T?} in #t5{self::Class::T%};
   }
-  set lateGenericField2(covariant-by-class self::Class::T% #t10) → void {
+  set lateGenericField2(covariant-by-class self::Class::T% lateGenericField2#param) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
-    this.{self::Class::_#Class#lateGenericField2} = #t10;
+    this.{self::Class::_#Class#lateGenericField2} = lateGenericField2#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int});
@@ -110,33 +110,33 @@
     self::_#lateTopLevelField1 = 123;
     self::_#lateTopLevelField1#isSet = true;
   }
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11{core::int};
+  return let final core::int? #t6 = self::_#lateTopLevelField1 in #t6{core::int};
 }
-static set lateTopLevelField1(core::int #t12) → void {
+static set lateTopLevelField1(core::int lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t12;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static get Extension|lateExtensionField1() → core::int {
   if(!self::_#Extension|lateExtensionField1#isSet) {
     self::_#Extension|lateExtensionField1 = 87;
     self::_#Extension|lateExtensionField1#isSet = true;
   }
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField1 in #t7{core::int};
 }
-static set Extension|lateExtensionField1(core::int #t14) → void {
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t14;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int {
   if(!self::_#Extension|lateExtensionField2#isSet) {
     self::_#Extension|lateExtensionField2 = 42;
     self::_#Extension|lateExtensionField2#isSet = true;
   }
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15{core::int};
+  return let final core::int? #t8 = self::_#Extension|lateExtensionField2 in #t8{core::int};
 }
-static set Extension|lateExtensionField2(core::int #t16) → void {
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t16;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
index 1483023..bb6521e 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -14,26 +14,26 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField1") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
-    self::Class::_#lateStaticField1 = #t2;
+  static set lateStaticField1(core::int lateStaticField1#param) → void
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
-    self::Class::_#lateStaticField2 = #t4;
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   get lateGenericInstanceField() → self::Class::T%
-    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t7{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t8) → void {
+    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t4{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -57,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t9 = self::_#lateTopLevelField in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t9{core::int};
-static set lateTopLevelField(core::int #t10) → void
-  self::_#lateTopLevelField = #t10;
+  return let final core::int? #t5 = self::_#lateTopLevelField in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t5{core::int};
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
+  self::_#lateTopLevelField = lateTopLevelField#param;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t11{core::int};
-static set Extension|lateExtensionField1(core::int #t12) → void
-  self::_#Extension|lateExtensionField1 = #t12;
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t6{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t13{core::int};
-static set Extension|lateExtensionField2(core::int #t14) → void
-  self::_#Extension|lateExtensionField2 = #t14;
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t7{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
index 1483023..bb6521e 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -14,26 +14,26 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField1") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
-    self::Class::_#lateStaticField1 = #t2;
+  static set lateStaticField1(core::int lateStaticField1#param) → void
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
-    self::Class::_#lateStaticField2 = #t4;
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   get lateGenericInstanceField() → self::Class::T%
-    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t7{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t8) → void {
+    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t4{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -57,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t9 = self::_#lateTopLevelField in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t9{core::int};
-static set lateTopLevelField(core::int #t10) → void
-  self::_#lateTopLevelField = #t10;
+  return let final core::int? #t5 = self::_#lateTopLevelField in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t5{core::int};
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
+  self::_#lateTopLevelField = lateTopLevelField#param;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t11{core::int};
-static set Extension|lateExtensionField1(core::int #t12) → void
-  self::_#Extension|lateExtensionField1 = #t12;
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t6{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t13{core::int};
-static set Extension|lateExtensionField2(core::int #t14) → void
-  self::_#Extension|lateExtensionField2 = #t14;
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t7{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index 9734ddb..57271db 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void {
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -33,16 +33,16 @@
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void {
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T%
-    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t7{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t8) → void {
+    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t4{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,22 +71,22 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t9 = self::_#lateTopLevelField in #t9{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t10) → void {
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t5 = self::_#lateTopLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t10;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t12) → void {
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t12;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t14) → void {
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t14;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.modular.expect
index 9734ddb..57271db 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.modular.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void {
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -33,16 +33,16 @@
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void {
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T%
-    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t7{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t8) → void {
+    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t4{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,22 +71,22 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t9 = self::_#lateTopLevelField in #t9{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t10) → void {
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t5 = self::_#lateTopLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t10;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t12) → void {
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t12;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t14) → void {
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t14;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.outline.expect
index b3cc2e8..808100e 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.outline.expect
@@ -14,15 +14,15 @@
   synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int;
-  static set lateStaticField1(core::int #t1) → void;
+  static set lateStaticField1(core::int lateStaticField1#param) → void;
   static get lateStaticField2() → core::int;
-  static set lateStaticField2(core::int #t2) → void;
+  static set lateStaticField2(core::int lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   get lateInstanceField() → core::int;
-  set lateInstanceField(core::int #t3) → void;
+  set lateInstanceField(core::int lateInstanceField#param) → void;
   get lateGenericInstanceField() → self::Class::T%;
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t4) → void;
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void;
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic
     ;
 }
@@ -44,11 +44,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int;
-static set lateTopLevelField(core::int #t5) → void;
+static set lateTopLevelField(core::int lateTopLevelField#param) → void;
 static get Extension|lateExtensionField1() → core::int;
-static set Extension|lateExtensionField1(core::int #t6) → void;
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void;
 static get Extension|lateExtensionField2() → core::int;
-static set Extension|lateExtensionField2(core::int #t7) → void;
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index 9734ddb..57271db 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void {
+  static set lateStaticField1(core::int lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t2;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void {
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t4;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -33,16 +33,16 @@
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void {
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t6;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T%
-    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t7{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T% #t8) → void {
+    return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T%} let final self::Class::T? #t4 = this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} in #t4{self::Class::T%} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
+  set lateGenericInstanceField(covariant-by-class self::Class::T% lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,22 +71,22 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t9 = self::_#lateTopLevelField in #t9{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t10) → void {
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t5 = self::_#lateTopLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t10;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t12) → void {
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t12;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t14) → void {
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t14;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
index a18219a..207a31e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
@@ -12,16 +12,16 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField1") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+  static set lateStaticField1(core::int lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1 == null)
-      self::Class::_#lateStaticField1 = #t2;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     else
       throw new _in::LateError::fieldAI("lateStaticField1");
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2 == null)
-      self::Class::_#lateStaticField2 = #t4;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     else
       throw new _in::LateError::fieldAI("lateStaticField2");
   static method staticMethod() → dynamic {
@@ -31,10 +31,10 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     else
       throw new _in::LateError::fieldAI("lateInstanceField");
   method instanceMethod() → dynamic {
@@ -57,24 +57,24 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
+  return let final core::int? #t4 = self::_#lateTopLevelField in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t4{core::int};
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
   if(self::_#lateTopLevelField == null)
-    self::_#lateTopLevelField = #t8;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("lateTopLevelField");
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
+  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t5{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1 == null)
-    self::_#Extension|lateExtensionField1 = #t10;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   else
     throw new _in::LateError::fieldAI("lateExtensionField1");
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t6{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2 == null)
-    self::_#Extension|lateExtensionField2 = #t12;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   else
     throw new _in::LateError::fieldAI("lateExtensionField2");
 static method Extension|staticMethod() → dynamic {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
index a18219a..207a31e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
@@ -12,16 +12,16 @@
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField1") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+  static set lateStaticField1(core::int lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1 == null)
-      self::Class::_#lateStaticField1 = #t2;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     else
       throw new _in::LateError::fieldAI("lateStaticField1");
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("lateStaticField2") : #t2{core::int};
+  static set lateStaticField2(core::int lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2 == null)
-      self::Class::_#lateStaticField2 = #t4;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     else
       throw new _in::LateError::fieldAI("lateStaticField2");
   static method staticMethod() → dynamic {
@@ -31,10 +31,10 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+    return let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("lateInstanceField") : #t3{core::int};
+  set lateInstanceField(core::int lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     else
       throw new _in::LateError::fieldAI("lateInstanceField");
   method instanceMethod() → dynamic {
@@ -57,24 +57,24 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
+  return let final core::int? #t4 = self::_#lateTopLevelField in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("lateTopLevelField") : #t4{core::int};
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
   if(self::_#lateTopLevelField == null)
-    self::_#lateTopLevelField = #t8;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("lateTopLevelField");
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
+  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField1") : #t5{core::int};
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1 == null)
-    self::_#Extension|lateExtensionField1 = #t10;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   else
     throw new _in::LateError::fieldAI("lateExtensionField1");
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("lateExtensionField2") : #t6{core::int};
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2 == null)
-    self::_#Extension|lateExtensionField2 = #t12;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   else
     throw new _in::LateError::fieldAI("lateExtensionField2");
 static method Extension|staticMethod() → dynamic {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
index f0429db..ab8252e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
@@ -15,21 +15,21 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void
+  static set lateStaticField1(core::int lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t2;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t4;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -38,13 +38,13 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   method instanceMethod() → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,31 +71,31 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t7 = self::_#lateTopLevelField in #t7{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t8) → void
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t4 = self::_#lateTopLevelField in #t4{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t8;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t10) → void
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t10;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t12) → void
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t12;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.modular.expect
index f0429db..ab8252e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.modular.expect
@@ -15,21 +15,21 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void
+  static set lateStaticField1(core::int lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t2;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t4;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -38,13 +38,13 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   method instanceMethod() → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,31 +71,31 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t7 = self::_#lateTopLevelField in #t7{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t8) → void
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t4 = self::_#lateTopLevelField in #t4{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t8;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t10) → void
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t10;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t12) → void
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t12;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.outline.expect
index bb9e392..3081907 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.outline.expect
@@ -12,13 +12,13 @@
   synthetic constructor •() → self::Class
     ;
   static get lateStaticField1() → core::int;
-  static set lateStaticField1(core::int #t1) → void;
+  static set lateStaticField1(core::int lateStaticField1#param) → void;
   static get lateStaticField2() → core::int;
-  static set lateStaticField2(core::int #t2) → void;
+  static set lateStaticField2(core::int lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   get lateInstanceField() → core::int;
-  set lateInstanceField(core::int #t3) → void;
+  set lateInstanceField(core::int lateInstanceField#param) → void;
   method instanceMethod() → dynamic
     ;
 }
@@ -40,11 +40,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int;
-static set lateTopLevelField(core::int #t4) → void;
+static set lateTopLevelField(core::int lateTopLevelField#param) → void;
 static get Extension|lateExtensionField1() → core::int;
-static set Extension|lateExtensionField1(core::int #t5) → void;
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void;
 static get Extension|lateExtensionField2() → core::int;
-static set Extension|lateExtensionField2(core::int #t6) → void;
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
index f0429db..ab8252e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
@@ -15,21 +15,21 @@
     ;
   static get lateStaticField1() → core::int
     return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int #t2) → void
+  static set lateStaticField1(core::int lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t2;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int
-    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int #t4) → void
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2{core::int} : throw new _in::LateError::fieldNI("lateStaticField2");
+  static set lateStaticField2(core::int lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t4;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -38,13 +38,13 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int #t6) → void
+    return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#lateInstanceField}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("lateInstanceField");
+  set lateInstanceField(core::int lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   method instanceMethod() → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}{core::int}, "Read value from uninitialized Class.lateInstanceField");
@@ -71,31 +71,31 @@
 static field core::int? _#Extension|lateExtensionField2 = null;
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t7 = self::_#lateTopLevelField in #t7{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int #t8) → void
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t4 = self::_#lateTopLevelField in #t4{core::int} : throw new _in::LateError::fieldNI("lateTopLevelField");
+static set lateTopLevelField(core::int lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t8;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int
-  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int #t10) → void
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5{core::int} : throw new _in::LateError::fieldNI("lateExtensionField1");
+static set Extension|lateExtensionField1(core::int Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t10;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int
-  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int #t12) → void
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6{core::int} : throw new _in::LateError::fieldNI("lateExtensionField2");
+static set Extension|lateExtensionField2(core::int Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t12;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
index fd2829a..e0a2558 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
@@ -8,9 +8,9 @@
   lowered final core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
     if(#lateLocal == null)
-      return #lateLocal = #t2;
+      return #lateLocal = lateLocal#param;
     else
       throw new _in::LateError::localAI("lateLocal");
   if(b) {
@@ -27,12 +27,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t3) → dynamic
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t3;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     if(b) {
       #lateGenericLocal#set(value){(T%) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
index fd2829a..e0a2558 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
@@ -8,9 +8,9 @@
   lowered final core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
     if(#lateLocal == null)
-      return #lateLocal = #t2;
+      return #lateLocal = lateLocal#param;
     else
       throw new _in::LateError::localAI("lateLocal");
   if(b) {
@@ -27,12 +27,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t3) → dynamic
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t3;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     if(b) {
       #lateGenericLocal#set(value){(T%) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
index 6050d9e..f62610a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
@@ -9,12 +9,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   if(b) {
     #lateLocal#set(123){(core::int) → dynamic};
@@ -30,12 +30,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     if(b) {
       #lateGenericLocal#set(value){(T%) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.modular.expect
index 6050d9e..f62610a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.modular.expect
@@ -9,12 +9,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   if(b) {
     #lateLocal#set(123){(core::int) → dynamic};
@@ -30,12 +30,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     if(b) {
       #lateGenericLocal#set(value){(T%) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
index 6050d9e..f62610a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
@@ -9,12 +9,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   if(b) {
     #lateLocal#set(123){(core::int) → dynamic};
@@ -30,12 +30,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     if(b) {
       #lateGenericLocal#set(value){(T%) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
index ce6ed76..fb2d8d3 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
@@ -17,21 +17,21 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void
+  static set lateStaticField1(core::int? lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t1;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void
+  static set lateStaticField2(core::int? lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t2;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -41,21 +41,21 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void
+  set lateInstanceField(core::int? lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t3;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(self::Class::T? #t4) → void
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void
     if(this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateGenericInstanceField");
     else {
       this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+      this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
     }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -87,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t5;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t6;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t7;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
index ce6ed76..fb2d8d3 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -17,21 +17,21 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void
+  static set lateStaticField1(core::int? lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t1;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void
+  static set lateStaticField2(core::int? lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t2;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -41,21 +41,21 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void
+  set lateInstanceField(core::int? lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t3;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(self::Class::T? #t4) → void
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void
     if(this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateGenericInstanceField");
     else {
       this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+      this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
     }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -87,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t5;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t6;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t7;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
index ce6ed76..fb2d8d3 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
@@ -17,21 +17,21 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void
+  static set lateStaticField1(core::int? lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t1;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void
+  static set lateStaticField2(core::int? lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t2;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -41,21 +41,21 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void
+  set lateInstanceField(core::int? lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t3;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(self::Class::T? #t4) → void
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void
     if(this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateGenericInstanceField");
     else {
       this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+      this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
     }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -87,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t5;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t6;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t7;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.modular.expect
index ce6ed76..fb2d8d3 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.modular.expect
@@ -17,21 +17,21 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void
+  static set lateStaticField1(core::int? lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t1;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void
+  static set lateStaticField2(core::int? lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t2;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -41,21 +41,21 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void
+  set lateInstanceField(core::int? lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t3;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(self::Class::T? #t4) → void
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void
     if(this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateGenericInstanceField");
     else {
       this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+      this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
     }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -87,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t5;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t6;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t7;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.outline.expect
index 86a7e1c..96a8d71 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.outline.expect
@@ -14,15 +14,15 @@
   synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int?;
-  static set lateStaticField1(core::int? #t1) → void;
+  static set lateStaticField1(core::int? lateStaticField1#param) → void;
   static get lateStaticField2() → core::int?;
-  static set lateStaticField2(core::int? #t2) → void;
+  static set lateStaticField2(core::int? lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   get lateInstanceField() → core::int?;
-  set lateInstanceField(core::int? #t3) → void;
+  set lateInstanceField(core::int? lateInstanceField#param) → void;
   get lateGenericInstanceField() → self::Class::T?;
-  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void;
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic
     ;
 }
@@ -44,11 +44,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int?;
-static set lateTopLevelField(core::int? #t5) → void;
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t6) → void;
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t7) → void;
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
index ce6ed76..fb2d8d3 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -17,21 +17,21 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void
+  static set lateStaticField1(core::int? lateStaticField1#param) → void
     if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateError::fieldAI("lateStaticField1");
     else {
       self::Class::_#lateStaticField1#isSet = true;
-      self::Class::_#lateStaticField1 = #t1;
+      self::Class::_#lateStaticField1 = lateStaticField1#param;
     }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void
+  static set lateStaticField2(core::int? lateStaticField2#param) → void
     if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateError::fieldAI("lateStaticField2");
     else {
       self::Class::_#lateStaticField2#isSet = true;
-      self::Class::_#lateStaticField2 = #t2;
+      self::Class::_#lateStaticField2 = lateStaticField2#param;
     }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -41,21 +41,21 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void
+  set lateInstanceField(core::int? lateInstanceField#param) → void
     if(this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateInstanceField");
     else {
       this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateInstanceField} = #t3;
+      this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
     }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(self::Class::T? #t4) → void
+  set lateGenericInstanceField(self::Class::T? lateGenericInstanceField#param) → void
     if(this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("lateGenericInstanceField");
     else {
       this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-      this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+      this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
     }
   method instanceMethod(covariant-by-class self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -87,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateError::fieldAI("lateTopLevelField");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t5;
+    self::_#lateTopLevelField = lateTopLevelField#param;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField1");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t6;
+    self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateError::fieldAI("lateExtensionField2");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t7;
+    self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
index 751ada1..e9350bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -8,12 +8,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
@@ -26,12 +26,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
index 0a5fece..b757dd2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -8,12 +8,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
@@ -26,12 +26,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
index 751ada1..e9350bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
@@ -8,12 +8,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
@@ -26,12 +26,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.modular.expect
index 751ada1..e9350bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.modular.expect
@@ -8,12 +8,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
@@ -26,12 +26,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
index 0a5fece..b757dd2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -8,12 +8,12 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic
     if(#lateLocal#isSet)
       throw new _in::LateError::localAI("lateLocal");
     else {
       #lateLocal#isSet = true;
-      return #lateLocal = #t1;
+      return #lateLocal = lateLocal#param;
     }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
@@ -26,12 +26,12 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateError::localAI("lateGenericLocal");
       else {
         #lateGenericLocal#isSet = true;
-        return #lateGenericLocal = #t2;
+        return #lateGenericLocal = lateGenericLocal#param;
       }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     if(1 =={core::num::==}{(core::Object) → core::bool} 1) {
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
index c7f8179..499cda4 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
@@ -21,74 +21,74 @@
     ;
   get field1() → FutureOr<dynamic>
     return this.{self::C::_#C#field1#isSet}{core::bool} ?{FutureOr<dynamic>} this.{self::C::_#C#field1}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field1");
-  set field1(FutureOr<dynamic>#t1) → void {
+  set field1(FutureOr<dynamic>field1#param) → void {
     this.{self::C::_#C#field1#isSet} = true;
-    this.{self::C::_#C#field1} = #t1;
+    this.{self::C::_#C#field1} = field1#param;
   }
   get field2() → FutureOr<dynamic>?
     return this.{self::C::_#C#field2#isSet}{core::bool} ?{FutureOr<dynamic>?} this.{self::C::_#C#field2}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field2");
-  set field2(FutureOr<dynamic>? #t2) → void {
+  set field2(FutureOr<dynamic>? field2#param) → void {
     this.{self::C::_#C#field2#isSet} = true;
-    this.{self::C::_#C#field2} = #t2;
+    this.{self::C::_#C#field2} = field2#param;
   }
   get field3() → FutureOr<self::C::T%>
-    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t3{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
-  set field3(covariant-by-class FutureOr<self::C::T%>#t4) → void {
+    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t1 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t1{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void {
     this.{self::C::_#C#field3#isSet} = true;
-    this.{self::C::_#C#field3} = #t4;
+    this.{self::C::_#C#field3} = field3#param;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet}{core::bool} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field4");
-  set field4(covariant-by-class FutureOr<self::C::T?>#t5) → void {
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void {
     this.{self::C::_#C#field4#isSet} = true;
-    this.{self::C::_#C#field4} = #t5;
+    this.{self::C::_#C#field4} = field4#param;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet}{core::bool} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field5");
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t6) → void {
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void {
     this.{self::C::_#C#field5#isSet} = true;
-    this.{self::C::_#C#field5} = #t6;
+    this.{self::C::_#C#field5} = field5#param;
   }
   method method() → dynamic {
     lowered FutureOr<dynamic>? #local1;
     lowered core::bool #local1#isSet = false;
     function #local1#get() → FutureOr<dynamic>
       return #local1#isSet ?{FutureOr<dynamic>} #local1 : throw new _in::LateError::localNI("local1");
-    function #local1#set(FutureOr<dynamic>#t7) → dynamic {
+    function #local1#set(FutureOr<dynamic>local1#param) → dynamic {
       #local1#isSet = true;
-      return #local1 = #t7;
+      return #local1 = local1#param;
     }
     lowered FutureOr<dynamic>? #local2;
     lowered core::bool #local2#isSet = false;
     function #local2#get() → FutureOr<dynamic>?
       return #local2#isSet ?{FutureOr<dynamic>?} #local2 : throw new _in::LateError::localNI("local2");
-    function #local2#set(FutureOr<dynamic>? #t8) → dynamic {
+    function #local2#set(FutureOr<dynamic>? local2#param) → dynamic {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
     lowered FutureOr<self::C::T%>? #local3;
     lowered core::bool #local3#isSet = false;
     function #local3#get() → FutureOr<self::C::T%>
       return #local3#isSet ?{FutureOr<self::C::T%>} #local3{FutureOr<self::C::T%>} : throw new _in::LateError::localNI("local3");
-    function #local3#set(FutureOr<self::C::T%>#t9) → dynamic {
+    function #local3#set(FutureOr<self::C::T%>local3#param) → dynamic {
       #local3#isSet = true;
-      return #local3 = #t9;
+      return #local3 = local3#param;
     }
     lowered FutureOr<self::C::T?>? #local4;
     lowered core::bool #local4#isSet = false;
     function #local4#get() → FutureOr<self::C::T?>
       return #local4#isSet ?{FutureOr<self::C::T?>} #local4 : throw new _in::LateError::localNI("local4");
-    function #local4#set(FutureOr<self::C::T?>#t10) → dynamic {
+    function #local4#set(FutureOr<self::C::T?>local4#param) → dynamic {
       #local4#isSet = true;
-      return #local4 = #t10;
+      return #local4 = local4#param;
     }
     lowered FutureOr<self::C::T?>? #local5;
     lowered core::bool #local5#isSet = false;
     function #local5#get() → FutureOr<self::C::T?>?
       return #local5#isSet ?{FutureOr<self::C::T?>?} #local5 : throw new _in::LateError::localNI("local5");
-    function #local5#set(FutureOr<self::C::T?>? #t11) → dynamic {
+    function #local5#set(FutureOr<self::C::T?>? local5#param) → dynamic {
       #local5#isSet = true;
-      return #local5 = #t11;
+      return #local5 = local5#param;
     }
   }
 }
@@ -123,9 +123,9 @@
   }
   return self::_#field1;
 }
-static set field1(FutureOr<dynamic>#t12) → void {
+static set field1(FutureOr<dynamic>field1#param) → void {
   self::_#field1#isSet = true;
-  self::_#field1 = #t12;
+  self::_#field1 = field1#param;
 }
 static get field2() → FutureOr<dynamic>? {
   if(!self::_#field2#isSet) {
@@ -134,9 +134,9 @@
   }
   return self::_#field2;
 }
-static set field2(FutureOr<dynamic>? #t13) → void {
+static set field2(FutureOr<dynamic>? field2#param) → void {
   self::_#field2#isSet = true;
-  self::_#field2 = #t13;
+  self::_#field2 = field2#param;
 }
 static get field3() → FutureOr<dynamic> {
   if(!self::_#field3#isSet) {
@@ -145,14 +145,14 @@
   }
   return self::_#field3;
 }
-static set field3(FutureOr<dynamic>#t14) → void {
+static set field3(FutureOr<dynamic>field3#param) → void {
   self::_#field3#isSet = true;
-  self::_#field3 = #t14;
+  self::_#field3 = field3#param;
 }
 static get field4() → FutureOr<core::int>
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15 == null ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t15{FutureOr<core::int>};
-static set field4(FutureOr<core::int>#t16) → void
-  self::_#field4 = #t16;
+  return let final FutureOr<core::int>? #t2 = self::_#field4 in #t2 == null ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t2{FutureOr<core::int>};
+static set field4(FutureOr<core::int>field4#param) → void
+  self::_#field4 = field4#param;
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
     self::_#field5 = self::method5();
@@ -160,9 +160,9 @@
   }
   return self::_#field5;
 }
-static set field5(FutureOr<core::int?>#t17) → void {
+static set field5(FutureOr<core::int?>field5#param) → void {
   self::_#field5#isSet = true;
-  self::_#field5 = #t17;
+  self::_#field5 = field5#param;
 }
 static get field6() → FutureOr<core::int?>? {
   if(!self::_#field6#isSet) {
@@ -171,8 +171,8 @@
   }
   return self::_#field6;
 }
-static set field6(FutureOr<core::int?>? #t18) → void {
+static set field6(FutureOr<core::int?>? field6#param) → void {
   self::_#field6#isSet = true;
-  self::_#field6 = #t18;
+  self::_#field6 = field6#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
index c7f8179..499cda4 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
@@ -21,74 +21,74 @@
     ;
   get field1() → FutureOr<dynamic>
     return this.{self::C::_#C#field1#isSet}{core::bool} ?{FutureOr<dynamic>} this.{self::C::_#C#field1}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field1");
-  set field1(FutureOr<dynamic>#t1) → void {
+  set field1(FutureOr<dynamic>field1#param) → void {
     this.{self::C::_#C#field1#isSet} = true;
-    this.{self::C::_#C#field1} = #t1;
+    this.{self::C::_#C#field1} = field1#param;
   }
   get field2() → FutureOr<dynamic>?
     return this.{self::C::_#C#field2#isSet}{core::bool} ?{FutureOr<dynamic>?} this.{self::C::_#C#field2}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field2");
-  set field2(FutureOr<dynamic>? #t2) → void {
+  set field2(FutureOr<dynamic>? field2#param) → void {
     this.{self::C::_#C#field2#isSet} = true;
-    this.{self::C::_#C#field2} = #t2;
+    this.{self::C::_#C#field2} = field2#param;
   }
   get field3() → FutureOr<self::C::T%>
-    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t3{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
-  set field3(covariant-by-class FutureOr<self::C::T%>#t4) → void {
+    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t1 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t1{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void {
     this.{self::C::_#C#field3#isSet} = true;
-    this.{self::C::_#C#field3} = #t4;
+    this.{self::C::_#C#field3} = field3#param;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet}{core::bool} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field4");
-  set field4(covariant-by-class FutureOr<self::C::T?>#t5) → void {
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void {
     this.{self::C::_#C#field4#isSet} = true;
-    this.{self::C::_#C#field4} = #t5;
+    this.{self::C::_#C#field4} = field4#param;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet}{core::bool} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field5");
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t6) → void {
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void {
     this.{self::C::_#C#field5#isSet} = true;
-    this.{self::C::_#C#field5} = #t6;
+    this.{self::C::_#C#field5} = field5#param;
   }
   method method() → dynamic {
     lowered FutureOr<dynamic>? #local1;
     lowered core::bool #local1#isSet = false;
     function #local1#get() → FutureOr<dynamic>
       return #local1#isSet ?{FutureOr<dynamic>} #local1 : throw new _in::LateError::localNI("local1");
-    function #local1#set(FutureOr<dynamic>#t7) → dynamic {
+    function #local1#set(FutureOr<dynamic>local1#param) → dynamic {
       #local1#isSet = true;
-      return #local1 = #t7;
+      return #local1 = local1#param;
     }
     lowered FutureOr<dynamic>? #local2;
     lowered core::bool #local2#isSet = false;
     function #local2#get() → FutureOr<dynamic>?
       return #local2#isSet ?{FutureOr<dynamic>?} #local2 : throw new _in::LateError::localNI("local2");
-    function #local2#set(FutureOr<dynamic>? #t8) → dynamic {
+    function #local2#set(FutureOr<dynamic>? local2#param) → dynamic {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
     lowered FutureOr<self::C::T%>? #local3;
     lowered core::bool #local3#isSet = false;
     function #local3#get() → FutureOr<self::C::T%>
       return #local3#isSet ?{FutureOr<self::C::T%>} #local3{FutureOr<self::C::T%>} : throw new _in::LateError::localNI("local3");
-    function #local3#set(FutureOr<self::C::T%>#t9) → dynamic {
+    function #local3#set(FutureOr<self::C::T%>local3#param) → dynamic {
       #local3#isSet = true;
-      return #local3 = #t9;
+      return #local3 = local3#param;
     }
     lowered FutureOr<self::C::T?>? #local4;
     lowered core::bool #local4#isSet = false;
     function #local4#get() → FutureOr<self::C::T?>
       return #local4#isSet ?{FutureOr<self::C::T?>} #local4 : throw new _in::LateError::localNI("local4");
-    function #local4#set(FutureOr<self::C::T?>#t10) → dynamic {
+    function #local4#set(FutureOr<self::C::T?>local4#param) → dynamic {
       #local4#isSet = true;
-      return #local4 = #t10;
+      return #local4 = local4#param;
     }
     lowered FutureOr<self::C::T?>? #local5;
     lowered core::bool #local5#isSet = false;
     function #local5#get() → FutureOr<self::C::T?>?
       return #local5#isSet ?{FutureOr<self::C::T?>?} #local5 : throw new _in::LateError::localNI("local5");
-    function #local5#set(FutureOr<self::C::T?>? #t11) → dynamic {
+    function #local5#set(FutureOr<self::C::T?>? local5#param) → dynamic {
       #local5#isSet = true;
-      return #local5 = #t11;
+      return #local5 = local5#param;
     }
   }
 }
@@ -123,9 +123,9 @@
   }
   return self::_#field1;
 }
-static set field1(FutureOr<dynamic>#t12) → void {
+static set field1(FutureOr<dynamic>field1#param) → void {
   self::_#field1#isSet = true;
-  self::_#field1 = #t12;
+  self::_#field1 = field1#param;
 }
 static get field2() → FutureOr<dynamic>? {
   if(!self::_#field2#isSet) {
@@ -134,9 +134,9 @@
   }
   return self::_#field2;
 }
-static set field2(FutureOr<dynamic>? #t13) → void {
+static set field2(FutureOr<dynamic>? field2#param) → void {
   self::_#field2#isSet = true;
-  self::_#field2 = #t13;
+  self::_#field2 = field2#param;
 }
 static get field3() → FutureOr<dynamic> {
   if(!self::_#field3#isSet) {
@@ -145,14 +145,14 @@
   }
   return self::_#field3;
 }
-static set field3(FutureOr<dynamic>#t14) → void {
+static set field3(FutureOr<dynamic>field3#param) → void {
   self::_#field3#isSet = true;
-  self::_#field3 = #t14;
+  self::_#field3 = field3#param;
 }
 static get field4() → FutureOr<core::int>
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15 == null ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t15{FutureOr<core::int>};
-static set field4(FutureOr<core::int>#t16) → void
-  self::_#field4 = #t16;
+  return let final FutureOr<core::int>? #t2 = self::_#field4 in #t2 == null ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t2{FutureOr<core::int>};
+static set field4(FutureOr<core::int>field4#param) → void
+  self::_#field4 = field4#param;
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
     self::_#field5 = self::method5();
@@ -160,9 +160,9 @@
   }
   return self::_#field5;
 }
-static set field5(FutureOr<core::int?>#t17) → void {
+static set field5(FutureOr<core::int?>field5#param) → void {
   self::_#field5#isSet = true;
-  self::_#field5 = #t17;
+  self::_#field5 = field5#param;
 }
 static get field6() → FutureOr<core::int?>? {
   if(!self::_#field6#isSet) {
@@ -171,8 +171,8 @@
   }
   return self::_#field6;
 }
-static set field6(FutureOr<core::int?>? #t18) → void {
+static set field6(FutureOr<core::int?>? field6#param) → void {
   self::_#field6#isSet = true;
-  self::_#field6 = #t18;
+  self::_#field6 = field6#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
index b358ead..24faada 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
@@ -21,74 +21,74 @@
     ;
   get field1() → FutureOr<dynamic>
     return this.{self::C::_#C#field1#isSet}{core::bool} ?{FutureOr<dynamic>} this.{self::C::_#C#field1}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field1");
-  set field1(FutureOr<dynamic>#t1) → void {
+  set field1(FutureOr<dynamic>field1#param) → void {
     this.{self::C::_#C#field1#isSet} = true;
-    this.{self::C::_#C#field1} = #t1;
+    this.{self::C::_#C#field1} = field1#param;
   }
   get field2() → FutureOr<dynamic>?
     return this.{self::C::_#C#field2#isSet}{core::bool} ?{FutureOr<dynamic>?} this.{self::C::_#C#field2}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field2");
-  set field2(FutureOr<dynamic>? #t2) → void {
+  set field2(FutureOr<dynamic>? field2#param) → void {
     this.{self::C::_#C#field2#isSet} = true;
-    this.{self::C::_#C#field2} = #t2;
+    this.{self::C::_#C#field2} = field2#param;
   }
   get field3() → FutureOr<self::C::T%>
-    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t3{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
-  set field3(covariant-by-class FutureOr<self::C::T%>#t4) → void {
+    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t1 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t1{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void {
     this.{self::C::_#C#field3#isSet} = true;
-    this.{self::C::_#C#field3} = #t4;
+    this.{self::C::_#C#field3} = field3#param;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet}{core::bool} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field4");
-  set field4(covariant-by-class FutureOr<self::C::T?>#t5) → void {
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void {
     this.{self::C::_#C#field4#isSet} = true;
-    this.{self::C::_#C#field4} = #t5;
+    this.{self::C::_#C#field4} = field4#param;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet}{core::bool} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field5");
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t6) → void {
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void {
     this.{self::C::_#C#field5#isSet} = true;
-    this.{self::C::_#C#field5} = #t6;
+    this.{self::C::_#C#field5} = field5#param;
   }
   method method() → dynamic {
     lowered FutureOr<dynamic>? #local1;
     lowered core::bool #local1#isSet = false;
     function #local1#get() → FutureOr<dynamic>
       return #local1#isSet ?{FutureOr<dynamic>} #local1 : throw new _in::LateError::localNI("local1");
-    function #local1#set(FutureOr<dynamic>#t7) → dynamic {
+    function #local1#set(FutureOr<dynamic>local1#param) → dynamic {
       #local1#isSet = true;
-      return #local1 = #t7;
+      return #local1 = local1#param;
     }
     lowered FutureOr<dynamic>? #local2;
     lowered core::bool #local2#isSet = false;
     function #local2#get() → FutureOr<dynamic>?
       return #local2#isSet ?{FutureOr<dynamic>?} #local2 : throw new _in::LateError::localNI("local2");
-    function #local2#set(FutureOr<dynamic>? #t8) → dynamic {
+    function #local2#set(FutureOr<dynamic>? local2#param) → dynamic {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
     lowered FutureOr<self::C::T%>? #local3;
     lowered core::bool #local3#isSet = false;
     function #local3#get() → FutureOr<self::C::T%>
       return #local3#isSet ?{FutureOr<self::C::T%>} #local3{FutureOr<self::C::T%>} : throw new _in::LateError::localNI("local3");
-    function #local3#set(FutureOr<self::C::T%>#t9) → dynamic {
+    function #local3#set(FutureOr<self::C::T%>local3#param) → dynamic {
       #local3#isSet = true;
-      return #local3 = #t9;
+      return #local3 = local3#param;
     }
     lowered FutureOr<self::C::T?>? #local4;
     lowered core::bool #local4#isSet = false;
     function #local4#get() → FutureOr<self::C::T?>
       return #local4#isSet ?{FutureOr<self::C::T?>} #local4 : throw new _in::LateError::localNI("local4");
-    function #local4#set(FutureOr<self::C::T?>#t10) → dynamic {
+    function #local4#set(FutureOr<self::C::T?>local4#param) → dynamic {
       #local4#isSet = true;
-      return #local4 = #t10;
+      return #local4 = local4#param;
     }
     lowered FutureOr<self::C::T?>? #local5;
     lowered core::bool #local5#isSet = false;
     function #local5#get() → FutureOr<self::C::T?>?
       return #local5#isSet ?{FutureOr<self::C::T?>?} #local5 : throw new _in::LateError::localNI("local5");
-    function #local5#set(FutureOr<self::C::T?>? #t11) → dynamic {
+    function #local5#set(FutureOr<self::C::T?>? local5#param) → dynamic {
       #local5#isSet = true;
-      return #local5 = #t11;
+      return #local5 = local5#param;
     }
   }
 }
@@ -123,9 +123,9 @@
   }
   return self::_#field1;
 }
-static set field1(FutureOr<dynamic>#t12) → void {
+static set field1(FutureOr<dynamic>field1#param) → void {
   self::_#field1#isSet = true;
-  self::_#field1 = #t12;
+  self::_#field1 = field1#param;
 }
 static get field2() → FutureOr<dynamic>? {
   if(!self::_#field2#isSet) {
@@ -134,9 +134,9 @@
   }
   return self::_#field2;
 }
-static set field2(FutureOr<dynamic>? #t13) → void {
+static set field2(FutureOr<dynamic>? field2#param) → void {
   self::_#field2#isSet = true;
-  self::_#field2 = #t13;
+  self::_#field2 = field2#param;
 }
 static get field3() → FutureOr<dynamic> {
   if(!self::_#field3#isSet) {
@@ -145,20 +145,20 @@
   }
   return self::_#field3;
 }
-static set field3(FutureOr<dynamic>#t14) → void {
+static set field3(FutureOr<dynamic>field3#param) → void {
   self::_#field3#isSet = true;
-  self::_#field3 = #t14;
+  self::_#field3 = field3#param;
 }
 static get field4() → FutureOr<core::int> {
   if(!self::_#field4#isSet) {
     self::_#field4 = self::method4();
     self::_#field4#isSet = true;
   }
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15{FutureOr<core::int>};
+  return let final FutureOr<core::int>? #t2 = self::_#field4 in #t2{FutureOr<core::int>};
 }
-static set field4(FutureOr<core::int>#t16) → void {
+static set field4(FutureOr<core::int>field4#param) → void {
   self::_#field4#isSet = true;
-  self::_#field4 = #t16;
+  self::_#field4 = field4#param;
 }
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
@@ -167,9 +167,9 @@
   }
   return self::_#field5;
 }
-static set field5(FutureOr<core::int?>#t17) → void {
+static set field5(FutureOr<core::int?>field5#param) → void {
   self::_#field5#isSet = true;
-  self::_#field5 = #t17;
+  self::_#field5 = field5#param;
 }
 static get field6() → FutureOr<core::int?>? {
   if(!self::_#field6#isSet) {
@@ -178,8 +178,8 @@
   }
   return self::_#field6;
 }
-static set field6(FutureOr<core::int?>? #t18) → void {
+static set field6(FutureOr<core::int?>? field6#param) → void {
   self::_#field6#isSet = true;
-  self::_#field6 = #t18;
+  self::_#field6 = field6#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.modular.expect
index b358ead..24faada 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.modular.expect
@@ -21,74 +21,74 @@
     ;
   get field1() → FutureOr<dynamic>
     return this.{self::C::_#C#field1#isSet}{core::bool} ?{FutureOr<dynamic>} this.{self::C::_#C#field1}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field1");
-  set field1(FutureOr<dynamic>#t1) → void {
+  set field1(FutureOr<dynamic>field1#param) → void {
     this.{self::C::_#C#field1#isSet} = true;
-    this.{self::C::_#C#field1} = #t1;
+    this.{self::C::_#C#field1} = field1#param;
   }
   get field2() → FutureOr<dynamic>?
     return this.{self::C::_#C#field2#isSet}{core::bool} ?{FutureOr<dynamic>?} this.{self::C::_#C#field2}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field2");
-  set field2(FutureOr<dynamic>? #t2) → void {
+  set field2(FutureOr<dynamic>? field2#param) → void {
     this.{self::C::_#C#field2#isSet} = true;
-    this.{self::C::_#C#field2} = #t2;
+    this.{self::C::_#C#field2} = field2#param;
   }
   get field3() → FutureOr<self::C::T%>
-    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t3{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
-  set field3(covariant-by-class FutureOr<self::C::T%>#t4) → void {
+    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t1 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t1{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void {
     this.{self::C::_#C#field3#isSet} = true;
-    this.{self::C::_#C#field3} = #t4;
+    this.{self::C::_#C#field3} = field3#param;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet}{core::bool} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field4");
-  set field4(covariant-by-class FutureOr<self::C::T?>#t5) → void {
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void {
     this.{self::C::_#C#field4#isSet} = true;
-    this.{self::C::_#C#field4} = #t5;
+    this.{self::C::_#C#field4} = field4#param;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet}{core::bool} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field5");
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t6) → void {
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void {
     this.{self::C::_#C#field5#isSet} = true;
-    this.{self::C::_#C#field5} = #t6;
+    this.{self::C::_#C#field5} = field5#param;
   }
   method method() → dynamic {
     lowered FutureOr<dynamic>? #local1;
     lowered core::bool #local1#isSet = false;
     function #local1#get() → FutureOr<dynamic>
       return #local1#isSet ?{FutureOr<dynamic>} #local1 : throw new _in::LateError::localNI("local1");
-    function #local1#set(FutureOr<dynamic>#t7) → dynamic {
+    function #local1#set(FutureOr<dynamic>local1#param) → dynamic {
       #local1#isSet = true;
-      return #local1 = #t7;
+      return #local1 = local1#param;
     }
     lowered FutureOr<dynamic>? #local2;
     lowered core::bool #local2#isSet = false;
     function #local2#get() → FutureOr<dynamic>?
       return #local2#isSet ?{FutureOr<dynamic>?} #local2 : throw new _in::LateError::localNI("local2");
-    function #local2#set(FutureOr<dynamic>? #t8) → dynamic {
+    function #local2#set(FutureOr<dynamic>? local2#param) → dynamic {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
     lowered FutureOr<self::C::T%>? #local3;
     lowered core::bool #local3#isSet = false;
     function #local3#get() → FutureOr<self::C::T%>
       return #local3#isSet ?{FutureOr<self::C::T%>} #local3{FutureOr<self::C::T%>} : throw new _in::LateError::localNI("local3");
-    function #local3#set(FutureOr<self::C::T%>#t9) → dynamic {
+    function #local3#set(FutureOr<self::C::T%>local3#param) → dynamic {
       #local3#isSet = true;
-      return #local3 = #t9;
+      return #local3 = local3#param;
     }
     lowered FutureOr<self::C::T?>? #local4;
     lowered core::bool #local4#isSet = false;
     function #local4#get() → FutureOr<self::C::T?>
       return #local4#isSet ?{FutureOr<self::C::T?>} #local4 : throw new _in::LateError::localNI("local4");
-    function #local4#set(FutureOr<self::C::T?>#t10) → dynamic {
+    function #local4#set(FutureOr<self::C::T?>local4#param) → dynamic {
       #local4#isSet = true;
-      return #local4 = #t10;
+      return #local4 = local4#param;
     }
     lowered FutureOr<self::C::T?>? #local5;
     lowered core::bool #local5#isSet = false;
     function #local5#get() → FutureOr<self::C::T?>?
       return #local5#isSet ?{FutureOr<self::C::T?>?} #local5 : throw new _in::LateError::localNI("local5");
-    function #local5#set(FutureOr<self::C::T?>? #t11) → dynamic {
+    function #local5#set(FutureOr<self::C::T?>? local5#param) → dynamic {
       #local5#isSet = true;
-      return #local5 = #t11;
+      return #local5 = local5#param;
     }
   }
 }
@@ -123,9 +123,9 @@
   }
   return self::_#field1;
 }
-static set field1(FutureOr<dynamic>#t12) → void {
+static set field1(FutureOr<dynamic>field1#param) → void {
   self::_#field1#isSet = true;
-  self::_#field1 = #t12;
+  self::_#field1 = field1#param;
 }
 static get field2() → FutureOr<dynamic>? {
   if(!self::_#field2#isSet) {
@@ -134,9 +134,9 @@
   }
   return self::_#field2;
 }
-static set field2(FutureOr<dynamic>? #t13) → void {
+static set field2(FutureOr<dynamic>? field2#param) → void {
   self::_#field2#isSet = true;
-  self::_#field2 = #t13;
+  self::_#field2 = field2#param;
 }
 static get field3() → FutureOr<dynamic> {
   if(!self::_#field3#isSet) {
@@ -145,20 +145,20 @@
   }
   return self::_#field3;
 }
-static set field3(FutureOr<dynamic>#t14) → void {
+static set field3(FutureOr<dynamic>field3#param) → void {
   self::_#field3#isSet = true;
-  self::_#field3 = #t14;
+  self::_#field3 = field3#param;
 }
 static get field4() → FutureOr<core::int> {
   if(!self::_#field4#isSet) {
     self::_#field4 = self::method4();
     self::_#field4#isSet = true;
   }
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15{FutureOr<core::int>};
+  return let final FutureOr<core::int>? #t2 = self::_#field4 in #t2{FutureOr<core::int>};
 }
-static set field4(FutureOr<core::int>#t16) → void {
+static set field4(FutureOr<core::int>field4#param) → void {
   self::_#field4#isSet = true;
-  self::_#field4 = #t16;
+  self::_#field4 = field4#param;
 }
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
@@ -167,9 +167,9 @@
   }
   return self::_#field5;
 }
-static set field5(FutureOr<core::int?>#t17) → void {
+static set field5(FutureOr<core::int?>field5#param) → void {
   self::_#field5#isSet = true;
-  self::_#field5 = #t17;
+  self::_#field5 = field5#param;
 }
 static get field6() → FutureOr<core::int?>? {
   if(!self::_#field6#isSet) {
@@ -178,8 +178,8 @@
   }
   return self::_#field6;
 }
-static set field6(FutureOr<core::int?>? #t18) → void {
+static set field6(FutureOr<core::int?>? field6#param) → void {
   self::_#field6#isSet = true;
-  self::_#field6 = #t18;
+  self::_#field6 = field6#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.outline.expect
index 6c197d9..27f5ef5 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.outline.expect
@@ -18,15 +18,15 @@
   synthetic constructor •() → self::C<self::C::T%>
     ;
   get field1() → FutureOr<dynamic>;
-  set field1(FutureOr<dynamic>#t1) → void;
+  set field1(FutureOr<dynamic>field1#param) → void;
   get field2() → FutureOr<dynamic>?;
-  set field2(FutureOr<dynamic>? #t2) → void;
+  set field2(FutureOr<dynamic>? field2#param) → void;
   get field3() → FutureOr<self::C::T%>;
-  set field3(covariant-by-class FutureOr<self::C::T%>#t3) → void;
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void;
   get field4() → FutureOr<self::C::T?>;
-  set field4(covariant-by-class FutureOr<self::C::T?>#t4) → void;
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void;
   get field5() → FutureOr<self::C::T?>?;
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t5) → void;
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void;
   method method() → dynamic
     ;
 }
@@ -55,16 +55,16 @@
 static method method6() → FutureOr<core::int?>?
   ;
 static get field1() → FutureOr<dynamic>;
-static set field1(FutureOr<dynamic>#t6) → void;
+static set field1(FutureOr<dynamic>field1#param) → void;
 static get field2() → FutureOr<dynamic>?;
-static set field2(FutureOr<dynamic>? #t7) → void;
+static set field2(FutureOr<dynamic>? field2#param) → void;
 static get field3() → FutureOr<dynamic>;
-static set field3(FutureOr<dynamic>#t8) → void;
+static set field3(FutureOr<dynamic>field3#param) → void;
 static get field4() → FutureOr<core::int>;
-static set field4(FutureOr<core::int>#t9) → void;
+static set field4(FutureOr<core::int>field4#param) → void;
 static get field5() → FutureOr<core::int?>;
-static set field5(FutureOr<core::int?>#t10) → void;
+static set field5(FutureOr<core::int?>field5#param) → void;
 static get field6() → FutureOr<core::int?>?;
-static set field6(FutureOr<core::int?>? #t11) → void;
+static set field6(FutureOr<core::int?>? field6#param) → void;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
index b358ead..24faada 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
@@ -21,74 +21,74 @@
     ;
   get field1() → FutureOr<dynamic>
     return this.{self::C::_#C#field1#isSet}{core::bool} ?{FutureOr<dynamic>} this.{self::C::_#C#field1}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field1");
-  set field1(FutureOr<dynamic>#t1) → void {
+  set field1(FutureOr<dynamic>field1#param) → void {
     this.{self::C::_#C#field1#isSet} = true;
-    this.{self::C::_#C#field1} = #t1;
+    this.{self::C::_#C#field1} = field1#param;
   }
   get field2() → FutureOr<dynamic>?
     return this.{self::C::_#C#field2#isSet}{core::bool} ?{FutureOr<dynamic>?} this.{self::C::_#C#field2}{FutureOr<dynamic>?} : throw new _in::LateError::fieldNI("field2");
-  set field2(FutureOr<dynamic>? #t2) → void {
+  set field2(FutureOr<dynamic>? field2#param) → void {
     this.{self::C::_#C#field2#isSet} = true;
-    this.{self::C::_#C#field2} = #t2;
+    this.{self::C::_#C#field2} = field2#param;
   }
   get field3() → FutureOr<self::C::T%>
-    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t3{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
-  set field3(covariant-by-class FutureOr<self::C::T%>#t4) → void {
+    return this.{self::C::_#C#field3#isSet}{core::bool} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t1 = this.{self::C::_#C#field3}{FutureOr<self::C::T%>?} in #t1{FutureOr<self::C::T%>} : throw new _in::LateError::fieldNI("field3");
+  set field3(covariant-by-class FutureOr<self::C::T%>field3#param) → void {
     this.{self::C::_#C#field3#isSet} = true;
-    this.{self::C::_#C#field3} = #t4;
+    this.{self::C::_#C#field3} = field3#param;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet}{core::bool} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field4");
-  set field4(covariant-by-class FutureOr<self::C::T?>#t5) → void {
+  set field4(covariant-by-class FutureOr<self::C::T?>field4#param) → void {
     this.{self::C::_#C#field4#isSet} = true;
-    this.{self::C::_#C#field4} = #t5;
+    this.{self::C::_#C#field4} = field4#param;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet}{core::bool} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5}{FutureOr<self::C::T?>?} : throw new _in::LateError::fieldNI("field5");
-  set field5(covariant-by-class FutureOr<self::C::T?>? #t6) → void {
+  set field5(covariant-by-class FutureOr<self::C::T?>? field5#param) → void {
     this.{self::C::_#C#field5#isSet} = true;
-    this.{self::C::_#C#field5} = #t6;
+    this.{self::C::_#C#field5} = field5#param;
   }
   method method() → dynamic {
     lowered FutureOr<dynamic>? #local1;
     lowered core::bool #local1#isSet = false;
     function #local1#get() → FutureOr<dynamic>
       return #local1#isSet ?{FutureOr<dynamic>} #local1 : throw new _in::LateError::localNI("local1");
-    function #local1#set(FutureOr<dynamic>#t7) → dynamic {
+    function #local1#set(FutureOr<dynamic>local1#param) → dynamic {
       #local1#isSet = true;
-      return #local1 = #t7;
+      return #local1 = local1#param;
     }
     lowered FutureOr<dynamic>? #local2;
     lowered core::bool #local2#isSet = false;
     function #local2#get() → FutureOr<dynamic>?
       return #local2#isSet ?{FutureOr<dynamic>?} #local2 : throw new _in::LateError::localNI("local2");
-    function #local2#set(FutureOr<dynamic>? #t8) → dynamic {
+    function #local2#set(FutureOr<dynamic>? local2#param) → dynamic {
       #local2#isSet = true;
-      return #local2 = #t8;
+      return #local2 = local2#param;
     }
     lowered FutureOr<self::C::T%>? #local3;
     lowered core::bool #local3#isSet = false;
     function #local3#get() → FutureOr<self::C::T%>
       return #local3#isSet ?{FutureOr<self::C::T%>} #local3{FutureOr<self::C::T%>} : throw new _in::LateError::localNI("local3");
-    function #local3#set(FutureOr<self::C::T%>#t9) → dynamic {
+    function #local3#set(FutureOr<self::C::T%>local3#param) → dynamic {
       #local3#isSet = true;
-      return #local3 = #t9;
+      return #local3 = local3#param;
     }
     lowered FutureOr<self::C::T?>? #local4;
     lowered core::bool #local4#isSet = false;
     function #local4#get() → FutureOr<self::C::T?>
       return #local4#isSet ?{FutureOr<self::C::T?>} #local4 : throw new _in::LateError::localNI("local4");
-    function #local4#set(FutureOr<self::C::T?>#t10) → dynamic {
+    function #local4#set(FutureOr<self::C::T?>local4#param) → dynamic {
       #local4#isSet = true;
-      return #local4 = #t10;
+      return #local4 = local4#param;
     }
     lowered FutureOr<self::C::T?>? #local5;
     lowered core::bool #local5#isSet = false;
     function #local5#get() → FutureOr<self::C::T?>?
       return #local5#isSet ?{FutureOr<self::C::T?>?} #local5 : throw new _in::LateError::localNI("local5");
-    function #local5#set(FutureOr<self::C::T?>? #t11) → dynamic {
+    function #local5#set(FutureOr<self::C::T?>? local5#param) → dynamic {
       #local5#isSet = true;
-      return #local5 = #t11;
+      return #local5 = local5#param;
     }
   }
 }
@@ -123,9 +123,9 @@
   }
   return self::_#field1;
 }
-static set field1(FutureOr<dynamic>#t12) → void {
+static set field1(FutureOr<dynamic>field1#param) → void {
   self::_#field1#isSet = true;
-  self::_#field1 = #t12;
+  self::_#field1 = field1#param;
 }
 static get field2() → FutureOr<dynamic>? {
   if(!self::_#field2#isSet) {
@@ -134,9 +134,9 @@
   }
   return self::_#field2;
 }
-static set field2(FutureOr<dynamic>? #t13) → void {
+static set field2(FutureOr<dynamic>? field2#param) → void {
   self::_#field2#isSet = true;
-  self::_#field2 = #t13;
+  self::_#field2 = field2#param;
 }
 static get field3() → FutureOr<dynamic> {
   if(!self::_#field3#isSet) {
@@ -145,20 +145,20 @@
   }
   return self::_#field3;
 }
-static set field3(FutureOr<dynamic>#t14) → void {
+static set field3(FutureOr<dynamic>field3#param) → void {
   self::_#field3#isSet = true;
-  self::_#field3 = #t14;
+  self::_#field3 = field3#param;
 }
 static get field4() → FutureOr<core::int> {
   if(!self::_#field4#isSet) {
     self::_#field4 = self::method4();
     self::_#field4#isSet = true;
   }
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15{FutureOr<core::int>};
+  return let final FutureOr<core::int>? #t2 = self::_#field4 in #t2{FutureOr<core::int>};
 }
-static set field4(FutureOr<core::int>#t16) → void {
+static set field4(FutureOr<core::int>field4#param) → void {
   self::_#field4#isSet = true;
-  self::_#field4 = #t16;
+  self::_#field4 = field4#param;
 }
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
@@ -167,9 +167,9 @@
   }
   return self::_#field5;
 }
-static set field5(FutureOr<core::int?>#t17) → void {
+static set field5(FutureOr<core::int?>field5#param) → void {
   self::_#field5#isSet = true;
-  self::_#field5 = #t17;
+  self::_#field5 = field5#param;
 }
 static get field6() → FutureOr<core::int?>? {
   if(!self::_#field6#isSet) {
@@ -178,8 +178,8 @@
   }
   return self::_#field6;
 }
-static set field6(FutureOr<core::int?>? #t18) → void {
+static set field6(FutureOr<core::int?>? field6#param) → void {
   self::_#field6#isSet = true;
-  self::_#field6 = #t18;
+  self::_#field6 = field6#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
index 3e73dd7..5e8787e 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
@@ -6,8 +6,8 @@
   lowered core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} #lateLocal = 123 : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return #lateLocal = #t2;
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
+    return #lateLocal = lateLocal#param;
   self::expect(123, #lateLocal#get(){() → core::int});
   self::expect(124, #lateLocal#set(124){(core::int) → dynamic});
   self::expect(124, #lateLocal#get(){() → core::int});
@@ -21,9 +21,9 @@
       }
       return #lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t3;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T%});
     self::expect(value2, #lateGenericLocal#set(value2){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
index 3e73dd7..5e8787e 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
@@ -6,8 +6,8 @@
   lowered core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} #lateLocal = 123 : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return #lateLocal = #t2;
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
+    return #lateLocal = lateLocal#param;
   self::expect(123, #lateLocal#get(){() → core::int});
   self::expect(124, #lateLocal#set(124){(core::int) → dynamic});
   self::expect(124, #lateLocal#get(){() → core::int});
@@ -21,9 +21,9 @@
       }
       return #lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t3;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T%});
     self::expect(value2, #lateGenericLocal#set(value2){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
index caa8e52..50562b0 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
@@ -12,9 +12,9 @@
     }
     return #lateLocal{core::int};
   }
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int});
   self::expect(124, #lateLocal#set(124){(core::int) → dynamic});
@@ -29,9 +29,9 @@
       }
       return #lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T%});
     self::expect(value2, #lateGenericLocal#set(value2){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.modular.expect
index caa8e52..50562b0 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.modular.expect
@@ -12,9 +12,9 @@
     }
     return #lateLocal{core::int};
   }
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int});
   self::expect(124, #lateLocal#set(124){(core::int) → dynamic});
@@ -29,9 +29,9 @@
       }
       return #lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T%});
     self::expect(value2, #lateGenericLocal#set(value2){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
index caa8e52..50562b0 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
@@ -12,9 +12,9 @@
     }
     return #lateLocal{core::int};
   }
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int});
   self::expect(124, #lateLocal#set(124){(core::int) → dynamic});
@@ -29,9 +29,9 @@
       }
       return #lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T%});
     self::expect(value2, #lateGenericLocal#set(value2){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
index 9b91555..d867d13 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
@@ -7,8 +7,8 @@
   lowered core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return #lateLocal = #t2;
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
+    return #lateLocal = lateLocal#param;
   self::throws(() → core::int => #lateLocal#get(){() → core::int}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int) → dynamic});
   self::expect(123, #lateLocal#get(){() → core::int});
@@ -17,9 +17,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t3;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T% => #lateGenericLocal#get(){() → T%}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
index 9b91555..d867d13 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
@@ -7,8 +7,8 @@
   lowered core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1 == null ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return #lateLocal = #t2;
+  function #lateLocal#set(core::int lateLocal#param) → dynamic
+    return #lateLocal = lateLocal#param;
   self::throws(() → core::int => #lateLocal#get(){() → core::int}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int) → dynamic});
   self::expect(123, #lateLocal#get(){() → core::int});
@@ -17,9 +17,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t3;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T% => #lateGenericLocal#get(){() → T%}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
index c6c3b91..5bc0eca 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int => #lateLocal#get(){() → core::int}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T% => #lateGenericLocal#get(){() → T%}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.modular.expect
index c6c3b91..5bc0eca 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.modular.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int => #lateLocal#get(){() → core::int}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T% => #lateGenericLocal#get(){() → T%}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
index c6c3b91..5bc0eca 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
     return #lateLocal#isSet ?{core::int} #lateLocal{core::int} : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int #t1) → dynamic {
+  function #lateLocal#set(core::int lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int => #lateLocal#get(){() → core::int}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} #lateGenericLocal{T%} : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T% #t2) → dynamic {
+    function #lateGenericLocal#set(T% lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T% => #lateGenericLocal#get(){() → T%}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T%) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
index 9cfa15f..fbb4ddc 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
@@ -17,38 +17,38 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField") : #t1{core::int};
-  static set uninitializedNonFinalStaticField(core::int #t2) → void
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   static get uninitializedFinalStaticField() → core::int
-    return let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t3{core::int};
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t2{core::int};
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField == null)
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
   static get initializedNonFinalStaticField() → core::int
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t5{core::int};
-  static set initializedNonFinalStaticField(core::int #t6) → void
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t3{core::int};
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   static get initializedFinalStaticField() → core::int
-    return let final core::int? #t7 = self::Class::_#initializedFinalStaticField in #t7 == null ?{core::int} let final core::int #t8 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t8 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t7{core::int};
+    return let final core::int? #t4 = self::Class::_#initializedFinalStaticField in #t4 == null ?{core::int} let final core::int #t5 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t5 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t4{core::int};
   get uninitializedNonFinalInstanceField() → core::int
-    return let final core::int? #t9 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField") : #t9{core::int};
-  set uninitializedNonFinalInstanceField(core::int #t10) → void
-    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = #t10;
+    return let final core::int? #t6 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField") : #t6{core::int};
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = uninitializedNonFinalInstanceField#param;
   get uninitializedFinalInstanceField() → core::int
-    return let final core::int? #t11 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t11{core::int};
-  set uninitializedFinalInstanceField(core::int #t12) → void
+    return let final core::int? #t7 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t7{core::int};
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t12;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
   get initializedNonFinalInstanceField() → core::int
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t13 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t13{core::int};
-  set initializedNonFinalInstanceField(core::int #t14) → void
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t14;
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t8 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t8{core::int};
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   get initializedFinalInstanceField() → core::int
-    return let final core::int? #t15 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t15 == null ?{core::int} let final core::int #t16 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t16 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t15{core::int};
+    return let final core::int? #t9 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t9 == null ?{core::int} let final core::int #t10 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t10 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t9{core::int};
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
 static field core::int? _#uninitializedFinalTopLevelField = null;
@@ -60,32 +60,32 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t17) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t17;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t18 = #nonNullableUninitializedNonFinalLocal in #t18 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t18{core::int};
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t19) → dynamic
-    return #nonNullableUninitializedNonFinalLocal = #t19;
+    return let final core::int? #t11 = #nonNullableUninitializedNonFinalLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t11{core::int};
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t20) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t20;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   function #nonNullableUninitializedFinalLocal#get() → core::int
-    return let final core::int? #t21 = #nonNullableUninitializedFinalLocal in #t21 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t21{core::int};
-  function #nonNullableUninitializedFinalLocal#set(core::int #t22) → dynamic
+    return let final core::int? #t12 = #nonNullableUninitializedFinalLocal in #t12 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t12{core::int};
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal == null)
-      return #nonNullableUninitializedFinalLocal = #t22;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
   lowered core::int? #nullableInitializedNonFinalLocal;
@@ -97,45 +97,45 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t23) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t23;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   function #nonNullableInitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t24 = #nonNullableInitializedNonFinalLocal in #t24 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t24{core::int};
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t25) → dynamic
-    return #nonNullableInitializedNonFinalLocal = #t25;
+    return let final core::int? #t13 = #nonNullableInitializedNonFinalLocal in #t13 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t13{core::int};
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t26 = 0;
+      final core::int? #t14 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t26;
+      #nullableInitializedFinalLocal = #t14;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
   }
   lowered final core::int? #nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t27 = #nonNullableInitializedFinalLocal in #t27 == null ?{core::int} let final core::int #t28 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t28 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t27{core::int};
+    return let final core::int? #t15 = #nonNullableInitializedFinalLocal in #t15 == null ?{core::int} let final core::int #t16 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t16 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t15{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedNonFinalTopLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t29{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t30) → void
-  self::_#uninitializedNonFinalTopLevelField = #t30;
+  return let final core::int? #t17 = self::_#uninitializedNonFinalTopLevelField in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t17{core::int};
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#uninitializedFinalTopLevelField in #t31 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t31{core::int};
-static set uninitializedFinalTopLevelField(core::int #t32) → void
+  return let final core::int? #t18 = self::_#uninitializedFinalTopLevelField in #t18 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t18{core::int};
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField == null)
-    self::_#uninitializedFinalTopLevelField = #t32;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedNonFinalTopLevelField in #t33 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t33{core::int};
-static set initializedNonFinalTopLevelField(core::int #t34) → void
-  self::_#initializedNonFinalTopLevelField = #t34;
+  return let final core::int? #t19 = self::_#initializedNonFinalTopLevelField in #t19 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t19{core::int};
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t35 = self::_#initializedFinalTopLevelField in #t35 == null ?{core::int} let final core::int #t36 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t36 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t35{core::int};
+  return let final core::int? #t20 = self::_#initializedFinalTopLevelField in #t20 == null ?{core::int} let final core::int #t21 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t21 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t20{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
index f35b5d9..a24db18 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
@@ -17,38 +17,38 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField") : #t1{core::int};
-  static set uninitializedNonFinalStaticField(core::int #t2) → void
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   static get uninitializedFinalStaticField() → core::int
-    return let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t3{core::int};
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t2{core::int};
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField == null)
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
   static get initializedNonFinalStaticField() → core::int
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t5{core::int};
-  static set initializedNonFinalStaticField(core::int #t6) → void
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t3{core::int};
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   static get initializedFinalStaticField() → core::int
-    return let final core::int? #t7 = self::Class::_#initializedFinalStaticField in #t7 == null ?{core::int} let final core::int #t8 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t8 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t7{core::int};
+    return let final core::int? #t4 = self::Class::_#initializedFinalStaticField in #t4 == null ?{core::int} let final core::int #t5 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t5 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t4{core::int};
   get uninitializedNonFinalInstanceField() → core::int
-    return let final core::int? #t9 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField") : #t9{core::int};
-  set uninitializedNonFinalInstanceField(core::int #t10) → void
-    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = #t10;
+    return let final core::int? #t6 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField") : #t6{core::int};
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = uninitializedNonFinalInstanceField#param;
   get uninitializedFinalInstanceField() → core::int
-    return let final core::int? #t11 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t11{core::int};
-  set uninitializedFinalInstanceField(core::int #t12) → void
+    return let final core::int? #t7 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t7{core::int};
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t12;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
   get initializedNonFinalInstanceField() → core::int
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t13 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t13{core::int};
-  set initializedNonFinalInstanceField(core::int #t14) → void
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t14;
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t8 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t8{core::int};
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   get initializedFinalInstanceField() → core::int
-    return let final core::int? #t15 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t15 == null ?{core::int} let final core::int #t16 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t16 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t15{core::int};
+    return let final core::int? #t9 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t9 == null ?{core::int} let final core::int #t10 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t10 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t9{core::int};
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
 static field core::int? _#uninitializedFinalTopLevelField = null;
@@ -60,32 +60,32 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t17) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t17;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t18 = #nonNullableUninitializedNonFinalLocal in #t18 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t18{core::int};
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t19) → dynamic
-    return #nonNullableUninitializedNonFinalLocal = #t19;
+    return let final core::int? #t11 = #nonNullableUninitializedNonFinalLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t11{core::int};
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t20) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t20;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   function #nonNullableUninitializedFinalLocal#get() → core::int
-    return let final core::int? #t21 = #nonNullableUninitializedFinalLocal in #t21 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t21{core::int};
-  function #nonNullableUninitializedFinalLocal#set(core::int #t22) → dynamic
+    return let final core::int? #t12 = #nonNullableUninitializedFinalLocal in #t12 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t12{core::int};
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal == null)
-      return #nonNullableUninitializedFinalLocal = #t22;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
   lowered core::int? #nullableInitializedNonFinalLocal;
@@ -97,48 +97,48 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t23) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t23;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   function #nonNullableInitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t24 = #nonNullableInitializedNonFinalLocal in #t24 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t24{core::int};
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t25) → dynamic
-    return #nonNullableInitializedNonFinalLocal = #t25;
+    return let final core::int? #t13 = #nonNullableInitializedNonFinalLocal in #t13 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t13{core::int};
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t26 = 0;
+      final core::int? #t14 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t26;
+      #nullableInitializedFinalLocal = #t14;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
   }
   lowered final core::int? #nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t27 = #nonNullableInitializedFinalLocal in #t27 == null ?{core::int} let final core::int #t28 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t28 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t27{core::int};
+    return let final core::int? #t15 = #nonNullableInitializedFinalLocal in #t15 == null ?{core::int} let final core::int #t16 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t16 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t15{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedNonFinalTopLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t29{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t30) → void
-  self::_#uninitializedNonFinalTopLevelField = #t30;
+  return let final core::int? #t17 = self::_#uninitializedNonFinalTopLevelField in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t17{core::int};
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#uninitializedFinalTopLevelField in #t31 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t31{core::int};
-static set uninitializedFinalTopLevelField(core::int #t32) → void
+  return let final core::int? #t18 = self::_#uninitializedFinalTopLevelField in #t18 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t18{core::int};
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField == null)
-    self::_#uninitializedFinalTopLevelField = #t32;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedNonFinalTopLevelField in #t33 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t33{core::int};
-static set initializedNonFinalTopLevelField(core::int #t34) → void
-  self::_#initializedNonFinalTopLevelField = #t34;
+  return let final core::int? #t19 = self::_#initializedNonFinalTopLevelField in #t19 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t19{core::int};
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t35 = self::_#initializedFinalTopLevelField in #t35 == null ?{core::int} let final core::int #t36 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t36 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t35{core::int};
+  return let final core::int? #t20 = self::_#initializedFinalTopLevelField in #t20 == null ?{core::int} let final core::int #t21 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t21 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t20{core::int};
 
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
index 4c7909a..c0e43bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
@@ -25,75 +25,75 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedNonFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
-  set uninitializedNonFinalInstanceField(core::int #t10) → void {
+    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = #t10;
+    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = uninitializedNonFinalInstanceField#param;
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t12) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t12;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t13{core::int};
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t8{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t14) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t14;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t9 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t15;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t9;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t16{core::int};
+    return let final core::int? #t10 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t10{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -110,39 +110,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t17) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t17;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t18) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t18;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t19) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t19;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t20) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t20;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -153,9 +153,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t21) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t21;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -166,18 +166,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t22) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t22;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t23 = 0;
+      final core::int? #t11 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t23;
+      #nullableInitializedFinalLocal = #t11;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -186,48 +186,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t24 = 0;
+      final core::int #t12 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t24;
+      #nonNullableInitializedFinalLocal = #t12;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t26) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedNonFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t26;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t28) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t14 = self::_#uninitializedFinalTopLevelField in #t14{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t28;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29{core::int};
+  return let final core::int? #t15 = self::_#initializedNonFinalTopLevelField in #t15{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t30) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t30;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t31 = 0;
+    final core::int #t16 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t31;
+    self::_#initializedFinalTopLevelField = #t16;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t32 = self::_#initializedFinalTopLevelField in #t32{core::int};
+  return let final core::int? #t17 = self::_#initializedFinalTopLevelField in #t17{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.modular.expect
index 4c7909a..c0e43bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.modular.expect
@@ -25,75 +25,75 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedNonFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
-  set uninitializedNonFinalInstanceField(core::int #t10) → void {
+    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = #t10;
+    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = uninitializedNonFinalInstanceField#param;
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t12) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t12;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t13{core::int};
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t8{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t14) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t14;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t9 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t15;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t9;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t16{core::int};
+    return let final core::int? #t10 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t10{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -110,39 +110,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t17) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t17;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t18) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t18;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t19) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t19;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t20) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t20;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -153,9 +153,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t21) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t21;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -166,18 +166,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t22) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t22;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t23 = 0;
+      final core::int? #t11 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t23;
+      #nullableInitializedFinalLocal = #t11;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -186,48 +186,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t24 = 0;
+      final core::int #t12 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t24;
+      #nonNullableInitializedFinalLocal = #t12;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t26) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedNonFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t26;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t28) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t14 = self::_#uninitializedFinalTopLevelField in #t14{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t28;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29{core::int};
+  return let final core::int? #t15 = self::_#initializedNonFinalTopLevelField in #t15{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t30) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t30;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t31 = 0;
+    final core::int #t16 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t31;
+    self::_#initializedFinalTopLevelField = #t16;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t32 = self::_#initializedFinalTopLevelField in #t32{core::int};
+  return let final core::int? #t17 = self::_#initializedFinalTopLevelField in #t17{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.outline.expect
index 45633bf..36bd60c 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.outline.expect
@@ -22,18 +22,18 @@
   synthetic constructor •() → self::Class
     ;
   static get uninitializedNonFinalStaticField() → core::int;
-  static set uninitializedNonFinalStaticField(core::int #t1) → void;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void;
   static get uninitializedFinalStaticField() → core::int;
-  static set uninitializedFinalStaticField(core::int #t2) → void;
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void;
   static get initializedNonFinalStaticField() → core::int;
-  static set initializedNonFinalStaticField(core::int #t3) → void;
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void;
   static get initializedFinalStaticField() → core::int;
   get uninitializedNonFinalInstanceField() → core::int;
-  set uninitializedNonFinalInstanceField(core::int #t4) → void;
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void;
   get uninitializedFinalInstanceField() → core::int;
-  set uninitializedFinalInstanceField(core::int #t5) → void;
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void;
   get initializedNonFinalInstanceField() → core::int;
-  set initializedNonFinalInstanceField(core::int #t6) → void;
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void;
   get initializedFinalInstanceField() → core::int;
 }
 static field core::int? _#uninitializedNonFinalTopLevelField;
@@ -49,9 +49,9 @@
 static method method() → dynamic
   ;
 static get uninitializedNonFinalTopLevelField() → core::int;
-static set uninitializedNonFinalTopLevelField(core::int #t7) → void;
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void;
 static get uninitializedFinalTopLevelField() → core::int;
-static set uninitializedFinalTopLevelField(core::int #t8) → void;
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void;
 static get initializedNonFinalTopLevelField() → core::int;
-static set initializedNonFinalTopLevelField(core::int #t9) → void;
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void;
 static get initializedFinalTopLevelField() → core::int;
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
index 4c7909a..c0e43bc 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
@@ -25,75 +25,75 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedNonFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
-  set uninitializedNonFinalInstanceField(core::int #t10) → void {
+    return this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedNonFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalInstanceField");
+  set uninitializedNonFinalInstanceField(core::int uninitializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#uninitializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = #t10;
+    this.{self::Class::_#Class#uninitializedNonFinalInstanceField} = uninitializedNonFinalInstanceField#param;
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t11 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t11{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t12) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t12;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t13{core::int};
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t8{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t14) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t14;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t9 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t15;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t9;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t16{core::int};
+    return let final core::int? #t10 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t10{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -110,39 +110,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t17) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t17;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t18) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t18;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t19) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t19;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t20) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t20;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -153,9 +153,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t21) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t21;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -166,18 +166,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t22) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t22;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t23 = 0;
+      final core::int? #t11 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t23;
+      #nullableInitializedFinalLocal = #t11;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -186,48 +186,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t24 = 0;
+      final core::int #t12 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t24;
+      #nonNullableInitializedFinalLocal = #t12;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t26) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedNonFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t26;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t28) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t14 = self::_#uninitializedFinalTopLevelField in #t14{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t28;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29{core::int};
+  return let final core::int? #t15 = self::_#initializedNonFinalTopLevelField in #t15{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t30) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t30;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t31 = 0;
+    final core::int #t16 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t31;
+    self::_#initializedFinalTopLevelField = #t16;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t32 = self::_#initializedFinalTopLevelField in #t32{core::int};
+  return let final core::int? #t17 = self::_#initializedFinalTopLevelField in #t17{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
index a743497..6af11b6 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
@@ -24,9 +24,9 @@
     }
     return self::Class::_#lateStaticField1;
   }
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static method lateStaticField2Init() → core::int?
     return 42;
@@ -37,9 +37,9 @@
     }
     return self::Class::_#lateStaticField2;
   }
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -55,9 +55,9 @@
     }
     return this.{self::Class::_#Class#lateInstanceField}{core::int?};
   }
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   method lateGenericInstanceFieldInit() → self::Class::T?
     return this.{self::Class::field}{self::Class::T?};
@@ -68,9 +68,9 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?};
   }
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int?});
@@ -109,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t5) → void {
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t5;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -122,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -135,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
index a743497..6af11b6 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -24,9 +24,9 @@
     }
     return self::Class::_#lateStaticField1;
   }
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static method lateStaticField2Init() → core::int?
     return 42;
@@ -37,9 +37,9 @@
     }
     return self::Class::_#lateStaticField2;
   }
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -55,9 +55,9 @@
     }
     return this.{self::Class::_#Class#lateInstanceField}{core::int?};
   }
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   method lateGenericInstanceFieldInit() → self::Class::T?
     return this.{self::Class::field}{self::Class::T?};
@@ -68,9 +68,9 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?};
   }
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int?});
@@ -109,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t5) → void {
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t5;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -122,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -135,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
index a743497..6af11b6 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
@@ -24,9 +24,9 @@
     }
     return self::Class::_#lateStaticField1;
   }
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static method lateStaticField2Init() → core::int?
     return 42;
@@ -37,9 +37,9 @@
     }
     return self::Class::_#lateStaticField2;
   }
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -55,9 +55,9 @@
     }
     return this.{self::Class::_#Class#lateInstanceField}{core::int?};
   }
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   method lateGenericInstanceFieldInit() → self::Class::T?
     return this.{self::Class::field}{self::Class::T?};
@@ -68,9 +68,9 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?};
   }
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int?});
@@ -109,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t5) → void {
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t5;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -122,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -135,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.modular.expect
index a743497..6af11b6 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.modular.expect
@@ -24,9 +24,9 @@
     }
     return self::Class::_#lateStaticField1;
   }
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static method lateStaticField2Init() → core::int?
     return 42;
@@ -37,9 +37,9 @@
     }
     return self::Class::_#lateStaticField2;
   }
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -55,9 +55,9 @@
     }
     return this.{self::Class::_#Class#lateInstanceField}{core::int?};
   }
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   method lateGenericInstanceFieldInit() → self::Class::T?
     return this.{self::Class::field}{self::Class::T?};
@@ -68,9 +68,9 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?};
   }
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int?});
@@ -109,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t5) → void {
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t5;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -122,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -135,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.outline.expect
index bf54c39..c2d9df2 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.outline.expect
@@ -17,21 +17,21 @@
   static method lateStaticField1Init() → core::int?
     ;
   static get lateStaticField1() → core::int?;
-  static set lateStaticField1(core::int? #t1) → void;
+  static set lateStaticField1(core::int? lateStaticField1#param) → void;
   static method lateStaticField2Init() → core::int?
     ;
   static get lateStaticField2() → core::int?;
-  static set lateStaticField2(core::int? #t2) → void;
+  static set lateStaticField2(core::int? lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   method lateInstanceFieldInit() → core::int?
     ;
   get lateInstanceField() → core::int?;
-  set lateInstanceField(core::int? #t3) → void;
+  set lateInstanceField(core::int? lateInstanceField#param) → void;
   method lateGenericInstanceFieldInit() → self::Class::T?
     ;
   get lateGenericInstanceField() → self::Class::T?;
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void;
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void;
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic
     ;
 }
@@ -57,15 +57,15 @@
 static method lateTopLevelField1Init() → core::int?
   ;
 static get lateTopLevelField1() → core::int?;
-static set lateTopLevelField1(core::int? #t5) → void;
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void;
 static method Extension|lateExtensionField1Init() → core::int?
   ;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t6) → void;
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void;
 static method Extension|lateExtensionField2Init() → core::int?
   ;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t7) → void;
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
index a743497..6af11b6 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -24,9 +24,9 @@
     }
     return self::Class::_#lateStaticField1;
   }
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static method lateStaticField2Init() → core::int?
     return 42;
@@ -37,9 +37,9 @@
     }
     return self::Class::_#lateStaticField2;
   }
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
@@ -55,9 +55,9 @@
     }
     return this.{self::Class::_#Class#lateInstanceField}{core::int?};
   }
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   method lateGenericInstanceFieldInit() → self::Class::T?
     return this.{self::Class::field}{self::Class::T?};
@@ -68,9 +68,9 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?};
   }
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField}{core::int?});
@@ -109,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t5) → void {
+static set lateTopLevelField1(core::int? lateTopLevelField1#param) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t5;
+  self::_#lateTopLevelField1 = lateTopLevelField1#param;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -122,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -135,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
index 91ed9ea..e2d2b39 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -34,15 +34,15 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -72,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void {
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t5;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
index 91ed9ea..e2d2b39 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -34,15 +34,15 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -72,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void {
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t5;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
index 91ed9ea..e2d2b39 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -34,15 +34,15 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -72,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void {
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t5;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.modular.expect
index 91ed9ea..e2d2b39 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.modular.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -34,15 +34,15 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -72,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void {
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t5;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.outline.expect
index f234077..daef161 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.outline.expect
@@ -14,15 +14,15 @@
   synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int?;
-  static set lateStaticField1(core::int? #t1) → void;
+  static set lateStaticField1(core::int? lateStaticField1#param) → void;
   static get lateStaticField2() → core::int?;
-  static set lateStaticField2(core::int? #t2) → void;
+  static set lateStaticField2(core::int? lateStaticField2#param) → void;
   static method staticMethod() → dynamic
     ;
   get lateInstanceField() → core::int?;
-  set lateInstanceField(core::int? #t3) → void;
+  set lateInstanceField(core::int? lateInstanceField#param) → void;
   get lateGenericInstanceField() → self::Class::T?;
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void;
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void;
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic
     ;
 }
@@ -44,11 +44,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int?;
-static set lateTopLevelField(core::int? #t5) → void;
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t6) → void;
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t7) → void;
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
index 91ed9ea..e2d2b39 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -17,15 +17,15 @@
     ;
   static get lateStaticField1() → core::int?
     return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw new _in::LateError::fieldNI("lateStaticField1");
-  static set lateStaticField1(core::int? #t1) → void {
+  static set lateStaticField1(core::int? lateStaticField1#param) → void {
     self::Class::_#lateStaticField1#isSet = true;
-    self::Class::_#lateStaticField1 = #t1;
+    self::Class::_#lateStaticField1 = lateStaticField1#param;
   }
   static get lateStaticField2() → core::int?
     return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw new _in::LateError::fieldNI("lateStaticField2");
-  static set lateStaticField2(core::int? #t2) → void {
+  static set lateStaticField2(core::int? lateStaticField2#param) → void {
     self::Class::_#lateStaticField2#isSet = true;
-    self::Class::_#lateStaticField2 = #t2;
+    self::Class::_#lateStaticField2 = lateStaticField2#param;
   }
   static method staticMethod() → dynamic {
     self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
@@ -34,15 +34,15 @@
   }
   get lateInstanceField() → core::int?
     return this.{self::Class::_#Class#lateInstanceField#isSet}{core::bool} ?{core::int?} this.{self::Class::_#Class#lateInstanceField}{core::int?} : throw new _in::LateError::fieldNI("lateInstanceField");
-  set lateInstanceField(core::int? #t3) → void {
+  set lateInstanceField(core::int? lateInstanceField#param) → void {
     this.{self::Class::_#Class#lateInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateInstanceField} = #t3;
+    this.{self::Class::_#Class#lateInstanceField} = lateInstanceField#param;
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet}{core::bool} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField}{self::Class::T?} : throw new _in::LateError::fieldNI("lateGenericInstanceField");
-  set lateGenericInstanceField(covariant-by-class self::Class::T? #t4) → void {
+  set lateGenericInstanceField(covariant-by-class self::Class::T? lateGenericInstanceField#param) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
-    this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
+    this.{self::Class::_#Class#lateGenericInstanceField} = lateGenericInstanceField#param;
   }
   method instanceMethod(covariant-by-class self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}{core::int?}, "Read value from uninitialized Class.lateInstanceField");
@@ -72,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateError::fieldNI("lateTopLevelField");
-static set lateTopLevelField(core::int? #t5) → void {
+static set lateTopLevelField(core::int? lateTopLevelField#param) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t5;
+  self::_#lateTopLevelField = lateTopLevelField#param;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateError::fieldNI("lateExtensionField1");
-static set Extension|lateExtensionField1(core::int? #t6) → void {
+static set Extension|lateExtensionField1(core::int? Extension|lateExtensionField1#param) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t6;
+  self::_#Extension|lateExtensionField1 = Extension|lateExtensionField1#param;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateError::fieldNI("lateExtensionField2");
-static set Extension|lateExtensionField2(core::int? #t7) → void {
+static set Extension|lateExtensionField2(core::int? Extension|lateExtensionField2#param) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t7;
+  self::_#Extension|lateExtensionField2 = Extension|lateExtensionField2#param;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
index a150002..a6e67a5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
@@ -14,9 +14,9 @@
     }
     return #lateLocal;
   }
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int?});
   self::expect(124, #lateLocal#set(124){(core::int?) → dynamic});
@@ -31,9 +31,9 @@
       }
       return #lateGenericLocal;
     }
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T?});
     self::expect(value2, #lateGenericLocal#set(value2){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
index a150002..a6e67a5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -14,9 +14,9 @@
     }
     return #lateLocal;
   }
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int?});
   self::expect(124, #lateLocal#set(124){(core::int?) → dynamic});
@@ -31,9 +31,9 @@
       }
       return #lateGenericLocal;
     }
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T?});
     self::expect(value2, #lateGenericLocal#set(value2){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
index a150002..a6e67a5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
@@ -14,9 +14,9 @@
     }
     return #lateLocal;
   }
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int?});
   self::expect(124, #lateLocal#set(124){(core::int?) → dynamic});
@@ -31,9 +31,9 @@
       }
       return #lateGenericLocal;
     }
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T?});
     self::expect(value2, #lateGenericLocal#set(value2){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.modular.expect
index a150002..a6e67a5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.modular.expect
@@ -14,9 +14,9 @@
     }
     return #lateLocal;
   }
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int?});
   self::expect(124, #lateLocal#set(124){(core::int?) → dynamic});
@@ -31,9 +31,9 @@
       }
       return #lateGenericLocal;
     }
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T?});
     self::expect(value2, #lateGenericLocal#set(value2){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
index a150002..a6e67a5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -14,9 +14,9 @@
     }
     return #lateLocal;
   }
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::expect(123, #lateLocal#get(){() → core::int?});
   self::expect(124, #lateLocal#set(124){(core::int?) → dynamic});
@@ -31,9 +31,9 @@
       }
       return #lateGenericLocal;
     }
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::expect(value1, #lateGenericLocal#get(){() → T?});
     self::expect(value2, #lateGenericLocal#set(value2){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
index 133710a..448e782 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int?) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
index 133710a..448e782 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int?) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
index 133710a..448e782 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int?) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.modular.expect
index 133710a..448e782 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.modular.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int?) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
index 133710a..448e782 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -8,9 +8,9 @@
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int?
     return #lateLocal#isSet ?{core::int?} #lateLocal : throw new _in::LateError::localNI("lateLocal");
-  function #lateLocal#set(core::int? #t1) → dynamic {
+  function #lateLocal#set(core::int? lateLocal#param) → dynamic {
     #lateLocal#isSet = true;
-    return #lateLocal = #t1;
+    return #lateLocal = lateLocal#param;
   }
   self::throws(() → core::int? => #lateLocal#get(){() → core::int?}, "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set(123){(core::int?) → dynamic});
@@ -20,9 +20,9 @@
     lowered core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T?
       return #lateGenericLocal#isSet ?{T?} #lateGenericLocal : throw new _in::LateError::localNI("lateGenericLocal");
-    function #lateGenericLocal#set(T? #t2) → dynamic {
+    function #lateGenericLocal#set(T? lateGenericLocal#param) → dynamic {
       #lateGenericLocal#isSet = true;
-      return #lateGenericLocal = #t2;
+      return #lateGenericLocal = lateGenericLocal#param;
     }
     self::throws(() → T? => #lateGenericLocal#get(){() → T?}, "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set(value){(T?) → dynamic});
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect
index cc41c15..e572bcb 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect
@@ -10,8 +10,8 @@
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int
     return let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter") : #t1{core::int};
-  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void
-    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = implementedLateFieldDeclaredGetterSetter#param;
 }
 class Class extends core::Object implements self::Interface {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect
index cc41c15..e572bcb 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int
     return let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter") : #t1{core::int};
-  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void
-    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = implementedLateFieldDeclaredGetterSetter#param;
 }
 class Class extends core::Object implements self::Interface {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect
index bb99080..4790393 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect
@@ -11,9 +11,9 @@
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int
     return this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter");
-  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void {
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void {
     this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} = true;
-    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = implementedLateFieldDeclaredGetterSetter#param;
   }
 }
 class Class extends core::Object implements self::Interface {
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.modular.expect
index bb99080..4790393 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.modular.expect
@@ -11,9 +11,9 @@
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int
     return this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter");
-  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void {
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void {
     this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} = true;
-    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = implementedLateFieldDeclaredGetterSetter#param;
   }
 }
 class Class extends core::Object implements self::Interface {
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.outline.expect
index 8d37f5d..fd5e6db 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.outline.expect
@@ -8,7 +8,7 @@
   synthetic constructor •() → self::Interface
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int;
-  set implementedLateFieldDeclaredGetterSetter(core::int #t1) → void;
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void;
 }
 class Class extends core::Object implements self::Interface {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect
index bb99080..4790393 100644
--- a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect
@@ -11,9 +11,9 @@
     ;
   get implementedLateFieldDeclaredGetterSetter() → core::int
     return this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter");
-  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void {
+  set implementedLateFieldDeclaredGetterSetter(core::int implementedLateFieldDeclaredGetterSetter#param) → void {
     this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} = true;
-    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = implementedLateFieldDeclaredGetterSetter#param;
   }
 }
 class Class extends core::Object implements self::Interface {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
index 20030f2..dac68ea 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -75,8 +75,8 @@
     ;
   get b() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#b}{core::int?} in #t1 == null ?{core::int} this.{self::A::_#A#b} = this.{self::A::a}{core::int}.{core::num::*}(2){(core::num) → core::int}.{core::int::>>}(1){(core::int) → core::int} : #t1{core::int};
-  set b(core::int #t2) → void
-    this.{self::A::_#A#b} = #t2;
+  set b(core::int b#param) → void
+    this.{self::A::_#A#b} = b#param;
   method foo(core::int x) → dynamic {}
 }
 class B extends core::Object /*hasConstConstructor*/  {
@@ -85,7 +85,7 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3 == null ?{core::int} let final core::int #t4 = 42 in this.{self::B::_#B#x}{core::int?} == null ?{core::int} this.{self::B::_#B#x} = #t4 : throw new _in::LateError::fieldADI("x") : #t3{core::int};
+    return let final core::int? #t2 = this.{self::B::_#B#x}{core::int?} in #t2 == null ?{core::int} let final core::int #t3 = 42 in this.{self::B::_#B#x}{core::int?} == null ?{core::int} this.{self::B::_#B#x} = #t3 : throw new _in::LateError::fieldADI("x") : #t2{core::int};
 }
 class C extends core::Object {
   field core::int? _#C#x = null;
@@ -93,10 +93,10 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t5{core::int};
-  set x(core::int #t6) → void
+    return let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t4{core::int};
+  set x(core::int x#param) → void
     if(this.{self::C::_#C#x}{core::int?} == null)
-      this.{self::C::_#C#x} = #t6;
+      this.{self::C::_#C#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
   method initVars() → dynamic {
@@ -125,10 +125,10 @@
     core::print(s);
   }
   block {
-    final core::List<core::int> #t7 = <core::int>[];
+    final core::List<core::int> #t5 = <core::int>[];
     for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
-      #t7.{core::List::add}{Invariant}(i){(core::int) → void};
-  } =>#t7;
+      #t5.{core::List::add}{Invariant}(i){(core::int) → void};
+  } =>#t5;
 }
 static method hest() → dynamic async {
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
@@ -139,23 +139,23 @@
 static method fisk() → dynamic async {
   lowered core::String? #s1;
   function #s1#get() → core::String
-    return let final core::String? #t8 = #s1 in #t8 == null ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t6 = #s1 in #t6 == null ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" : #t8{core::String};
-  function #s1#set(core::String #t9) → dynamic
-    return #s1 = #t9;
+                   ^^^^^" : #t6{core::String};
+  function #s1#set(core::String s1#param) → dynamic
+    return #s1 = s1#param;
   lowered core::String? #s2;
   function #s2#get() → core::String
-    return let final core::String? #t10 = #s2 in #t10 == null ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t7 = #s2 in #t7 == null ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t10{core::String};
-  function #s2#set(core::String #t11) → dynamic
-    return #s2 = #t11;
+                             ^^^^^"}${#C1}" : #t7{core::String};
+  function #s2#set(core::String s2#param) → dynamic
+    return #s2 = s2#param;
   lowered core::Function? #f;
   function #f#get() → core::Function
-    return let final core::Function? #t12 = #f in #t12 == null ?{core::Function} #f = () → asy::Future<dynamic> async => await self::hest() : #t12{core::Function};
-  function #f#set(core::Function #t13) → dynamic
-    return #f = #t13;
+    return let final core::Function? #t8 = #f in #t8 == null ?{core::Function} #f = () → asy::Future<dynamic> async => await self::hest() : #t8{core::Function};
+  function #f#set(core::Function f#param) → dynamic
+    return #f = f#param;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index d009196..079f495 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -75,8 +75,8 @@
     ;
   get b() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#b}{core::int?} in #t1 == null ?{core::int} this.{self::A::_#A#b} = this.{self::A::a}{core::int}.{core::num::*}(2){(core::num) → core::int}.{core::int::>>}(1){(core::int) → core::int} : #t1{core::int};
-  set b(core::int #t2) → void
-    this.{self::A::_#A#b} = #t2;
+  set b(core::int b#param) → void
+    this.{self::A::_#A#b} = b#param;
   method foo(core::int x) → dynamic {}
 }
 class B extends core::Object /*hasConstConstructor*/  {
@@ -85,7 +85,7 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3 == null ?{core::int} let final core::int #t4 = 42 in this.{self::B::_#B#x}{core::int?} == null ?{core::int} this.{self::B::_#B#x} = #t4 : throw new _in::LateError::fieldADI("x") : #t3{core::int};
+    return let final core::int? #t2 = this.{self::B::_#B#x}{core::int?} in #t2 == null ?{core::int} let final core::int #t3 = 42 in this.{self::B::_#B#x}{core::int?} == null ?{core::int} this.{self::B::_#B#x} = #t3 : throw new _in::LateError::fieldADI("x") : #t2{core::int};
 }
 class C extends core::Object {
   field core::int? _#C#x = null;
@@ -93,10 +93,10 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t5{core::int};
-  set x(core::int #t6) → void
+    return let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t4{core::int};
+  set x(core::int x#param) → void
     if(this.{self::C::_#C#x}{core::int?} == null)
-      this.{self::C::_#C#x} = #t6;
+      this.{self::C::_#C#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
   method initVars() → dynamic {
@@ -131,10 +131,10 @@
     }
   }
   block {
-    final core::List<core::int> #t7 = core::_GrowableList::•<core::int>(0);
+    final core::List<core::int> #t5 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
-      #t7.{core::List::add}{Invariant}(i){(core::int) → void};
-  } =>#t7;
+      #t5.{core::List::add}{Invariant}(i){(core::int) → void};
+  } =>#t5;
 }
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -158,8 +158,8 @@
           try
             #L2:
             while (true) {
-              dynamic #t8 = asy::_asyncStarMoveNextHelper(:stream);
-              [yield] let dynamic #t9 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
+              dynamic #t6 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t7 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
               if(_in::unsafeCast<core::bool>(:result)) {
                 core::String s = :for-iterator.{asy::_StreamIterator::current}{core::String};
                 {
@@ -171,7 +171,7 @@
             }
           finally
             if(!(:for-iterator.{asy::_StreamIterator::_subscription}{asy::StreamSubscription<core::String>?} == null)) {
-              [yield] let dynamic #t10 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
+              [yield] let dynamic #t8 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
               :result;
             }
         }
@@ -204,21 +204,21 @@
       {
         lowered core::String? #s1;
         function #s1#get() → core::String
-          return let final core::String? #t11 = #s1 in #t11 == null ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t9 = #s1 in #t9 == null ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" : #t11{core::String};
-        function #s1#set(core::String #t12) → dynamic
-          return #s1 = #t12;
+                   ^^^^^" : #t9{core::String};
+        function #s1#set(core::String s1#param) → dynamic
+          return #s1 = s1#param;
         lowered core::String? #s2;
         function #s2#get() → core::String
-          return let final core::String? #t13 = #s2 in #t13 == null ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t10 = #s2 in #t10 == null ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t13{core::String};
-        function #s2#set(core::String #t14) → dynamic
-          return #s2 = #t14;
+                             ^^^^^"}${#C1}" : #t10{core::String};
+        function #s2#set(core::String s2#param) → dynamic
+          return #s2 = s2#param;
         lowered core::Function? #f;
         function #f#get() → core::Function
-          return let final core::Function? #t15 = #f in #t15 == null ?{core::Function} #f = () → asy::Future<dynamic> /* originally async */ {
+          return let final core::Function? #t11 = #f in #t11 == null ?{core::Function} #f = () → asy::Future<dynamic> /* originally async */ {
             final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
             core::bool* :is_sync = false;
             FutureOr<dynamic>? :return_value;
@@ -231,7 +231,7 @@
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t16 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  [yield] let dynamic #t12 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
                   :return_value = :result;
                   break #L4;
                 }
@@ -246,9 +246,9 @@
             :async_op(){() → dynamic};
             :is_sync = true;
             return :async_future;
-          } : #t15{core::Function};
-        function #f#set(core::Function #t17) → dynamic
-          return #f = #t17;
+          } : #t11{core::Function};
+        function #f#set(core::Function f#param) → dynamic
+          return #f = f#param;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
index a38e25a..74e414d 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -81,9 +81,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#b}{core::int?} in #t1{core::int};
   }
-  set b(core::int #t2) → void {
+  set b(core::int b#param) → void {
     this.{self::A::_#A#b#isSet} = true;
-    this.{self::A::_#A#b} = #t2;
+    this.{self::A::_#A#b} = b#param;
   }
   method foo(core::int x) → dynamic {}
 }
@@ -95,13 +95,13 @@
     ;
   get x() → core::int {
     if(!this.{self::B::_#B#x#isSet}{core::bool}) {
-      final core::int #t3 = 42;
+      final core::int #t2 = 42;
       if(this.{self::B::_#B#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::B::_#B#x} = #t3;
+      this.{self::B::_#B#x} = #t2;
       this.{self::B::_#B#x#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::B::_#B#x}{core::int?} in #t4{core::int};
+    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3{core::int};
   }
 }
 class C extends core::Object {
@@ -111,13 +111,13 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t6) → void
+    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("x");
+  set x(core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t6;
+      this.{self::C::_#C#x} = x#param;
     }
   method initVars() → dynamic {
     this.{self::C::x} = 42;
@@ -145,10 +145,10 @@
     core::print(s);
   }
   block {
-    final core::List<core::int> #t7 = <core::int>[];
+    final core::List<core::int> #t5 = <core::int>[];
     for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
-      #t7.{core::List::add}{Invariant}(i){(core::int) → void};
-  } =>#t7;
+      #t5.{core::List::add}{Invariant}(i){(core::int) → void};
+  } =>#t5;
 }
 static method hest() → dynamic async {
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
@@ -168,9 +168,9 @@
     }
     return #s1{core::String};
   }
-  function #s1#set(core::String #t8) → dynamic {
+  function #s1#set(core::String s1#param) → dynamic {
     #s1#isSet = true;
-    return #s1 = #t8;
+    return #s1 = s1#param;
   }
   lowered core::String? #s2;
   lowered core::bool #s2#isSet = false;
@@ -183,9 +183,9 @@
     }
     return #s2{core::String};
   }
-  function #s2#set(core::String #t9) → dynamic {
+  function #s2#set(core::String s2#param) → dynamic {
     #s2#isSet = true;
-    return #s2 = #t9;
+    return #s2 = s2#param;
   }
   lowered core::Function? #f;
   lowered core::bool #f#isSet = false;
@@ -196,9 +196,9 @@
     }
     return #f{core::Function};
   }
-  function #f#set(core::Function #t10) → dynamic {
+  function #f#set(core::Function f#param) → dynamic {
     #f#isSet = true;
-    return #f = #t10;
+    return #f = f#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.modular.expect
index a38e25a..74e414d 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.modular.expect
@@ -81,9 +81,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#b}{core::int?} in #t1{core::int};
   }
-  set b(core::int #t2) → void {
+  set b(core::int b#param) → void {
     this.{self::A::_#A#b#isSet} = true;
-    this.{self::A::_#A#b} = #t2;
+    this.{self::A::_#A#b} = b#param;
   }
   method foo(core::int x) → dynamic {}
 }
@@ -95,13 +95,13 @@
     ;
   get x() → core::int {
     if(!this.{self::B::_#B#x#isSet}{core::bool}) {
-      final core::int #t3 = 42;
+      final core::int #t2 = 42;
       if(this.{self::B::_#B#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::B::_#B#x} = #t3;
+      this.{self::B::_#B#x} = #t2;
       this.{self::B::_#B#x#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::B::_#B#x}{core::int?} in #t4{core::int};
+    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3{core::int};
   }
 }
 class C extends core::Object {
@@ -111,13 +111,13 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t6) → void
+    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("x");
+  set x(core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t6;
+      this.{self::C::_#C#x} = x#param;
     }
   method initVars() → dynamic {
     this.{self::C::x} = 42;
@@ -145,10 +145,10 @@
     core::print(s);
   }
   block {
-    final core::List<core::int> #t7 = <core::int>[];
+    final core::List<core::int> #t5 = <core::int>[];
     for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
-      #t7.{core::List::add}{Invariant}(i){(core::int) → void};
-  } =>#t7;
+      #t5.{core::List::add}{Invariant}(i){(core::int) → void};
+  } =>#t5;
 }
 static method hest() → dynamic async {
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
@@ -168,9 +168,9 @@
     }
     return #s1{core::String};
   }
-  function #s1#set(core::String #t8) → dynamic {
+  function #s1#set(core::String s1#param) → dynamic {
     #s1#isSet = true;
-    return #s1 = #t8;
+    return #s1 = s1#param;
   }
   lowered core::String? #s2;
   lowered core::bool #s2#isSet = false;
@@ -183,9 +183,9 @@
     }
     return #s2{core::String};
   }
-  function #s2#set(core::String #t9) → dynamic {
+  function #s2#set(core::String s2#param) → dynamic {
     #s2#isSet = true;
-    return #s2 = #t9;
+    return #s2 = s2#param;
   }
   lowered core::Function? #f;
   lowered core::bool #f#isSet = false;
@@ -196,9 +196,9 @@
     }
     return #f{core::Function};
   }
-  function #f#set(core::Function #t10) → dynamic {
+  function #f#set(core::Function f#param) → dynamic {
     #f#isSet = true;
-    return #f = #t10;
+    return #f = f#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.outline.expect
index 0c2d04f..dd03270 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.outline.expect
@@ -23,7 +23,7 @@
   synthetic constructor •() → self::A
     ;
   get b() → core::int;
-  set b(core::int #t1) → void;
+  set b(core::int b#param) → void;
   method foo(core::int x) → dynamic
     ;
 }
@@ -35,13 +35,13 @@
     ;
   get x() → core::int {
     if(!this.{self::B::_#B#x#isSet}{core::bool}) {
-      final core::int #t2 = 42;
+      final core::int #t1 = 42;
       if(this.{self::B::_#B#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::B::_#B#x} = #t2;
+      this.{self::B::_#B#x} = #t1;
       this.{self::B::_#B#x#isSet} = true;
     }
-    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3{core::int};
+    return let final core::int? #t2 = this.{self::B::_#B#x}{core::int?} in #t2{core::int};
   }
 }
 class C extends core::Object {
@@ -50,7 +50,7 @@
   synthetic constructor •() → self::C
     ;
   get x() → core::int;
-  set x(core::int #t4) → void;
+  set x(core::int x#param) → void;
   method initVars() → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index a808b23..c43553e 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -81,9 +81,9 @@
     }
     return let final core::int? #t1 = this.{self::A::_#A#b}{core::int?} in #t1{core::int};
   }
-  set b(core::int #t2) → void {
+  set b(core::int b#param) → void {
     this.{self::A::_#A#b#isSet} = true;
-    this.{self::A::_#A#b} = #t2;
+    this.{self::A::_#A#b} = b#param;
   }
   method foo(core::int x) → dynamic {}
 }
@@ -95,13 +95,13 @@
     ;
   get x() → core::int {
     if(!this.{self::B::_#B#x#isSet}{core::bool}) {
-      final core::int #t3 = 42;
+      final core::int #t2 = 42;
       if(this.{self::B::_#B#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::B::_#B#x} = #t3;
+      this.{self::B::_#B#x} = #t2;
       this.{self::B::_#B#x#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::B::_#B#x}{core::int?} in #t4{core::int};
+    return let final core::int? #t3 = this.{self::B::_#B#x}{core::int?} in #t3{core::int};
   }
 }
 class C extends core::Object {
@@ -111,13 +111,13 @@
     : super core::Object::•()
     ;
   get x() → core::int
-    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t6) → void
+    return this.{self::C::_#C#x#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("x");
+  set x(core::int x#param) → void
     if(this.{self::C::_#C#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::C::_#C#x#isSet} = true;
-      this.{self::C::_#C#x} = #t6;
+      this.{self::C::_#C#x} = x#param;
     }
   method initVars() → dynamic {
     this.{self::C::x} = 42;
@@ -151,10 +151,10 @@
     }
   }
   block {
-    final core::List<core::int> #t7 = core::_GrowableList::•<core::int>(0);
+    final core::List<core::int> #t5 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
-      #t7.{core::List::add}{Invariant}(i){(core::int) → void};
-  } =>#t7;
+      #t5.{core::List::add}{Invariant}(i){(core::int) → void};
+  } =>#t5;
 }
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -178,8 +178,8 @@
           try
             #L2:
             while (true) {
-              dynamic #t8 = asy::_asyncStarMoveNextHelper(:stream);
-              [yield] let dynamic #t9 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
+              dynamic #t6 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t7 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
               if(_in::unsafeCast<core::bool>(:result)) {
                 core::String s = :for-iterator.{asy::_StreamIterator::current}{core::String};
                 {
@@ -191,7 +191,7 @@
             }
           finally
             if(!(:for-iterator.{asy::_StreamIterator::_subscription}{asy::StreamSubscription<core::String>?} == null)) {
-              [yield] let dynamic #t10 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
+              [yield] let dynamic #t8 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
               :result;
             }
         }
@@ -233,9 +233,9 @@
           }
           return #s1{core::String};
         }
-        function #s1#set(core::String #t11) → dynamic {
+        function #s1#set(core::String s1#param) → dynamic {
           #s1#isSet = true;
-          return #s1 = #t11;
+          return #s1 = s1#param;
         }
         lowered core::String? #s2;
         lowered core::bool #s2#isSet = false;
@@ -248,9 +248,9 @@
           }
           return #s2{core::String};
         }
-        function #s2#set(core::String #t12) → dynamic {
+        function #s2#set(core::String s2#param) → dynamic {
           #s2#isSet = true;
-          return #s2 = #t12;
+          return #s2 = s2#param;
         }
         lowered core::Function? #f;
         lowered core::bool #f#isSet = false;
@@ -269,7 +269,7 @@
                 try {
                   #L4:
                   {
-                    [yield] let dynamic #t13 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                    [yield] let dynamic #t9 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
                     :return_value = :result;
                     break #L4;
                   }
@@ -289,9 +289,9 @@
           }
           return #f{core::Function};
         }
-        function #f#set(core::Function #t14) → dynamic {
+        function #f#set(core::Function f#param) → dynamic {
           #f#isSet = true;
-          return #f = #t14;
+          return #f = f#param;
         }
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect
index 3df87d0..4ae5a1a 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect
@@ -56,86 +56,86 @@
     ;
   get instanceField() → core::int
     return let final core::int? #t1 = this.{non::Class::_#Class#instanceField}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t1{core::int};
-  set instanceField(core::int #t2) → void
-    this.{non::Class::_#Class#instanceField} = #t2;
+  set instanceField(core::int instanceField#param) → void
+    this.{non::Class::_#Class#instanceField} = instanceField#param;
   get finalInstanceField() → dynamic
     return this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool} ?{dynamic} this.{non::Class::_#Class#finalInstanceField}{dynamic} : throw new _in::LateError::fieldNI("finalInstanceField");
-  set finalInstanceField(dynamic #t3) → void
+  set finalInstanceField(dynamic finalInstanceField#param) → void
     if(this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{non::Class::_#Class#finalInstanceField#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceField} = #t3;
+      this.{non::Class::_#Class#finalInstanceField} = finalInstanceField#param;
     }
   get instanceTypeVariable() → non::Class::T
-    return let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t4 == null ?{non::Class::T} throw new _in::LateError::fieldNI("instanceTypeVariable") : #t4{non::Class::T};
-  set instanceTypeVariable(covariant-by-class non::Class::T #t5) → void
-    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+    return let final non::Class::T? #t2 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t2 == null ?{non::Class::T} throw new _in::LateError::fieldNI("instanceTypeVariable") : #t2{non::Class::T};
+  set instanceTypeVariable(covariant-by-class non::Class::T instanceTypeVariable#param) → void
+    this.{non::Class::_#Class#instanceTypeVariable} = instanceTypeVariable#param;
   get finalInstanceTypeVariable() → non::Class::T
-    return let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t6 == null ?{non::Class::T} throw new _in::LateError::fieldNI("finalInstanceTypeVariable") : #t6{non::Class::T};
-  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    return let final non::Class::T? #t3 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t3 == null ?{non::Class::T} throw new _in::LateError::fieldNI("finalInstanceTypeVariable") : #t3{non::Class::T};
+  set finalInstanceTypeVariable(non::Class::T finalInstanceTypeVariable#param) → void
     if(this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} == null)
-      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = finalInstanceTypeVariable#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceTypeVariable");
   static get staticField() → core::int
-    return let final core::int? #t8 = non::Class::_#staticField in #t8 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t8{core::int};
-  static set staticField(core::int #t9) → void
-    non::Class::_#staticField = #t9;
+    return let final core::int? #t4 = non::Class::_#staticField in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t4{core::int};
+  static set staticField(core::int staticField#param) → void
+    non::Class::_#staticField = staticField#param;
   static get staticFinalField() → dynamic
     return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateError::fieldNI("staticFinalField");
-  static set staticFinalField(dynamic #t10) → void
+  static set staticFinalField(dynamic staticFinalField#param) → void
     if(non::Class::_#staticFinalField#isSet)
       throw new _in::LateError::fieldAI("staticFinalField");
     else {
       non::Class::_#staticFinalField#isSet = true;
-      non::Class::_#staticFinalField = #t10;
+      non::Class::_#staticFinalField = staticFinalField#param;
     }
 }
 static field core::int? _#topLevelField = null;
 static field dynamic _#finalTopLevelField = null;
 static field core::bool _#finalTopLevelField#isSet = false;
 static get topLevelField() → core::int
-  return let final core::int? #t11 = non::_#topLevelField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t11{core::int};
-static set topLevelField(core::int #t12) → void
-  non::_#topLevelField = #t12;
+  return let final core::int? #t5 = non::_#topLevelField in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t5{core::int};
+static set topLevelField(core::int topLevelField#param) → void
+  non::_#topLevelField = topLevelField#param;
 static get finalTopLevelField() → dynamic
   return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateError::fieldNI("finalTopLevelField");
-static set finalTopLevelField(dynamic #t13) → void
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void
   if(non::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     non::_#finalTopLevelField#isSet = true;
-    non::_#finalTopLevelField = #t13;
+    non::_#finalTopLevelField = finalTopLevelField#param;
   }
 static method method<T extends core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
   lowered core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t14 = #local in #t14 == null ?{core::int} throw new _in::LateError::localNI("local") : #t14{core::int};
-  function #local#set(core::int #t15) → dynamic
-    return #local = #t15;
+    return let final core::int? #t6 = #local in #t6 == null ?{core::int} throw new _in::LateError::localNI("local") : #t6{core::int};
+  function #local#set(core::int local#param) → dynamic
+    return #local = local#param;
   lowered final dynamic #finalLocal;
   lowered core::bool #finalLocal#isSet = false;
   function #finalLocal#get() → dynamic
     return #finalLocal#isSet ?{dynamic} #finalLocal : throw new _in::LateError::localNI("finalLocal");
-  function #finalLocal#set(dynamic #t16) → dynamic
+  function #finalLocal#set(dynamic finalLocal#param) → dynamic
     if(#finalLocal#isSet)
       throw new _in::LateError::localAI("finalLocal");
     else {
       #finalLocal#isSet = true;
-      return #finalLocal = #t16;
+      return #finalLocal = finalLocal#param;
     }
   lowered non::method::T? #localTypeVariable;
   function #localTypeVariable#get() → non::method::T
-    return let final non::method::T? #t17 = #localTypeVariable in #t17 == null ?{non::method::T} throw new _in::LateError::localNI("localTypeVariable") : #t17{non::method::T};
-  function #localTypeVariable#set(non::method::T #t18) → dynamic
-    return #localTypeVariable = #t18;
+    return let final non::method::T? #t7 = #localTypeVariable in #t7 == null ?{non::method::T} throw new _in::LateError::localNI("localTypeVariable") : #t7{non::method::T};
+  function #localTypeVariable#set(non::method::T localTypeVariable#param) → dynamic
+    return #localTypeVariable = localTypeVariable#param;
   lowered final non::method::T? #finalLocalTypeVariable;
   function #finalLocalTypeVariable#get() → non::method::T
-    return let final non::method::T? #t19 = #finalLocalTypeVariable in #t19 == null ?{non::method::T} throw new _in::LateError::localNI("finalLocalTypeVariable") : #t19{non::method::T};
-  function #finalLocalTypeVariable#set(non::method::T #t20) → dynamic
+    return let final non::method::T? #t8 = #finalLocalTypeVariable in #t8 == null ?{non::method::T} throw new _in::LateError::localNI("finalLocalTypeVariable") : #t8{non::method::T};
+  function #finalLocalTypeVariable#set(non::method::T finalLocalTypeVariable#param) → dynamic
     if(#finalLocalTypeVariable == null)
-      return #finalLocalTypeVariable = #t20;
+      return #finalLocalTypeVariable = finalLocalTypeVariable#param;
     else
       throw new _in::LateError::localAI("finalLocalTypeVariable");
   if(b) {
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect
index 3df87d0..4ae5a1a 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect
@@ -56,86 +56,86 @@
     ;
   get instanceField() → core::int
     return let final core::int? #t1 = this.{non::Class::_#Class#instanceField}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("instanceField") : #t1{core::int};
-  set instanceField(core::int #t2) → void
-    this.{non::Class::_#Class#instanceField} = #t2;
+  set instanceField(core::int instanceField#param) → void
+    this.{non::Class::_#Class#instanceField} = instanceField#param;
   get finalInstanceField() → dynamic
     return this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool} ?{dynamic} this.{non::Class::_#Class#finalInstanceField}{dynamic} : throw new _in::LateError::fieldNI("finalInstanceField");
-  set finalInstanceField(dynamic #t3) → void
+  set finalInstanceField(dynamic finalInstanceField#param) → void
     if(this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{non::Class::_#Class#finalInstanceField#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceField} = #t3;
+      this.{non::Class::_#Class#finalInstanceField} = finalInstanceField#param;
     }
   get instanceTypeVariable() → non::Class::T
-    return let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t4 == null ?{non::Class::T} throw new _in::LateError::fieldNI("instanceTypeVariable") : #t4{non::Class::T};
-  set instanceTypeVariable(covariant-by-class non::Class::T #t5) → void
-    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+    return let final non::Class::T? #t2 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t2 == null ?{non::Class::T} throw new _in::LateError::fieldNI("instanceTypeVariable") : #t2{non::Class::T};
+  set instanceTypeVariable(covariant-by-class non::Class::T instanceTypeVariable#param) → void
+    this.{non::Class::_#Class#instanceTypeVariable} = instanceTypeVariable#param;
   get finalInstanceTypeVariable() → non::Class::T
-    return let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t6 == null ?{non::Class::T} throw new _in::LateError::fieldNI("finalInstanceTypeVariable") : #t6{non::Class::T};
-  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    return let final non::Class::T? #t3 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t3 == null ?{non::Class::T} throw new _in::LateError::fieldNI("finalInstanceTypeVariable") : #t3{non::Class::T};
+  set finalInstanceTypeVariable(non::Class::T finalInstanceTypeVariable#param) → void
     if(this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} == null)
-      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = finalInstanceTypeVariable#param;
     else
       throw new _in::LateError::fieldAI("finalInstanceTypeVariable");
   static get staticField() → core::int
-    return let final core::int? #t8 = non::Class::_#staticField in #t8 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t8{core::int};
-  static set staticField(core::int #t9) → void
-    non::Class::_#staticField = #t9;
+    return let final core::int? #t4 = non::Class::_#staticField in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("staticField") : #t4{core::int};
+  static set staticField(core::int staticField#param) → void
+    non::Class::_#staticField = staticField#param;
   static get staticFinalField() → dynamic
     return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateError::fieldNI("staticFinalField");
-  static set staticFinalField(dynamic #t10) → void
+  static set staticFinalField(dynamic staticFinalField#param) → void
     if(non::Class::_#staticFinalField#isSet)
       throw new _in::LateError::fieldAI("staticFinalField");
     else {
       non::Class::_#staticFinalField#isSet = true;
-      non::Class::_#staticFinalField = #t10;
+      non::Class::_#staticFinalField = staticFinalField#param;
     }
 }
 static field core::int? _#topLevelField = null;
 static field dynamic _#finalTopLevelField = null;
 static field core::bool _#finalTopLevelField#isSet = false;
 static get topLevelField() → core::int
-  return let final core::int? #t11 = non::_#topLevelField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t11{core::int};
-static set topLevelField(core::int #t12) → void
-  non::_#topLevelField = #t12;
+  return let final core::int? #t5 = non::_#topLevelField in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("topLevelField") : #t5{core::int};
+static set topLevelField(core::int topLevelField#param) → void
+  non::_#topLevelField = topLevelField#param;
 static get finalTopLevelField() → dynamic
   return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateError::fieldNI("finalTopLevelField");
-static set finalTopLevelField(dynamic #t13) → void
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void
   if(non::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     non::_#finalTopLevelField#isSet = true;
-    non::_#finalTopLevelField = #t13;
+    non::_#finalTopLevelField = finalTopLevelField#param;
   }
 static method method<T extends core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
   lowered core::int? #local;
   function #local#get() → core::int
-    return let final core::int? #t14 = #local in #t14 == null ?{core::int} throw new _in::LateError::localNI("local") : #t14{core::int};
-  function #local#set(core::int #t15) → dynamic
-    return #local = #t15;
+    return let final core::int? #t6 = #local in #t6 == null ?{core::int} throw new _in::LateError::localNI("local") : #t6{core::int};
+  function #local#set(core::int local#param) → dynamic
+    return #local = local#param;
   lowered final dynamic #finalLocal;
   lowered core::bool #finalLocal#isSet = false;
   function #finalLocal#get() → dynamic
     return #finalLocal#isSet ?{dynamic} #finalLocal : throw new _in::LateError::localNI("finalLocal");
-  function #finalLocal#set(dynamic #t16) → dynamic
+  function #finalLocal#set(dynamic finalLocal#param) → dynamic
     if(#finalLocal#isSet)
       throw new _in::LateError::localAI("finalLocal");
     else {
       #finalLocal#isSet = true;
-      return #finalLocal = #t16;
+      return #finalLocal = finalLocal#param;
     }
   lowered non::method::T? #localTypeVariable;
   function #localTypeVariable#get() → non::method::T
-    return let final non::method::T? #t17 = #localTypeVariable in #t17 == null ?{non::method::T} throw new _in::LateError::localNI("localTypeVariable") : #t17{non::method::T};
-  function #localTypeVariable#set(non::method::T #t18) → dynamic
-    return #localTypeVariable = #t18;
+    return let final non::method::T? #t7 = #localTypeVariable in #t7 == null ?{non::method::T} throw new _in::LateError::localNI("localTypeVariable") : #t7{non::method::T};
+  function #localTypeVariable#set(non::method::T localTypeVariable#param) → dynamic
+    return #localTypeVariable = localTypeVariable#param;
   lowered final non::method::T? #finalLocalTypeVariable;
   function #finalLocalTypeVariable#get() → non::method::T
-    return let final non::method::T? #t19 = #finalLocalTypeVariable in #t19 == null ?{non::method::T} throw new _in::LateError::localNI("finalLocalTypeVariable") : #t19{non::method::T};
-  function #finalLocalTypeVariable#set(non::method::T #t20) → dynamic
+    return let final non::method::T? #t8 = #finalLocalTypeVariable in #t8 == null ?{non::method::T} throw new _in::LateError::localNI("finalLocalTypeVariable") : #t8{non::method::T};
+  function #finalLocalTypeVariable#set(non::method::T finalLocalTypeVariable#param) → dynamic
     if(#finalLocalTypeVariable == null)
-      return #finalLocalTypeVariable = #t20;
+      return #finalLocalTypeVariable = finalLocalTypeVariable#param;
     else
       throw new _in::LateError::localAI("finalLocalTypeVariable");
   if(b) {
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect
index 86913df..58294fe 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect
@@ -53,48 +53,48 @@
     ;
   get instanceField() → core::int
     return this.{non::Class::_#Class#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{non::Class::_#Class#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{non::Class::_#Class#instanceField#isSet} = true;
-    this.{non::Class::_#Class#instanceField} = #t2;
+    this.{non::Class::_#Class#instanceField} = instanceField#param;
   }
   get finalInstanceField() → dynamic
     return this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool} ?{dynamic} this.{non::Class::_#Class#finalInstanceField}{dynamic} : throw new _in::LateError::fieldNI("finalInstanceField");
-  set finalInstanceField(dynamic #t3) → void
+  set finalInstanceField(dynamic finalInstanceField#param) → void
     if(this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{non::Class::_#Class#finalInstanceField#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceField} = #t3;
+      this.{non::Class::_#Class#finalInstanceField} = finalInstanceField#param;
     }
   get instanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t4{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
-  set instanceTypeVariable(covariant-by-class non::Class::T #t5) → void {
+    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t2 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t2{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
+  set instanceTypeVariable(covariant-by-class non::Class::T instanceTypeVariable#param) → void {
     this.{non::Class::_#Class#instanceTypeVariable#isSet} = true;
-    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+    this.{non::Class::_#Class#instanceTypeVariable} = instanceTypeVariable#param;
   }
   get finalInstanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t6{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
-  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t3 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t3{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
+  set finalInstanceTypeVariable(non::Class::T finalInstanceTypeVariable#param) → void
     if(this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceTypeVariable");
     else {
       this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = finalInstanceTypeVariable#param;
     }
   static get staticField() → core::int
-    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t8 = non::Class::_#staticField in #t8{core::int} : throw new _in::LateError::fieldNI("staticField");
-  static set staticField(core::int #t9) → void {
+    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t4 = non::Class::_#staticField in #t4{core::int} : throw new _in::LateError::fieldNI("staticField");
+  static set staticField(core::int staticField#param) → void {
     non::Class::_#staticField#isSet = true;
-    non::Class::_#staticField = #t9;
+    non::Class::_#staticField = staticField#param;
   }
   static get staticFinalField() → dynamic
     return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateError::fieldNI("staticFinalField");
-  static set staticFinalField(dynamic #t10) → void
+  static set staticFinalField(dynamic staticFinalField#param) → void
     if(non::Class::_#staticFinalField#isSet)
       throw new _in::LateError::fieldAI("staticFinalField");
     else {
       non::Class::_#staticFinalField#isSet = true;
-      non::Class::_#staticFinalField = #t10;
+      non::Class::_#staticFinalField = staticFinalField#param;
     }
 }
 static field core::int? _#topLevelField = null;
@@ -102,58 +102,58 @@
 static field dynamic _#finalTopLevelField = null;
 static field core::bool _#finalTopLevelField#isSet = false;
 static get topLevelField() → core::int
-  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t11 = non::_#topLevelField in #t11{core::int} : throw new _in::LateError::fieldNI("topLevelField");
-static set topLevelField(core::int #t12) → void {
+  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t5 = non::_#topLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+static set topLevelField(core::int topLevelField#param) → void {
   non::_#topLevelField#isSet = true;
-  non::_#topLevelField = #t12;
+  non::_#topLevelField = topLevelField#param;
 }
 static get finalTopLevelField() → dynamic
   return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateError::fieldNI("finalTopLevelField");
-static set finalTopLevelField(dynamic #t13) → void
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void
   if(non::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     non::_#finalTopLevelField#isSet = true;
-    non::_#finalTopLevelField = #t13;
+    non::_#finalTopLevelField = finalTopLevelField#param;
   }
 static method method<T extends core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
   lowered core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t14) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t14;
+    return #local = local#param;
   }
   lowered final dynamic #finalLocal;
   lowered core::bool #finalLocal#isSet = false;
   function #finalLocal#get() → dynamic
     return #finalLocal#isSet ?{dynamic} #finalLocal : throw new _in::LateError::localNI("finalLocal");
-  function #finalLocal#set(dynamic #t15) → dynamic
+  function #finalLocal#set(dynamic finalLocal#param) → dynamic
     if(#finalLocal#isSet)
       throw new _in::LateError::localAI("finalLocal");
     else {
       #finalLocal#isSet = true;
-      return #finalLocal = #t15;
+      return #finalLocal = finalLocal#param;
     }
   lowered non::method::T? #localTypeVariable;
   lowered core::bool #localTypeVariable#isSet = false;
   function #localTypeVariable#get() → non::method::T
     return #localTypeVariable#isSet ?{non::method::T} #localTypeVariable{non::method::T} : throw new _in::LateError::localNI("localTypeVariable");
-  function #localTypeVariable#set(non::method::T #t16) → dynamic {
+  function #localTypeVariable#set(non::method::T localTypeVariable#param) → dynamic {
     #localTypeVariable#isSet = true;
-    return #localTypeVariable = #t16;
+    return #localTypeVariable = localTypeVariable#param;
   }
   lowered final non::method::T? #finalLocalTypeVariable;
   lowered core::bool #finalLocalTypeVariable#isSet = false;
   function #finalLocalTypeVariable#get() → non::method::T
     return #finalLocalTypeVariable#isSet ?{non::method::T} #finalLocalTypeVariable{non::method::T} : throw new _in::LateError::localNI("finalLocalTypeVariable");
-  function #finalLocalTypeVariable#set(non::method::T #t17) → dynamic
+  function #finalLocalTypeVariable#set(non::method::T finalLocalTypeVariable#param) → dynamic
     if(#finalLocalTypeVariable#isSet)
       throw new _in::LateError::localAI("finalLocalTypeVariable");
     else {
       #finalLocalTypeVariable#isSet = true;
-      return #finalLocalTypeVariable = #t17;
+      return #finalLocalTypeVariable = finalLocalTypeVariable#param;
     }
   if(b) {
     #local#set(i){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.modular.expect
index 86913df..58294fe 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.modular.expect
@@ -53,48 +53,48 @@
     ;
   get instanceField() → core::int
     return this.{non::Class::_#Class#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{non::Class::_#Class#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{non::Class::_#Class#instanceField#isSet} = true;
-    this.{non::Class::_#Class#instanceField} = #t2;
+    this.{non::Class::_#Class#instanceField} = instanceField#param;
   }
   get finalInstanceField() → dynamic
     return this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool} ?{dynamic} this.{non::Class::_#Class#finalInstanceField}{dynamic} : throw new _in::LateError::fieldNI("finalInstanceField");
-  set finalInstanceField(dynamic #t3) → void
+  set finalInstanceField(dynamic finalInstanceField#param) → void
     if(this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{non::Class::_#Class#finalInstanceField#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceField} = #t3;
+      this.{non::Class::_#Class#finalInstanceField} = finalInstanceField#param;
     }
   get instanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t4{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
-  set instanceTypeVariable(covariant-by-class non::Class::T #t5) → void {
+    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t2 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t2{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
+  set instanceTypeVariable(covariant-by-class non::Class::T instanceTypeVariable#param) → void {
     this.{non::Class::_#Class#instanceTypeVariable#isSet} = true;
-    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+    this.{non::Class::_#Class#instanceTypeVariable} = instanceTypeVariable#param;
   }
   get finalInstanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t6{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
-  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t3 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t3{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
+  set finalInstanceTypeVariable(non::Class::T finalInstanceTypeVariable#param) → void
     if(this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceTypeVariable");
     else {
       this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = finalInstanceTypeVariable#param;
     }
   static get staticField() → core::int
-    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t8 = non::Class::_#staticField in #t8{core::int} : throw new _in::LateError::fieldNI("staticField");
-  static set staticField(core::int #t9) → void {
+    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t4 = non::Class::_#staticField in #t4{core::int} : throw new _in::LateError::fieldNI("staticField");
+  static set staticField(core::int staticField#param) → void {
     non::Class::_#staticField#isSet = true;
-    non::Class::_#staticField = #t9;
+    non::Class::_#staticField = staticField#param;
   }
   static get staticFinalField() → dynamic
     return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateError::fieldNI("staticFinalField");
-  static set staticFinalField(dynamic #t10) → void
+  static set staticFinalField(dynamic staticFinalField#param) → void
     if(non::Class::_#staticFinalField#isSet)
       throw new _in::LateError::fieldAI("staticFinalField");
     else {
       non::Class::_#staticFinalField#isSet = true;
-      non::Class::_#staticFinalField = #t10;
+      non::Class::_#staticFinalField = staticFinalField#param;
     }
 }
 static field core::int? _#topLevelField = null;
@@ -102,58 +102,58 @@
 static field dynamic _#finalTopLevelField = null;
 static field core::bool _#finalTopLevelField#isSet = false;
 static get topLevelField() → core::int
-  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t11 = non::_#topLevelField in #t11{core::int} : throw new _in::LateError::fieldNI("topLevelField");
-static set topLevelField(core::int #t12) → void {
+  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t5 = non::_#topLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+static set topLevelField(core::int topLevelField#param) → void {
   non::_#topLevelField#isSet = true;
-  non::_#topLevelField = #t12;
+  non::_#topLevelField = topLevelField#param;
 }
 static get finalTopLevelField() → dynamic
   return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateError::fieldNI("finalTopLevelField");
-static set finalTopLevelField(dynamic #t13) → void
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void
   if(non::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     non::_#finalTopLevelField#isSet = true;
-    non::_#finalTopLevelField = #t13;
+    non::_#finalTopLevelField = finalTopLevelField#param;
   }
 static method method<T extends core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
   lowered core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t14) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t14;
+    return #local = local#param;
   }
   lowered final dynamic #finalLocal;
   lowered core::bool #finalLocal#isSet = false;
   function #finalLocal#get() → dynamic
     return #finalLocal#isSet ?{dynamic} #finalLocal : throw new _in::LateError::localNI("finalLocal");
-  function #finalLocal#set(dynamic #t15) → dynamic
+  function #finalLocal#set(dynamic finalLocal#param) → dynamic
     if(#finalLocal#isSet)
       throw new _in::LateError::localAI("finalLocal");
     else {
       #finalLocal#isSet = true;
-      return #finalLocal = #t15;
+      return #finalLocal = finalLocal#param;
     }
   lowered non::method::T? #localTypeVariable;
   lowered core::bool #localTypeVariable#isSet = false;
   function #localTypeVariable#get() → non::method::T
     return #localTypeVariable#isSet ?{non::method::T} #localTypeVariable{non::method::T} : throw new _in::LateError::localNI("localTypeVariable");
-  function #localTypeVariable#set(non::method::T #t16) → dynamic {
+  function #localTypeVariable#set(non::method::T localTypeVariable#param) → dynamic {
     #localTypeVariable#isSet = true;
-    return #localTypeVariable = #t16;
+    return #localTypeVariable = localTypeVariable#param;
   }
   lowered final non::method::T? #finalLocalTypeVariable;
   lowered core::bool #finalLocalTypeVariable#isSet = false;
   function #finalLocalTypeVariable#get() → non::method::T
     return #finalLocalTypeVariable#isSet ?{non::method::T} #finalLocalTypeVariable{non::method::T} : throw new _in::LateError::localNI("finalLocalTypeVariable");
-  function #finalLocalTypeVariable#set(non::method::T #t17) → dynamic
+  function #finalLocalTypeVariable#set(non::method::T finalLocalTypeVariable#param) → dynamic
     if(#finalLocalTypeVariable#isSet)
       throw new _in::LateError::localAI("finalLocalTypeVariable");
     else {
       #finalLocalTypeVariable#isSet = true;
-      return #finalLocalTypeVariable = #t17;
+      return #finalLocalTypeVariable = finalLocalTypeVariable#param;
     }
   if(b) {
     #local#set(i){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.outline.expect
index 22fc18d..479613a 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.outline.expect
@@ -26,26 +26,26 @@
   synthetic constructor •() → self2::Class<self2::Class::T>
     ;
   get instanceField() → core::int;
-  set instanceField(core::int #t1) → void;
+  set instanceField(core::int instanceField#param) → void;
   get finalInstanceField() → dynamic;
-  set finalInstanceField(dynamic #t2) → void;
+  set finalInstanceField(dynamic finalInstanceField#param) → void;
   get instanceTypeVariable() → self2::Class::T;
-  set instanceTypeVariable(covariant-by-class self2::Class::T #t3) → void;
+  set instanceTypeVariable(covariant-by-class self2::Class::T instanceTypeVariable#param) → void;
   get finalInstanceTypeVariable() → self2::Class::T;
-  set finalInstanceTypeVariable(self2::Class::T #t4) → void;
+  set finalInstanceTypeVariable(self2::Class::T finalInstanceTypeVariable#param) → void;
   static get staticField() → core::int;
-  static set staticField(core::int #t5) → void;
+  static set staticField(core::int staticField#param) → void;
   static get staticFinalField() → dynamic;
-  static set staticFinalField(dynamic #t6) → void;
+  static set staticFinalField(dynamic staticFinalField#param) → void;
 }
 static field core::int? _#topLevelField;
 static field core::bool _#topLevelField#isSet;
 static field dynamic _#finalTopLevelField;
 static field core::bool _#finalTopLevelField#isSet;
 static get topLevelField() → core::int;
-static set topLevelField(core::int #t7) → void;
+static set topLevelField(core::int topLevelField#param) → void;
 static get finalTopLevelField() → dynamic;
-static set finalTopLevelField(dynamic #t8) → void;
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void;
 static method method<T extends core::Object>(core::bool b, core::int i, self2::method::T t) → dynamic
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect
index 86913df..58294fe 100644
--- a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect
@@ -53,48 +53,48 @@
     ;
   get instanceField() → core::int
     return this.{non::Class::_#Class#instanceField#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{non::Class::_#Class#instanceField}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("instanceField");
-  set instanceField(core::int #t2) → void {
+  set instanceField(core::int instanceField#param) → void {
     this.{non::Class::_#Class#instanceField#isSet} = true;
-    this.{non::Class::_#Class#instanceField} = #t2;
+    this.{non::Class::_#Class#instanceField} = instanceField#param;
   }
   get finalInstanceField() → dynamic
     return this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool} ?{dynamic} this.{non::Class::_#Class#finalInstanceField}{dynamic} : throw new _in::LateError::fieldNI("finalInstanceField");
-  set finalInstanceField(dynamic #t3) → void
+  set finalInstanceField(dynamic finalInstanceField#param) → void
     if(this.{non::Class::_#Class#finalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceField");
     else {
       this.{non::Class::_#Class#finalInstanceField#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceField} = #t3;
+      this.{non::Class::_#Class#finalInstanceField} = finalInstanceField#param;
     }
   get instanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t4{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
-  set instanceTypeVariable(covariant-by-class non::Class::T #t5) → void {
+    return this.{non::Class::_#Class#instanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t2 = this.{non::Class::_#Class#instanceTypeVariable}{non::Class::T?} in #t2{non::Class::T} : throw new _in::LateError::fieldNI("instanceTypeVariable");
+  set instanceTypeVariable(covariant-by-class non::Class::T instanceTypeVariable#param) → void {
     this.{non::Class::_#Class#instanceTypeVariable#isSet} = true;
-    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+    this.{non::Class::_#Class#instanceTypeVariable} = instanceTypeVariable#param;
   }
   get finalInstanceTypeVariable() → non::Class::T
-    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t6{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
-  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool} ?{non::Class::T} let final non::Class::T? #t3 = this.{non::Class::_#Class#finalInstanceTypeVariable}{non::Class::T?} in #t3{non::Class::T} : throw new _in::LateError::fieldNI("finalInstanceTypeVariable");
+  set finalInstanceTypeVariable(non::Class::T finalInstanceTypeVariable#param) → void
     if(this.{non::Class::_#Class#finalInstanceTypeVariable#isSet}{core::bool})
       throw new _in::LateError::fieldAI("finalInstanceTypeVariable");
     else {
       this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} = true;
-      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = finalInstanceTypeVariable#param;
     }
   static get staticField() → core::int
-    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t8 = non::Class::_#staticField in #t8{core::int} : throw new _in::LateError::fieldNI("staticField");
-  static set staticField(core::int #t9) → void {
+    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t4 = non::Class::_#staticField in #t4{core::int} : throw new _in::LateError::fieldNI("staticField");
+  static set staticField(core::int staticField#param) → void {
     non::Class::_#staticField#isSet = true;
-    non::Class::_#staticField = #t9;
+    non::Class::_#staticField = staticField#param;
   }
   static get staticFinalField() → dynamic
     return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateError::fieldNI("staticFinalField");
-  static set staticFinalField(dynamic #t10) → void
+  static set staticFinalField(dynamic staticFinalField#param) → void
     if(non::Class::_#staticFinalField#isSet)
       throw new _in::LateError::fieldAI("staticFinalField");
     else {
       non::Class::_#staticFinalField#isSet = true;
-      non::Class::_#staticFinalField = #t10;
+      non::Class::_#staticFinalField = staticFinalField#param;
     }
 }
 static field core::int? _#topLevelField = null;
@@ -102,58 +102,58 @@
 static field dynamic _#finalTopLevelField = null;
 static field core::bool _#finalTopLevelField#isSet = false;
 static get topLevelField() → core::int
-  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t11 = non::_#topLevelField in #t11{core::int} : throw new _in::LateError::fieldNI("topLevelField");
-static set topLevelField(core::int #t12) → void {
+  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t5 = non::_#topLevelField in #t5{core::int} : throw new _in::LateError::fieldNI("topLevelField");
+static set topLevelField(core::int topLevelField#param) → void {
   non::_#topLevelField#isSet = true;
-  non::_#topLevelField = #t12;
+  non::_#topLevelField = topLevelField#param;
 }
 static get finalTopLevelField() → dynamic
   return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateError::fieldNI("finalTopLevelField");
-static set finalTopLevelField(dynamic #t13) → void
+static set finalTopLevelField(dynamic finalTopLevelField#param) → void
   if(non::_#finalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("finalTopLevelField");
   else {
     non::_#finalTopLevelField#isSet = true;
-    non::_#finalTopLevelField = #t13;
+    non::_#finalTopLevelField = finalTopLevelField#param;
   }
 static method method<T extends core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
   lowered core::int? #local;
   lowered core::bool #local#isSet = false;
   function #local#get() → core::int
     return #local#isSet ?{core::int} #local{core::int} : throw new _in::LateError::localNI("local");
-  function #local#set(core::int #t14) → dynamic {
+  function #local#set(core::int local#param) → dynamic {
     #local#isSet = true;
-    return #local = #t14;
+    return #local = local#param;
   }
   lowered final dynamic #finalLocal;
   lowered core::bool #finalLocal#isSet = false;
   function #finalLocal#get() → dynamic
     return #finalLocal#isSet ?{dynamic} #finalLocal : throw new _in::LateError::localNI("finalLocal");
-  function #finalLocal#set(dynamic #t15) → dynamic
+  function #finalLocal#set(dynamic finalLocal#param) → dynamic
     if(#finalLocal#isSet)
       throw new _in::LateError::localAI("finalLocal");
     else {
       #finalLocal#isSet = true;
-      return #finalLocal = #t15;
+      return #finalLocal = finalLocal#param;
     }
   lowered non::method::T? #localTypeVariable;
   lowered core::bool #localTypeVariable#isSet = false;
   function #localTypeVariable#get() → non::method::T
     return #localTypeVariable#isSet ?{non::method::T} #localTypeVariable{non::method::T} : throw new _in::LateError::localNI("localTypeVariable");
-  function #localTypeVariable#set(non::method::T #t16) → dynamic {
+  function #localTypeVariable#set(non::method::T localTypeVariable#param) → dynamic {
     #localTypeVariable#isSet = true;
-    return #localTypeVariable = #t16;
+    return #localTypeVariable = localTypeVariable#param;
   }
   lowered final non::method::T? #finalLocalTypeVariable;
   lowered core::bool #finalLocalTypeVariable#isSet = false;
   function #finalLocalTypeVariable#get() → non::method::T
     return #finalLocalTypeVariable#isSet ?{non::method::T} #finalLocalTypeVariable{non::method::T} : throw new _in::LateError::localNI("finalLocalTypeVariable");
-  function #finalLocalTypeVariable#set(non::method::T #t17) → dynamic
+  function #finalLocalTypeVariable#set(non::method::T finalLocalTypeVariable#param) → dynamic
     if(#finalLocalTypeVariable#isSet)
       throw new _in::LateError::localAI("finalLocalTypeVariable");
     else {
       #finalLocalTypeVariable#isSet = true;
-      return #finalLocalTypeVariable = #t17;
+      return #finalLocalTypeVariable = finalLocalTypeVariable#param;
     }
   if(b) {
     #local#set(i){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
index ce5f3a8..e45c3f2 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
@@ -13,24 +13,24 @@
     ;
   get field1() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field1}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t1{core::int};
-  set field1(core::int #t2) → void
-    this.{self::Class::_#Class#field1} = #t2;
+  set field1(core::int field1#param) → void
+    this.{self::Class::_#Class#field1} = field1#param;
   get field2() → core::int
-    return let final core::int? #t3 = this.{self::Class::_#Class#field2}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("field2") : #t3{core::int};
-  set field2(core::int #t4) → void
-    this.{self::Class::_#Class#field2} = #t4;
+    return let final core::int? #t2 = this.{self::Class::_#Class#field2}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("field2") : #t2{core::int};
+  set field2(core::int field2#param) → void
+    this.{self::Class::_#Class#field2} = field2#param;
   get field3() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#field3}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t5{core::int};
-  set field3(core::int #t6) → void
+    return let final core::int? #t3 = this.{self::Class::_#Class#field3}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t3{core::int};
+  set field3(core::int field3#param) → void
     if(this.{self::Class::_#Class#field3}{core::int?} == null)
-      this.{self::Class::_#Class#field3} = #t6;
+      this.{self::Class::_#Class#field3} = field3#param;
     else
       throw new _in::LateError::fieldAI("field3");
   get field4() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#field4}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("field4") : #t7{core::int};
-  set field4(core::int #t8) → void
+    return let final core::int? #t4 = this.{self::Class::_#Class#field4}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("field4") : #t4{core::int};
+  set field4(core::int field4#param) → void
     if(this.{self::Class::_#Class#field4}{core::int?} == null)
-      this.{self::Class::_#Class#field4} = #t8;
+      this.{self::Class::_#Class#field4} = field4#param;
     else
       throw new _in::LateError::fieldAI("field4");
 }
@@ -43,22 +43,22 @@
     : super self::Class::•()
     ;
   get field1() → core::int
-    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t9{core::int};
-  set field1(core::int #t10) → void
-    this.{self::SubClass::_#SubClass#field1} = #t10;
+    return let final core::int? #t5 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t5{core::int};
+  set field1(core::int field1#param) → void
+    this.{self::SubClass::_#SubClass#field1} = field1#param;
   get field2() → core::int
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t11 == null ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t11{core::int};
-  set field2(core::int #t12) → void
-    this.{self::SubClass::_#SubClass#field2} = #t12;
+    return let final core::int? #t6 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t6 == null ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t6{core::int};
+  set field2(core::int field2#param) → void
+    this.{self::SubClass::_#SubClass#field2} = field2#param;
   get field3() → core::int
-    return let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t13{core::int};
-  set field3(core::int #t14) → void
+    return let final core::int? #t7 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t7{core::int};
+  set field3(core::int field3#param) → void
     if(this.{self::SubClass::_#SubClass#field3}{core::int?} == null)
-      this.{self::SubClass::_#SubClass#field3} = #t14;
+      this.{self::SubClass::_#SubClass#field3} = field3#param;
     else
       throw new _in::LateError::fieldAI("field3");
   get field4() → core::int
-    return let final core::int? #t15 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t15 == null ?{core::int} let final core::int #t16 = 0 in this.{self::SubClass::_#SubClass#field4}{core::int?} == null ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t16 : throw new _in::LateError::fieldADI("field4") : #t15{core::int};
+    return let final core::int? #t8 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t8 == null ?{core::int} let final core::int #t9 = 0 in this.{self::SubClass::_#SubClass#field4}{core::int?} == null ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t9 : throw new _in::LateError::fieldADI("field4") : #t8{core::int};
   get directField1() → core::int
     return super.{self::Class::field1};
   set directField1(core::int value) → void {
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
index f1ed5f3..e4f719d 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
@@ -13,24 +13,24 @@
     ;
   get field1() → core::int
     return let final core::int? #t1 = this.{self::Class::_#Class#field1}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t1{core::int};
-  set field1(core::int #t2) → void
-    this.{self::Class::_#Class#field1} = #t2;
+  set field1(core::int field1#param) → void
+    this.{self::Class::_#Class#field1} = field1#param;
   get field2() → core::int
-    return let final core::int? #t3 = this.{self::Class::_#Class#field2}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("field2") : #t3{core::int};
-  set field2(core::int #t4) → void
-    this.{self::Class::_#Class#field2} = #t4;
+    return let final core::int? #t2 = this.{self::Class::_#Class#field2}{core::int?} in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("field2") : #t2{core::int};
+  set field2(core::int field2#param) → void
+    this.{self::Class::_#Class#field2} = field2#param;
   get field3() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#field3}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t5{core::int};
-  set field3(core::int #t6) → void
+    return let final core::int? #t3 = this.{self::Class::_#Class#field3}{core::int?} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t3{core::int};
+  set field3(core::int field3#param) → void
     if(this.{self::Class::_#Class#field3}{core::int?} == null)
-      this.{self::Class::_#Class#field3} = #t6;
+      this.{self::Class::_#Class#field3} = field3#param;
     else
       throw new _in::LateError::fieldAI("field3");
   get field4() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#field4}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("field4") : #t7{core::int};
-  set field4(core::int #t8) → void
+    return let final core::int? #t4 = this.{self::Class::_#Class#field4}{core::int?} in #t4 == null ?{core::int} throw new _in::LateError::fieldNI("field4") : #t4{core::int};
+  set field4(core::int field4#param) → void
     if(this.{self::Class::_#Class#field4}{core::int?} == null)
-      this.{self::Class::_#Class#field4} = #t8;
+      this.{self::Class::_#Class#field4} = field4#param;
     else
       throw new _in::LateError::fieldAI("field4");
 }
@@ -43,22 +43,22 @@
     : super self::Class::•()
     ;
   get field1() → core::int
-    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t9{core::int};
-  set field1(core::int #t10) → void
-    this.{self::SubClass::_#SubClass#field1} = #t10;
+    return let final core::int? #t5 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t5 == null ?{core::int} throw new _in::LateError::fieldNI("field1") : #t5{core::int};
+  set field1(core::int field1#param) → void
+    this.{self::SubClass::_#SubClass#field1} = field1#param;
   get field2() → core::int
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t11 == null ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t11{core::int};
-  set field2(core::int #t12) → void
-    this.{self::SubClass::_#SubClass#field2} = #t12;
+    return let final core::int? #t6 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t6 == null ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t6{core::int};
+  set field2(core::int field2#param) → void
+    this.{self::SubClass::_#SubClass#field2} = field2#param;
   get field3() → core::int
-    return let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t13 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t13{core::int};
-  set field3(core::int #t14) → void
+    return let final core::int? #t7 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t7 == null ?{core::int} throw new _in::LateError::fieldNI("field3") : #t7{core::int};
+  set field3(core::int field3#param) → void
     if(this.{self::SubClass::_#SubClass#field3}{core::int?} == null)
-      this.{self::SubClass::_#SubClass#field3} = #t14;
+      this.{self::SubClass::_#SubClass#field3} = field3#param;
     else
       throw new _in::LateError::fieldAI("field3");
   get field4() → core::int
-    return let final core::int? #t15 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t15 == null ?{core::int} let final core::int #t16 = 0 in this.{self::SubClass::_#SubClass#field4}{core::int?} == null ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t16 : throw new _in::LateError::fieldADI("field4") : #t15{core::int};
+    return let final core::int? #t8 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t8 == null ?{core::int} let final core::int #t9 = 0 in this.{self::SubClass::_#SubClass#field4}{core::int?} == null ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t9 : throw new _in::LateError::fieldADI("field4") : #t8{core::int};
   get directField1() → core::int
     return super.{self::Class::field1};
   set directField1(core::int value) → void {
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
index d89b35a..a64ccbff 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
@@ -17,33 +17,33 @@
     ;
   get field1() → core::int
     return this.{self::Class::_#Class#field1#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field1}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t2) → void {
+  set field1(core::int field1#param) → void {
     this.{self::Class::_#Class#field1#isSet} = true;
-    this.{self::Class::_#Class#field1} = #t2;
+    this.{self::Class::_#Class#field1} = field1#param;
   }
   get field2() → core::int
-    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field2}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field2");
-  set field2(core::int #t4) → void {
+    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::Class::_#Class#field2}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("field2");
+  set field2(core::int field2#param) → void {
     this.{self::Class::_#Class#field2#isSet} = true;
-    this.{self::Class::_#Class#field2} = #t4;
+    this.{self::Class::_#Class#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#field3}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t6) → void
+    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field3}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::Class::_#Class#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::Class::_#Class#field3#isSet} = true;
-      this.{self::Class::_#Class#field3} = #t6;
+      this.{self::Class::_#Class#field3} = field3#param;
     }
   get field4() → core::int
-    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#field4}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field4");
-  set field4(core::int #t8) → void
+    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::Class::_#Class#field4}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("field4");
+  set field4(core::int field4#param) → void
     if(this.{self::Class::_#Class#field4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field4");
     else {
       this.{self::Class::_#Class#field4#isSet} = true;
-      this.{self::Class::_#Class#field4} = #t8;
+      this.{self::Class::_#Class#field4} = field4#param;
     }
 }
 class SubClass extends self::Class {
@@ -59,40 +59,40 @@
     : super self::Class::•()
     ;
   get field1() → core::int
-    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t10) → void {
+    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field1");
+  set field1(core::int field1#param) → void {
     this.{self::SubClass::_#SubClass#field1#isSet} = true;
-    this.{self::SubClass::_#SubClass#field1} = #t10;
+    this.{self::SubClass::_#SubClass#field1} = field1#param;
   }
   get field2() → core::int {
     if(!this.{self::SubClass::_#SubClass#field2#isSet}{core::bool}) {
       this.{self::SubClass::_#SubClass#field2} = 0;
       this.{self::SubClass::_#SubClass#field2#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t11{core::int};
+    return let final core::int? #t6 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t6{core::int};
   }
-  set field2(core::int #t12) → void {
+  set field2(core::int field2#param) → void {
     this.{self::SubClass::_#SubClass#field2#isSet} = true;
-    this.{self::SubClass::_#SubClass#field2} = #t12;
+    this.{self::SubClass::_#SubClass#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t14) → void
+    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::SubClass::_#SubClass#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::SubClass::_#SubClass#field3#isSet} = true;
-      this.{self::SubClass::_#SubClass#field3} = #t14;
+      this.{self::SubClass::_#SubClass#field3} = field3#param;
     }
   get field4() → core::int {
     if(!this.{self::SubClass::_#SubClass#field4#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t8 = 0;
       if(this.{self::SubClass::_#SubClass#field4#isSet}{core::bool})
         throw new _in::LateError::fieldADI("field4");
-      this.{self::SubClass::_#SubClass#field4} = #t15;
+      this.{self::SubClass::_#SubClass#field4} = #t8;
       this.{self::SubClass::_#SubClass#field4#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t16{core::int};
+    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t9{core::int};
   }
   get directField1() → core::int
     return super.{self::Class::field1};
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.modular.expect
index d89b35a..a64ccbff 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.modular.expect
@@ -17,33 +17,33 @@
     ;
   get field1() → core::int
     return this.{self::Class::_#Class#field1#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field1}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t2) → void {
+  set field1(core::int field1#param) → void {
     this.{self::Class::_#Class#field1#isSet} = true;
-    this.{self::Class::_#Class#field1} = #t2;
+    this.{self::Class::_#Class#field1} = field1#param;
   }
   get field2() → core::int
-    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field2}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field2");
-  set field2(core::int #t4) → void {
+    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::Class::_#Class#field2}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("field2");
+  set field2(core::int field2#param) → void {
     this.{self::Class::_#Class#field2#isSet} = true;
-    this.{self::Class::_#Class#field2} = #t4;
+    this.{self::Class::_#Class#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#field3}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t6) → void
+    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field3}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::Class::_#Class#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::Class::_#Class#field3#isSet} = true;
-      this.{self::Class::_#Class#field3} = #t6;
+      this.{self::Class::_#Class#field3} = field3#param;
     }
   get field4() → core::int
-    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#field4}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field4");
-  set field4(core::int #t8) → void
+    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::Class::_#Class#field4}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("field4");
+  set field4(core::int field4#param) → void
     if(this.{self::Class::_#Class#field4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field4");
     else {
       this.{self::Class::_#Class#field4#isSet} = true;
-      this.{self::Class::_#Class#field4} = #t8;
+      this.{self::Class::_#Class#field4} = field4#param;
     }
 }
 class SubClass extends self::Class {
@@ -59,40 +59,40 @@
     : super self::Class::•()
     ;
   get field1() → core::int
-    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t10) → void {
+    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field1");
+  set field1(core::int field1#param) → void {
     this.{self::SubClass::_#SubClass#field1#isSet} = true;
-    this.{self::SubClass::_#SubClass#field1} = #t10;
+    this.{self::SubClass::_#SubClass#field1} = field1#param;
   }
   get field2() → core::int {
     if(!this.{self::SubClass::_#SubClass#field2#isSet}{core::bool}) {
       this.{self::SubClass::_#SubClass#field2} = 0;
       this.{self::SubClass::_#SubClass#field2#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t11{core::int};
+    return let final core::int? #t6 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t6{core::int};
   }
-  set field2(core::int #t12) → void {
+  set field2(core::int field2#param) → void {
     this.{self::SubClass::_#SubClass#field2#isSet} = true;
-    this.{self::SubClass::_#SubClass#field2} = #t12;
+    this.{self::SubClass::_#SubClass#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t14) → void
+    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::SubClass::_#SubClass#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::SubClass::_#SubClass#field3#isSet} = true;
-      this.{self::SubClass::_#SubClass#field3} = #t14;
+      this.{self::SubClass::_#SubClass#field3} = field3#param;
     }
   get field4() → core::int {
     if(!this.{self::SubClass::_#SubClass#field4#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t8 = 0;
       if(this.{self::SubClass::_#SubClass#field4#isSet}{core::bool})
         throw new _in::LateError::fieldADI("field4");
-      this.{self::SubClass::_#SubClass#field4} = #t15;
+      this.{self::SubClass::_#SubClass#field4} = #t8;
       this.{self::SubClass::_#SubClass#field4#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t16{core::int};
+    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t9{core::int};
   }
   get directField1() → core::int
     return super.{self::Class::field1};
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.outline.expect
index 91bb0ab..d5af486 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.outline.expect
@@ -14,13 +14,13 @@
   synthetic constructor •() → self::Class
     ;
   get field1() → core::int;
-  set field1(core::int #t1) → void;
+  set field1(core::int field1#param) → void;
   get field2() → core::int;
-  set field2(core::int #t2) → void;
+  set field2(core::int field2#param) → void;
   get field3() → core::int;
-  set field3(core::int #t3) → void;
+  set field3(core::int field3#param) → void;
   get field4() → core::int;
-  set field4(core::int #t4) → void;
+  set field4(core::int field4#param) → void;
 }
 class SubClass extends self::Class {
   field core::int? _#SubClass#field1;
@@ -34,11 +34,11 @@
   synthetic constructor •() → self::SubClass
     ;
   get field1() → core::int;
-  set field1(core::int #t5) → void;
+  set field1(core::int field1#param) → void;
   get field2() → core::int;
-  set field2(core::int #t6) → void;
+  set field2(core::int field2#param) → void;
   get field3() → core::int;
-  set field3(core::int #t7) → void;
+  set field3(core::int field3#param) → void;
   get field4() → core::int;
   get directField1() → core::int
     ;
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
index d89b35a..a64ccbff 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
@@ -17,33 +17,33 @@
     ;
   get field1() → core::int
     return this.{self::Class::_#Class#field1#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field1}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t2) → void {
+  set field1(core::int field1#param) → void {
     this.{self::Class::_#Class#field1#isSet} = true;
-    this.{self::Class::_#Class#field1} = #t2;
+    this.{self::Class::_#Class#field1} = field1#param;
   }
   get field2() → core::int
-    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field2}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field2");
-  set field2(core::int #t4) → void {
+    return this.{self::Class::_#Class#field2#isSet}{core::bool} ?{core::int} let final core::int? #t2 = this.{self::Class::_#Class#field2}{core::int?} in #t2{core::int} : throw new _in::LateError::fieldNI("field2");
+  set field2(core::int field2#param) → void {
     this.{self::Class::_#Class#field2#isSet} = true;
-    this.{self::Class::_#Class#field2} = #t4;
+    this.{self::Class::_#Class#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#field3}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t6) → void
+    return this.{self::Class::_#Class#field3#isSet}{core::bool} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field3}{core::int?} in #t3{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::Class::_#Class#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::Class::_#Class#field3#isSet} = true;
-      this.{self::Class::_#Class#field3} = #t6;
+      this.{self::Class::_#Class#field3} = field3#param;
     }
   get field4() → core::int
-    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#field4}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field4");
-  set field4(core::int #t8) → void
+    return this.{self::Class::_#Class#field4#isSet}{core::bool} ?{core::int} let final core::int? #t4 = this.{self::Class::_#Class#field4}{core::int?} in #t4{core::int} : throw new _in::LateError::fieldNI("field4");
+  set field4(core::int field4#param) → void
     if(this.{self::Class::_#Class#field4#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field4");
     else {
       this.{self::Class::_#Class#field4#isSet} = true;
-      this.{self::Class::_#Class#field4} = #t8;
+      this.{self::Class::_#Class#field4} = field4#param;
     }
 }
 class SubClass extends self::Class {
@@ -59,40 +59,40 @@
     : super self::Class::•()
     ;
   get field1() → core::int
-    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("field1");
-  set field1(core::int #t10) → void {
+    return this.{self::SubClass::_#SubClass#field1#isSet}{core::bool} ?{core::int} let final core::int? #t5 = this.{self::SubClass::_#SubClass#field1}{core::int?} in #t5{core::int} : throw new _in::LateError::fieldNI("field1");
+  set field1(core::int field1#param) → void {
     this.{self::SubClass::_#SubClass#field1#isSet} = true;
-    this.{self::SubClass::_#SubClass#field1} = #t10;
+    this.{self::SubClass::_#SubClass#field1} = field1#param;
   }
   get field2() → core::int {
     if(!this.{self::SubClass::_#SubClass#field2#isSet}{core::bool}) {
       this.{self::SubClass::_#SubClass#field2} = 0;
       this.{self::SubClass::_#SubClass#field2#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t11{core::int};
+    return let final core::int? #t6 = this.{self::SubClass::_#SubClass#field2}{core::int?} in #t6{core::int};
   }
-  set field2(core::int #t12) → void {
+  set field2(core::int field2#param) → void {
     this.{self::SubClass::_#SubClass#field2#isSet} = true;
-    this.{self::SubClass::_#SubClass#field2} = #t12;
+    this.{self::SubClass::_#SubClass#field2} = field2#param;
   }
   get field3() → core::int
-    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t13{core::int} : throw new _in::LateError::fieldNI("field3");
-  set field3(core::int #t14) → void
+    return this.{self::SubClass::_#SubClass#field3#isSet}{core::bool} ?{core::int} let final core::int? #t7 = this.{self::SubClass::_#SubClass#field3}{core::int?} in #t7{core::int} : throw new _in::LateError::fieldNI("field3");
+  set field3(core::int field3#param) → void
     if(this.{self::SubClass::_#SubClass#field3#isSet}{core::bool})
       throw new _in::LateError::fieldAI("field3");
     else {
       this.{self::SubClass::_#SubClass#field3#isSet} = true;
-      this.{self::SubClass::_#SubClass#field3} = #t14;
+      this.{self::SubClass::_#SubClass#field3} = field3#param;
     }
   get field4() → core::int {
     if(!this.{self::SubClass::_#SubClass#field4#isSet}{core::bool}) {
-      final core::int #t15 = 0;
+      final core::int #t8 = 0;
       if(this.{self::SubClass::_#SubClass#field4#isSet}{core::bool})
         throw new _in::LateError::fieldADI("field4");
-      this.{self::SubClass::_#SubClass#field4} = #t15;
+      this.{self::SubClass::_#SubClass#field4} = #t8;
       this.{self::SubClass::_#SubClass#field4#isSet} = true;
     }
-    return let final core::int? #t16 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t16{core::int};
+    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field4}{core::int?} in #t9{core::int};
   }
   get directField1() → core::int
     return super.{self::Class::field1};
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
index 179f6d8..fbf4b98 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
@@ -12,19 +12,19 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
+  set x(core::int x#param) → void
     if(this.{self::A::_#A#x}{core::int?} == null)
-      this.{self::A::_#A#x} = #t2;
+      this.{self::A::_#A#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
   get y() → core::int?
     return this.{self::A::_#A#y#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#y}{core::int?} : throw new _in::LateError::fieldNI("y");
-  set y(core::int? #t3) → void
+  set y(core::int? y#param) → void
     if(this.{self::A::_#A#y#isSet}{core::bool})
       throw new _in::LateError::fieldAI("y");
     else {
       this.{self::A::_#A#y#isSet} = true;
-      this.{self::A::_#A#y} = #t3;
+      this.{self::A::_#A#y} = y#param;
     }
 }
 class B extends self::A {
@@ -44,13 +44,13 @@
     : super self::A::•()
     ;
   get x() → core::int
-    return let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4 == null ?{core::int} let final core::int #t5 = 2 in this.{self::C::_#C#x}{core::int?} == null ?{core::int} this.{self::C::_#C#x} = #t5 : throw new _in::LateError::fieldADI("x") : #t4{core::int};
+    return let final core::int? #t2 = this.{self::C::_#C#x}{core::int?} in #t2 == null ?{core::int} let final core::int #t3 = 2 in this.{self::C::_#C#x}{core::int?} == null ?{core::int} this.{self::C::_#C#x} = #t3 : throw new _in::LateError::fieldADI("x") : #t2{core::int};
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}{core::bool}) {
-      final core::int? #t6 = 2;
+      final core::int? #t4 = 2;
       if(this.{self::C::_#C#y#isSet}{core::bool})
         throw new _in::LateError::fieldADI("y");
-      this.{self::C::_#C#y} = #t6;
+      this.{self::C::_#C#y} = #t4;
       this.{self::C::_#C#y#isSet} = true;
     }
     return this.{self::C::_#C#y}{core::int?};
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
index f2492f7..d9bf012 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
@@ -12,19 +12,19 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
+  set x(core::int x#param) → void
     if(this.{self::A::_#A#x}{core::int?} == null)
-      this.{self::A::_#A#x} = #t2;
+      this.{self::A::_#A#x} = x#param;
     else
       throw new _in::LateError::fieldAI("x");
   get y() → core::int?
     return this.{self::A::_#A#y#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#y}{core::int?} : throw new _in::LateError::fieldNI("y");
-  set y(core::int? #t3) → void
+  set y(core::int? y#param) → void
     if(this.{self::A::_#A#y#isSet}{core::bool})
       throw new _in::LateError::fieldAI("y");
     else {
       this.{self::A::_#A#y#isSet} = true;
-      this.{self::A::_#A#y} = #t3;
+      this.{self::A::_#A#y} = y#param;
     }
 }
 class B extends self::A {
@@ -44,13 +44,13 @@
     : super self::A::•()
     ;
   get x() → core::int
-    return let final core::int? #t4 = this.{self::C::_#C#x}{core::int?} in #t4 == null ?{core::int} let final core::int #t5 = 2 in this.{self::C::_#C#x}{core::int?} == null ?{core::int} this.{self::C::_#C#x} = #t5 : throw new _in::LateError::fieldADI("x") : #t4{core::int};
+    return let final core::int? #t2 = this.{self::C::_#C#x}{core::int?} in #t2 == null ?{core::int} let final core::int #t3 = 2 in this.{self::C::_#C#x}{core::int?} == null ?{core::int} this.{self::C::_#C#x} = #t3 : throw new _in::LateError::fieldADI("x") : #t2{core::int};
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}{core::bool}) {
-      final core::int? #t6 = 2;
+      final core::int? #t4 = 2;
       if(this.{self::C::_#C#y#isSet}{core::bool})
         throw new _in::LateError::fieldADI("y");
-      this.{self::C::_#C#y} = #t6;
+      this.{self::C::_#C#y} = #t4;
       this.{self::C::_#C#y#isSet} = true;
     }
     return this.{self::C::_#C#y}{core::int?};
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
index e46b981..f89b6db 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
@@ -13,21 +13,21 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void
+  set x(core::int x#param) → void
     if(this.{self::A::_#A#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::A::_#A#x#isSet} = true;
-      this.{self::A::_#A#x} = #t2;
+      this.{self::A::_#A#x} = x#param;
     }
   get y() → core::int?
     return this.{self::A::_#A#y#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#y}{core::int?} : throw new _in::LateError::fieldNI("y");
-  set y(core::int? #t3) → void
+  set y(core::int? y#param) → void
     if(this.{self::A::_#A#y#isSet}{core::bool})
       throw new _in::LateError::fieldAI("y");
     else {
       this.{self::A::_#A#y#isSet} = true;
-      this.{self::A::_#A#y} = #t3;
+      this.{self::A::_#A#y} = y#param;
     }
 }
 class B extends self::A {
@@ -49,20 +49,20 @@
     ;
   get x() → core::int {
     if(!this.{self::C::_#C#x#isSet}{core::bool}) {
-      final core::int #t4 = 2;
+      final core::int #t2 = 2;
       if(this.{self::C::_#C#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::C::_#C#x} = #t4;
+      this.{self::C::_#C#x} = #t2;
       this.{self::C::_#C#x#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::C::_#C#x}{core::int?} in #t3{core::int};
   }
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}{core::bool}) {
-      final core::int? #t6 = 2;
+      final core::int? #t4 = 2;
       if(this.{self::C::_#C#y#isSet}{core::bool})
         throw new _in::LateError::fieldADI("y");
-      this.{self::C::_#C#y} = #t6;
+      this.{self::C::_#C#y} = #t4;
       this.{self::C::_#C#y#isSet} = true;
     }
     return this.{self::C::_#C#y}{core::int?};
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.modular.expect
index e46b981..f89b6db 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.modular.expect
@@ -13,21 +13,21 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void
+  set x(core::int x#param) → void
     if(this.{self::A::_#A#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::A::_#A#x#isSet} = true;
-      this.{self::A::_#A#x} = #t2;
+      this.{self::A::_#A#x} = x#param;
     }
   get y() → core::int?
     return this.{self::A::_#A#y#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#y}{core::int?} : throw new _in::LateError::fieldNI("y");
-  set y(core::int? #t3) → void
+  set y(core::int? y#param) → void
     if(this.{self::A::_#A#y#isSet}{core::bool})
       throw new _in::LateError::fieldAI("y");
     else {
       this.{self::A::_#A#y#isSet} = true;
-      this.{self::A::_#A#y} = #t3;
+      this.{self::A::_#A#y} = y#param;
     }
 }
 class B extends self::A {
@@ -49,20 +49,20 @@
     ;
   get x() → core::int {
     if(!this.{self::C::_#C#x#isSet}{core::bool}) {
-      final core::int #t4 = 2;
+      final core::int #t2 = 2;
       if(this.{self::C::_#C#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::C::_#C#x} = #t4;
+      this.{self::C::_#C#x} = #t2;
       this.{self::C::_#C#x#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::C::_#C#x}{core::int?} in #t3{core::int};
   }
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}{core::bool}) {
-      final core::int? #t6 = 2;
+      final core::int? #t4 = 2;
       if(this.{self::C::_#C#y#isSet}{core::bool})
         throw new _in::LateError::fieldADI("y");
-      this.{self::C::_#C#y} = #t6;
+      this.{self::C::_#C#y} = #t4;
       this.{self::C::_#C#y#isSet} = true;
     }
     return this.{self::C::_#C#y}{core::int?};
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.outline.expect
index b62fb76..03bd85a 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.outline.expect
@@ -10,9 +10,9 @@
   synthetic constructor •() → self::A
     ;
   get x() → core::int;
-  set x(core::int #t1) → void;
+  set x(core::int x#param) → void;
   get y() → core::int?;
-  set y(core::int? #t2) → void;
+  set y(core::int? y#param) → void;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
index e46b981..f89b6db 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
@@ -13,21 +13,21 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void
+  set x(core::int x#param) → void
     if(this.{self::A::_#A#x#isSet}{core::bool})
       throw new _in::LateError::fieldAI("x");
     else {
       this.{self::A::_#A#x#isSet} = true;
-      this.{self::A::_#A#x} = #t2;
+      this.{self::A::_#A#x} = x#param;
     }
   get y() → core::int?
     return this.{self::A::_#A#y#isSet}{core::bool} ?{core::int?} this.{self::A::_#A#y}{core::int?} : throw new _in::LateError::fieldNI("y");
-  set y(core::int? #t3) → void
+  set y(core::int? y#param) → void
     if(this.{self::A::_#A#y#isSet}{core::bool})
       throw new _in::LateError::fieldAI("y");
     else {
       this.{self::A::_#A#y#isSet} = true;
-      this.{self::A::_#A#y} = #t3;
+      this.{self::A::_#A#y} = y#param;
     }
 }
 class B extends self::A {
@@ -49,20 +49,20 @@
     ;
   get x() → core::int {
     if(!this.{self::C::_#C#x#isSet}{core::bool}) {
-      final core::int #t4 = 2;
+      final core::int #t2 = 2;
       if(this.{self::C::_#C#x#isSet}{core::bool})
         throw new _in::LateError::fieldADI("x");
-      this.{self::C::_#C#x} = #t4;
+      this.{self::C::_#C#x} = #t2;
       this.{self::C::_#C#x#isSet} = true;
     }
-    return let final core::int? #t5 = this.{self::C::_#C#x}{core::int?} in #t5{core::int};
+    return let final core::int? #t3 = this.{self::C::_#C#x}{core::int?} in #t3{core::int};
   }
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}{core::bool}) {
-      final core::int? #t6 = 2;
+      final core::int? #t4 = 2;
       if(this.{self::C::_#C#y#isSet}{core::bool})
         throw new _in::LateError::fieldADI("y");
-      this.{self::C::_#C#y} = #t6;
+      this.{self::C::_#C#y} = #t4;
       this.{self::C::_#C#y#isSet} = true;
     }
     return this.{self::C::_#C#y}{core::int?};
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.strong.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.strong.expect
index 7b44b11..4a3aa95 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.strong.expect
@@ -15,8 +15,8 @@
     ;
   get _privateField1() → core::int
     return let final core::int? #t1 = this.{self::_Class::_#_Class#_privateField1}{core::int?} in #t1 == null ?{core::int} this.{self::_Class::_#_Class#_privateField1} = 1 : #t1{core::int};
-  set _privateField1(core::int #t2) → void
-    this.{self::_Class::_#_Class#_privateField1} = #t2;
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void
+    this.{self::_Class::_#_Class#_privateField1} = library org-dartlang-testcase:///private_members_part.dart::_privateField1#param;
   get _privateField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateField2#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateField2} = 1;
@@ -24,14 +24,14 @@
     }
     return this.{self::_Class::_#_Class#_privateField2}{core::int?};
   }
-  set _privateField2(core::int? #t3) → void {
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void {
     this.{self::_Class::_#_Class#_privateField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField2} = #t3;
+    this.{self::_Class::_#_Class#_privateField2} = library org-dartlang-testcase:///private_members_part.dart::_privateField2#param;
   }
   get _privateFinalField1() → core::int
-    return let final core::int? #t4 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t4 == null ?{core::int} this.{self::_Class::_#_Class#_privateFinalField1} = 1 : #t4{core::int};
-  set _privateFinalField1(core::int #t5) → void
-    this.{self::_Class::_#_Class#_privateFinalField1} = #t5;
+    return let final core::int? #t2 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t2 == null ?{core::int} this.{self::_Class::_#_Class#_privateFinalField1} = 1 : #t2{core::int};
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void
+    this.{self::_Class::_#_Class#_privateFinalField1} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param;
   get _privateFinalField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateFinalField2#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateFinalField2} = 1;
@@ -39,9 +39,9 @@
     }
     return this.{self::_Class::_#_Class#_privateFinalField2}{core::int?};
   }
-  set _privateFinalField2(core::int? #t6) → void {
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField2} = #t6;
+    this.{self::_Class::_#_Class#_privateFinalField2} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param;
   }
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
@@ -78,9 +78,9 @@
   self::_Extension|_privateFinalField2;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1() → core::int
-  return let final core::int? #t7 = self::_#_Extension|_privateField1 in #t7 == null ?{core::int} self::_#_Extension|_privateField1 = 1 : #t7{core::int};
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t8) → void
-  self::_#_Extension|_privateField1 = #t8;
+  return let final core::int? #t3 = self::_#_Extension|_privateField1 in #t3 == null ?{core::int} self::_#_Extension|_privateField1 = 1 : #t3{core::int};
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void
+  self::_#_Extension|_privateField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int? {
   if(!self::_#_Extension|_privateField2#isSet) {
     self::_#_Extension|_privateField2 = 1;
@@ -88,14 +88,14 @@
   }
   return self::_#_Extension|_privateField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t9) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void {
   self::_#_Extension|_privateField2#isSet = true;
-  self::_#_Extension|_privateField2 = #t9;
+  self::_#_Extension|_privateField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int
-  return let final core::int? #t10 = self::_#_Extension|_privateFinalField1 in #t10 == null ?{core::int} self::_#_Extension|_privateFinalField1 = 1 : #t10{core::int};
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t11) → void
-  self::_#_Extension|_privateFinalField1 = #t11;
+  return let final core::int? #t4 = self::_#_Extension|_privateFinalField1 in #t4 == null ?{core::int} self::_#_Extension|_privateFinalField1 = 1 : #t4{core::int};
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void
+  self::_#_Extension|_privateFinalField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int? {
   if(!self::_#_Extension|_privateFinalField2#isSet) {
     self::_#_Extension|_privateFinalField2 = 1;
@@ -103,7 +103,7 @@
   }
   return self::_#_Extension|_privateFinalField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t12) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void {
   self::_#_Extension|_privateFinalField2#isSet = true;
-  self::_#_Extension|_privateFinalField2 = #t12;
+  self::_#_Extension|_privateFinalField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param;
 }
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.strong.transformed.expect
index 7b44b11..4a3aa95 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.strong.transformed.expect
@@ -15,8 +15,8 @@
     ;
   get _privateField1() → core::int
     return let final core::int? #t1 = this.{self::_Class::_#_Class#_privateField1}{core::int?} in #t1 == null ?{core::int} this.{self::_Class::_#_Class#_privateField1} = 1 : #t1{core::int};
-  set _privateField1(core::int #t2) → void
-    this.{self::_Class::_#_Class#_privateField1} = #t2;
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void
+    this.{self::_Class::_#_Class#_privateField1} = library org-dartlang-testcase:///private_members_part.dart::_privateField1#param;
   get _privateField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateField2#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateField2} = 1;
@@ -24,14 +24,14 @@
     }
     return this.{self::_Class::_#_Class#_privateField2}{core::int?};
   }
-  set _privateField2(core::int? #t3) → void {
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void {
     this.{self::_Class::_#_Class#_privateField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField2} = #t3;
+    this.{self::_Class::_#_Class#_privateField2} = library org-dartlang-testcase:///private_members_part.dart::_privateField2#param;
   }
   get _privateFinalField1() → core::int
-    return let final core::int? #t4 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t4 == null ?{core::int} this.{self::_Class::_#_Class#_privateFinalField1} = 1 : #t4{core::int};
-  set _privateFinalField1(core::int #t5) → void
-    this.{self::_Class::_#_Class#_privateFinalField1} = #t5;
+    return let final core::int? #t2 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t2 == null ?{core::int} this.{self::_Class::_#_Class#_privateFinalField1} = 1 : #t2{core::int};
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void
+    this.{self::_Class::_#_Class#_privateFinalField1} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param;
   get _privateFinalField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateFinalField2#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateFinalField2} = 1;
@@ -39,9 +39,9 @@
     }
     return this.{self::_Class::_#_Class#_privateFinalField2}{core::int?};
   }
-  set _privateFinalField2(core::int? #t6) → void {
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField2} = #t6;
+    this.{self::_Class::_#_Class#_privateFinalField2} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param;
   }
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
@@ -78,9 +78,9 @@
   self::_Extension|_privateFinalField2;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1() → core::int
-  return let final core::int? #t7 = self::_#_Extension|_privateField1 in #t7 == null ?{core::int} self::_#_Extension|_privateField1 = 1 : #t7{core::int};
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t8) → void
-  self::_#_Extension|_privateField1 = #t8;
+  return let final core::int? #t3 = self::_#_Extension|_privateField1 in #t3 == null ?{core::int} self::_#_Extension|_privateField1 = 1 : #t3{core::int};
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void
+  self::_#_Extension|_privateField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int? {
   if(!self::_#_Extension|_privateField2#isSet) {
     self::_#_Extension|_privateField2 = 1;
@@ -88,14 +88,14 @@
   }
   return self::_#_Extension|_privateField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t9) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void {
   self::_#_Extension|_privateField2#isSet = true;
-  self::_#_Extension|_privateField2 = #t9;
+  self::_#_Extension|_privateField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int
-  return let final core::int? #t10 = self::_#_Extension|_privateFinalField1 in #t10 == null ?{core::int} self::_#_Extension|_privateFinalField1 = 1 : #t10{core::int};
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t11) → void
-  self::_#_Extension|_privateFinalField1 = #t11;
+  return let final core::int? #t4 = self::_#_Extension|_privateFinalField1 in #t4 == null ?{core::int} self::_#_Extension|_privateFinalField1 = 1 : #t4{core::int};
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void
+  self::_#_Extension|_privateFinalField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int? {
   if(!self::_#_Extension|_privateFinalField2#isSet) {
     self::_#_Extension|_privateFinalField2 = 1;
@@ -103,7 +103,7 @@
   }
   return self::_#_Extension|_privateFinalField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t12) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void {
   self::_#_Extension|_privateFinalField2#isSet = true;
-  self::_#_Extension|_privateFinalField2 = #t12;
+  self::_#_Extension|_privateFinalField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param;
 }
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.expect
index 10fbd90..97f7725 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.expect
@@ -22,9 +22,9 @@
     }
     return let final core::int? #t1 = this.{self::_Class::_#_Class#_privateField1}{core::int?} in #t1{core::int};
   }
-  set _privateField1(core::int #t2) → void {
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void {
     this.{self::_Class::_#_Class#_privateField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField1} = #t2;
+    this.{self::_Class::_#_Class#_privateField1} = library org-dartlang-testcase:///private_members_part.dart::_privateField1#param;
   }
   get _privateField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateField2#isSet}{core::bool}) {
@@ -33,20 +33,20 @@
     }
     return this.{self::_Class::_#_Class#_privateField2}{core::int?};
   }
-  set _privateField2(core::int? #t3) → void {
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void {
     this.{self::_Class::_#_Class#_privateField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField2} = #t3;
+    this.{self::_Class::_#_Class#_privateField2} = library org-dartlang-testcase:///private_members_part.dart::_privateField2#param;
   }
   get _privateFinalField1() → core::int {
     if(!this.{self::_Class::_#_Class#_privateFinalField1#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateFinalField1} = 1;
       this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t4{core::int};
+    return let final core::int? #t2 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t2{core::int};
   }
-  set _privateFinalField1(core::int #t5) → void {
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField1} = #t5;
+    this.{self::_Class::_#_Class#_privateFinalField1} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param;
   }
   get _privateFinalField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateFinalField2#isSet}{core::bool}) {
@@ -55,9 +55,9 @@
     }
     return this.{self::_Class::_#_Class#_privateFinalField2}{core::int?};
   }
-  set _privateFinalField2(core::int? #t6) → void {
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField2} = #t6;
+    this.{self::_Class::_#_Class#_privateFinalField2} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param;
   }
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
@@ -102,11 +102,11 @@
     self::_#_Extension|_privateField1 = 1;
     self::_#_Extension|_privateField1#isSet = true;
   }
-  return let final core::int? #t7 = self::_#_Extension|_privateField1 in #t7{core::int};
+  return let final core::int? #t3 = self::_#_Extension|_privateField1 in #t3{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t8) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void {
   self::_#_Extension|_privateField1#isSet = true;
-  self::_#_Extension|_privateField1 = #t8;
+  self::_#_Extension|_privateField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int? {
   if(!self::_#_Extension|_privateField2#isSet) {
@@ -115,20 +115,20 @@
   }
   return self::_#_Extension|_privateField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t9) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void {
   self::_#_Extension|_privateField2#isSet = true;
-  self::_#_Extension|_privateField2 = #t9;
+  self::_#_Extension|_privateField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int {
   if(!self::_#_Extension|_privateFinalField1#isSet) {
     self::_#_Extension|_privateFinalField1 = 1;
     self::_#_Extension|_privateFinalField1#isSet = true;
   }
-  return let final core::int? #t10 = self::_#_Extension|_privateFinalField1 in #t10{core::int};
+  return let final core::int? #t4 = self::_#_Extension|_privateFinalField1 in #t4{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t11) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void {
   self::_#_Extension|_privateFinalField1#isSet = true;
-  self::_#_Extension|_privateFinalField1 = #t11;
+  self::_#_Extension|_privateFinalField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int? {
   if(!self::_#_Extension|_privateFinalField2#isSet) {
@@ -137,7 +137,7 @@
   }
   return self::_#_Extension|_privateFinalField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t12) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void {
   self::_#_Extension|_privateFinalField2#isSet = true;
-  self::_#_Extension|_privateFinalField2 = #t12;
+  self::_#_Extension|_privateFinalField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param;
 }
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.modular.expect
index 10fbd90..97f7725 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.modular.expect
@@ -22,9 +22,9 @@
     }
     return let final core::int? #t1 = this.{self::_Class::_#_Class#_privateField1}{core::int?} in #t1{core::int};
   }
-  set _privateField1(core::int #t2) → void {
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void {
     this.{self::_Class::_#_Class#_privateField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField1} = #t2;
+    this.{self::_Class::_#_Class#_privateField1} = library org-dartlang-testcase:///private_members_part.dart::_privateField1#param;
   }
   get _privateField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateField2#isSet}{core::bool}) {
@@ -33,20 +33,20 @@
     }
     return this.{self::_Class::_#_Class#_privateField2}{core::int?};
   }
-  set _privateField2(core::int? #t3) → void {
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void {
     this.{self::_Class::_#_Class#_privateField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField2} = #t3;
+    this.{self::_Class::_#_Class#_privateField2} = library org-dartlang-testcase:///private_members_part.dart::_privateField2#param;
   }
   get _privateFinalField1() → core::int {
     if(!this.{self::_Class::_#_Class#_privateFinalField1#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateFinalField1} = 1;
       this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t4{core::int};
+    return let final core::int? #t2 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t2{core::int};
   }
-  set _privateFinalField1(core::int #t5) → void {
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField1} = #t5;
+    this.{self::_Class::_#_Class#_privateFinalField1} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param;
   }
   get _privateFinalField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateFinalField2#isSet}{core::bool}) {
@@ -55,9 +55,9 @@
     }
     return this.{self::_Class::_#_Class#_privateFinalField2}{core::int?};
   }
-  set _privateFinalField2(core::int? #t6) → void {
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField2} = #t6;
+    this.{self::_Class::_#_Class#_privateFinalField2} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param;
   }
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
@@ -102,11 +102,11 @@
     self::_#_Extension|_privateField1 = 1;
     self::_#_Extension|_privateField1#isSet = true;
   }
-  return let final core::int? #t7 = self::_#_Extension|_privateField1 in #t7{core::int};
+  return let final core::int? #t3 = self::_#_Extension|_privateField1 in #t3{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t8) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void {
   self::_#_Extension|_privateField1#isSet = true;
-  self::_#_Extension|_privateField1 = #t8;
+  self::_#_Extension|_privateField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int? {
   if(!self::_#_Extension|_privateField2#isSet) {
@@ -115,20 +115,20 @@
   }
   return self::_#_Extension|_privateField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t9) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void {
   self::_#_Extension|_privateField2#isSet = true;
-  self::_#_Extension|_privateField2 = #t9;
+  self::_#_Extension|_privateField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int {
   if(!self::_#_Extension|_privateFinalField1#isSet) {
     self::_#_Extension|_privateFinalField1 = 1;
     self::_#_Extension|_privateFinalField1#isSet = true;
   }
-  return let final core::int? #t10 = self::_#_Extension|_privateFinalField1 in #t10{core::int};
+  return let final core::int? #t4 = self::_#_Extension|_privateFinalField1 in #t4{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t11) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void {
   self::_#_Extension|_privateFinalField1#isSet = true;
-  self::_#_Extension|_privateFinalField1 = #t11;
+  self::_#_Extension|_privateFinalField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int? {
   if(!self::_#_Extension|_privateFinalField2#isSet) {
@@ -137,7 +137,7 @@
   }
   return self::_#_Extension|_privateFinalField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t12) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void {
   self::_#_Extension|_privateFinalField2#isSet = true;
-  self::_#_Extension|_privateFinalField2 = #t12;
+  self::_#_Extension|_privateFinalField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param;
 }
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.outline.expect
index 88c4850ad..2d4f5abd 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.outline.expect
@@ -15,13 +15,13 @@
   synthetic constructor •() → self::_Class
     ;
   get _privateField1() → core::int;
-  set _privateField1(core::int #t1) → void;
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void;
   get _privateField2() → core::int?;
-  set _privateField2(core::int? #t2) → void;
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void;
   get _privateFinalField1() → core::int;
-  set _privateFinalField1(core::int #t3) → void;
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void;
   get _privateFinalField2() → core::int?;
-  set _privateFinalField2(core::int? #t4) → void;
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void;
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
   static field _privateField1 = self::_#_Extension|_privateField1;
@@ -52,10 +52,10 @@
 static method main() → dynamic
   ;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1() → core::int;
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t5) → void;
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int?;
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t6) → void;
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int;
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t7) → void;
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void;
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int?;
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t8) → void;
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void;
diff --git a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.transformed.expect
index 10fbd90..97f7725 100644
--- a/pkg/front_end/testcases/late_lowering/private_members.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/private_members.dart.weak.transformed.expect
@@ -22,9 +22,9 @@
     }
     return let final core::int? #t1 = this.{self::_Class::_#_Class#_privateField1}{core::int?} in #t1{core::int};
   }
-  set _privateField1(core::int #t2) → void {
+  set _privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateField1#param) → void {
     this.{self::_Class::_#_Class#_privateField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField1} = #t2;
+    this.{self::_Class::_#_Class#_privateField1} = library org-dartlang-testcase:///private_members_part.dart::_privateField1#param;
   }
   get _privateField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateField2#isSet}{core::bool}) {
@@ -33,20 +33,20 @@
     }
     return this.{self::_Class::_#_Class#_privateField2}{core::int?};
   }
-  set _privateField2(core::int? #t3) → void {
+  set _privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateField2#param) → void {
     this.{self::_Class::_#_Class#_privateField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateField2} = #t3;
+    this.{self::_Class::_#_Class#_privateField2} = library org-dartlang-testcase:///private_members_part.dart::_privateField2#param;
   }
   get _privateFinalField1() → core::int {
     if(!this.{self::_Class::_#_Class#_privateFinalField1#isSet}{core::bool}) {
       this.{self::_Class::_#_Class#_privateFinalField1} = 1;
       this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
     }
-    return let final core::int? #t4 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t4{core::int};
+    return let final core::int? #t2 = this.{self::_Class::_#_Class#_privateFinalField1}{core::int?} in #t2{core::int};
   }
-  set _privateFinalField1(core::int #t5) → void {
+  set _privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField1#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField1} = #t5;
+    this.{self::_Class::_#_Class#_privateFinalField1} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField1#param;
   }
   get _privateFinalField2() → core::int? {
     if(!this.{self::_Class::_#_Class#_privateFinalField2#isSet}{core::bool}) {
@@ -55,9 +55,9 @@
     }
     return this.{self::_Class::_#_Class#_privateFinalField2}{core::int?};
   }
-  set _privateFinalField2(core::int? #t6) → void {
+  set _privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param) → void {
     this.{self::_Class::_#_Class#_privateFinalField2#isSet} = true;
-    this.{self::_Class::_#_Class#_privateFinalField2} = #t6;
+    this.{self::_Class::_#_Class#_privateFinalField2} = library org-dartlang-testcase:///private_members_part.dart::_privateFinalField2#param;
   }
 }
 extension _Extension on core::int { // from org-dartlang-testcase:///private_members_part.dart
@@ -102,11 +102,11 @@
     self::_#_Extension|_privateField1 = 1;
     self::_#_Extension|_privateField1#isSet = true;
   }
-  return let final core::int? #t7 = self::_#_Extension|_privateField1 in #t7{core::int};
+  return let final core::int? #t3 = self::_#_Extension|_privateField1 in #t3{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int #t8) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param) → void {
   self::_#_Extension|_privateField1#isSet = true;
-  self::_#_Extension|_privateField1 = #t8;
+  self::_#_Extension|_privateField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2() → core::int? {
   if(!self::_#_Extension|_privateField2#isSet) {
@@ -115,20 +115,20 @@
   }
   return self::_#_Extension|_privateField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? #t9) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param) → void {
   self::_#_Extension|_privateField2#isSet = true;
-  self::_#_Extension|_privateField2 = #t9;
+  self::_#_Extension|_privateField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateField2#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1() → core::int {
   if(!self::_#_Extension|_privateFinalField1#isSet) {
     self::_#_Extension|_privateFinalField1 = 1;
     self::_#_Extension|_privateFinalField1#isSet = true;
   }
-  return let final core::int? #t10 = self::_#_Extension|_privateFinalField1 in #t10{core::int};
+  return let final core::int? #t4 = self::_#_Extension|_privateFinalField1 in #t4{core::int};
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int #t11) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField1(core::int library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param) → void {
   self::_#_Extension|_privateFinalField1#isSet = true;
-  self::_#_Extension|_privateFinalField1 = #t11;
+  self::_#_Extension|_privateFinalField1 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField1#param;
 }
 static get /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2() → core::int? {
   if(!self::_#_Extension|_privateFinalField2#isSet) {
@@ -137,7 +137,7 @@
   }
   return self::_#_Extension|_privateFinalField2;
 }
-static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? #t12) → void {
+static set /* from org-dartlang-testcase:///private_members_part.dart */ _Extension|_privateFinalField2(core::int? library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param) → void {
   self::_#_Extension|_privateFinalField2#isSet = true;
-  self::_#_Extension|_privateFinalField2 = #t12;
+  self::_#_Extension|_privateFinalField2 = library org-dartlang-testcase:///private_members_part.dart::_Extension|_privateFinalField2#param;
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
index 8b9bf40..1d0cc75 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.expect
@@ -17,9 +17,9 @@
       }
       return #result{self::Class::E%};
     }
-    function #result#set(self::Class::E% #t1) → dynamic {
+    function #result#set(self::Class::E% result#param) → dynamic {
       #result#isSet = true;
-      return #result = #t1;
+      return #result = result#param;
     }
     return #result#get(){() → self::Class::E%};
   }
@@ -27,9 +27,9 @@
 static method returnNonNullable(core::int value) → core::int {
   lowered core::int? #result;
   function #result#get() → core::int
-    return let final core::int? #t2 = #result in #t2 == null ?{core::int} #result = value : #t2{core::int};
-  function #result#set(core::int #t3) → dynamic
-    return #result = #t3;
+    return let final core::int? #t1 = #result in #t1 == null ?{core::int} #result = value : #t1{core::int};
+  function #result#set(core::int result#param) → dynamic
+    return #result = result#param;
   return #result#get(){() → core::int};
 }
 static method returnNullable(core::int? value) → core::int? {
@@ -42,9 +42,9 @@
     }
     return #result;
   }
-  function #result#set(core::int? #t4) → dynamic {
+  function #result#set(core::int? result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t4;
+    return #result = result#param;
   }
   return #result#get(){() → core::int?};
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
index 8b9bf40..1d0cc75 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.strong.transformed.expect
@@ -17,9 +17,9 @@
       }
       return #result{self::Class::E%};
     }
-    function #result#set(self::Class::E% #t1) → dynamic {
+    function #result#set(self::Class::E% result#param) → dynamic {
       #result#isSet = true;
-      return #result = #t1;
+      return #result = result#param;
     }
     return #result#get(){() → self::Class::E%};
   }
@@ -27,9 +27,9 @@
 static method returnNonNullable(core::int value) → core::int {
   lowered core::int? #result;
   function #result#get() → core::int
-    return let final core::int? #t2 = #result in #t2 == null ?{core::int} #result = value : #t2{core::int};
-  function #result#set(core::int #t3) → dynamic
-    return #result = #t3;
+    return let final core::int? #t1 = #result in #t1 == null ?{core::int} #result = value : #t1{core::int};
+  function #result#set(core::int result#param) → dynamic
+    return #result = result#param;
   return #result#get(){() → core::int};
 }
 static method returnNullable(core::int? value) → core::int? {
@@ -42,9 +42,9 @@
     }
     return #result;
   }
-  function #result#set(core::int? #t4) → dynamic {
+  function #result#set(core::int? result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t4;
+    return #result = result#param;
   }
   return #result#get(){() → core::int?};
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
index 3733586..36c861d 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
@@ -17,9 +17,9 @@
       }
       return #result{self::Class::E%};
     }
-    function #result#set(self::Class::E% #t1) → dynamic {
+    function #result#set(self::Class::E% result#param) → dynamic {
       #result#isSet = true;
-      return #result = #t1;
+      return #result = result#param;
     }
     return #result#get(){() → self::Class::E%};
   }
@@ -34,9 +34,9 @@
     }
     return #result{core::int};
   }
-  function #result#set(core::int #t2) → dynamic {
+  function #result#set(core::int result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t2;
+    return #result = result#param;
   }
   return #result#get(){() → core::int};
 }
@@ -50,9 +50,9 @@
     }
     return #result;
   }
-  function #result#set(core::int? #t3) → dynamic {
+  function #result#set(core::int? result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t3;
+    return #result = result#param;
   }
   return #result#get(){() → core::int?};
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.modular.expect
index 3733586..36c861d 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.modular.expect
@@ -17,9 +17,9 @@
       }
       return #result{self::Class::E%};
     }
-    function #result#set(self::Class::E% #t1) → dynamic {
+    function #result#set(self::Class::E% result#param) → dynamic {
       #result#isSet = true;
-      return #result = #t1;
+      return #result = result#param;
     }
     return #result#get(){() → self::Class::E%};
   }
@@ -34,9 +34,9 @@
     }
     return #result{core::int};
   }
-  function #result#set(core::int #t2) → dynamic {
+  function #result#set(core::int result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t2;
+    return #result = result#param;
   }
   return #result#get(){() → core::int};
 }
@@ -50,9 +50,9 @@
     }
     return #result;
   }
-  function #result#set(core::int? #t3) → dynamic {
+  function #result#set(core::int? result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t3;
+    return #result = result#param;
   }
   return #result#get(){() → core::int?};
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
index 3733586..36c861d 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
@@ -17,9 +17,9 @@
       }
       return #result{self::Class::E%};
     }
-    function #result#set(self::Class::E% #t1) → dynamic {
+    function #result#set(self::Class::E% result#param) → dynamic {
       #result#isSet = true;
-      return #result = #t1;
+      return #result = result#param;
     }
     return #result#get(){() → self::Class::E%};
   }
@@ -34,9 +34,9 @@
     }
     return #result{core::int};
   }
-  function #result#set(core::int #t2) → dynamic {
+  function #result#set(core::int result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t2;
+    return #result = result#param;
   }
   return #result#get(){() → core::int};
 }
@@ -50,9 +50,9 @@
     }
     return #result;
   }
-  function #result#set(core::int? #t3) → dynamic {
+  function #result#set(core::int? result#param) → dynamic {
     #result#isSet = true;
-    return #result = #t3;
+    return #result = result#param;
   }
   return #result#get(){() → core::int?};
 }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
index 6d6de22..f1fee7e 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
@@ -17,34 +17,34 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField") : #t1{core::int};
-  static set uninitializedNonFinalStaticField(core::int #t2) → void
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   static get uninitializedFinalStaticField() → core::int
-    return let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t3{core::int};
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t2{core::int};
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField == null)
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
   static get initializedNonFinalStaticField() → core::int
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t5{core::int};
-  static set initializedNonFinalStaticField(core::int #t6) → void
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t3{core::int};
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   static get initializedFinalStaticField() → core::int
-    return let final core::int? #t7 = self::Class::_#initializedFinalStaticField in #t7 == null ?{core::int} let final core::int #t8 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t8 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t7{core::int};
+    return let final core::int? #t4 = self::Class::_#initializedFinalStaticField in #t4 == null ?{core::int} let final core::int #t5 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t5 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t4{core::int};
   get uninitializedFinalInstanceField() → core::int
-    return let final core::int? #t9 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t9{core::int};
-  set uninitializedFinalInstanceField(core::int #t10) → void
+    return let final core::int? #t6 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t6{core::int};
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t10;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
   get initializedNonFinalInstanceField() → core::int
-    return let final core::int? #t11 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t11 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t11{core::int};
-  set initializedNonFinalInstanceField(core::int #t12) → void
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t12;
+    return let final core::int? #t7 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t7 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t7{core::int};
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   get initializedFinalInstanceField() → core::int
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t13 == null ?{core::int} let final core::int #t14 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t14 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t13{core::int};
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t8 == null ?{core::int} let final core::int #t9 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t9 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t8{core::int};
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
 static field core::int? _#uninitializedFinalTopLevelField = null;
@@ -56,32 +56,32 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t15) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t15;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t16 = #nonNullableUninitializedNonFinalLocal in #t16 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t16{core::int};
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t17) → dynamic
-    return #nonNullableUninitializedNonFinalLocal = #t17;
+    return let final core::int? #t10 = #nonNullableUninitializedNonFinalLocal in #t10 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t10{core::int};
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t18) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t18;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   function #nonNullableUninitializedFinalLocal#get() → core::int
-    return let final core::int? #t19 = #nonNullableUninitializedFinalLocal in #t19 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t19{core::int};
-  function #nonNullableUninitializedFinalLocal#set(core::int #t20) → dynamic
+    return let final core::int? #t11 = #nonNullableUninitializedFinalLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t11{core::int};
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal == null)
-      return #nonNullableUninitializedFinalLocal = #t20;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
   lowered core::int? #nullableInitializedNonFinalLocal;
@@ -93,45 +93,45 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t21) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t21;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   function #nonNullableInitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t22 = #nonNullableInitializedNonFinalLocal in #t22 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t22{core::int};
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t23) → dynamic
-    return #nonNullableInitializedNonFinalLocal = #t23;
+    return let final core::int? #t12 = #nonNullableInitializedNonFinalLocal in #t12 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t12{core::int};
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t24 = 0;
+      final core::int? #t13 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t24;
+      #nullableInitializedFinalLocal = #t13;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
   }
   lowered final core::int? #nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t25 = #nonNullableInitializedFinalLocal in #t25 == null ?{core::int} let final core::int #t26 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t26 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t25{core::int};
+    return let final core::int? #t14 = #nonNullableInitializedFinalLocal in #t14 == null ?{core::int} let final core::int #t15 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t15 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t14{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t28) → void
-  self::_#uninitializedNonFinalTopLevelField = #t28;
+  return let final core::int? #t16 = self::_#uninitializedNonFinalTopLevelField in #t16 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t16{core::int};
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
-static set uninitializedFinalTopLevelField(core::int #t30) → void
+  return let final core::int? #t17 = self::_#uninitializedFinalTopLevelField in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t17{core::int};
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField == null)
-    self::_#uninitializedFinalTopLevelField = #t30;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
-static set initializedNonFinalTopLevelField(core::int #t32) → void
-  self::_#initializedNonFinalTopLevelField = #t32;
+  return let final core::int? #t18 = self::_#initializedNonFinalTopLevelField in #t18 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t18{core::int};
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33 == null ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
+  return let final core::int? #t19 = self::_#initializedFinalTopLevelField in #t19 == null ?{core::int} let final core::int #t20 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t20 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t19{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
index 1bc9058..8eac5e6 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
@@ -17,34 +17,34 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField") : #t1{core::int};
-  static set uninitializedNonFinalStaticField(core::int #t2) → void
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   static get uninitializedFinalStaticField() → core::int
-    return let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t3{core::int};
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalStaticField") : #t2{core::int};
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField == null)
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
   static get initializedNonFinalStaticField() → core::int
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t5{core::int};
-  static set initializedNonFinalStaticField(core::int #t6) → void
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3 == null ?{core::int} self::Class::_#initializedNonFinalStaticField = 0 : #t3{core::int};
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   static get initializedFinalStaticField() → core::int
-    return let final core::int? #t7 = self::Class::_#initializedFinalStaticField in #t7 == null ?{core::int} let final core::int #t8 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t8 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t7{core::int};
+    return let final core::int? #t4 = self::Class::_#initializedFinalStaticField in #t4 == null ?{core::int} let final core::int #t5 = 0 in self::Class::_#initializedFinalStaticField == null ?{core::int} self::Class::_#initializedFinalStaticField = #t5 : throw new _in::LateError::fieldADI("initializedFinalStaticField") : #t4{core::int};
   get uninitializedFinalInstanceField() → core::int
-    return let final core::int? #t9 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t9 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t9{core::int};
-  set uninitializedFinalInstanceField(core::int #t10) → void
+    return let final core::int? #t6 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalInstanceField") : #t6{core::int};
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} == null)
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t10;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     else
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
   get initializedNonFinalInstanceField() → core::int
-    return let final core::int? #t11 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t11 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t11{core::int};
-  set initializedNonFinalInstanceField(core::int #t12) → void
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t12;
+    return let final core::int? #t7 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t7 == null ?{core::int} this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0 : #t7{core::int};
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   get initializedFinalInstanceField() → core::int
-    return let final core::int? #t13 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t13 == null ?{core::int} let final core::int #t14 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t14 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t13{core::int};
+    return let final core::int? #t8 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t8 == null ?{core::int} let final core::int #t9 = 0 in this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} == null ?{core::int} this.{self::Class::_#Class#initializedFinalInstanceField} = #t9 : throw new _in::LateError::fieldADI("initializedFinalInstanceField") : #t8{core::int};
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
 static field core::int? _#uninitializedFinalTopLevelField = null;
@@ -56,32 +56,32 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t15) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t15;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t16 = #nonNullableUninitializedNonFinalLocal in #t16 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t16{core::int};
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t17) → dynamic
-    return #nonNullableUninitializedNonFinalLocal = #t17;
+    return let final core::int? #t10 = #nonNullableUninitializedNonFinalLocal in #t10 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal") : #t10{core::int};
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t18) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t18;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   function #nonNullableUninitializedFinalLocal#get() → core::int
-    return let final core::int? #t19 = #nonNullableUninitializedFinalLocal in #t19 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t19{core::int};
-  function #nonNullableUninitializedFinalLocal#set(core::int #t20) → dynamic
+    return let final core::int? #t11 = #nonNullableUninitializedFinalLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal") : #t11{core::int};
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal == null)
-      return #nonNullableUninitializedFinalLocal = #t20;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
   lowered core::int? #nullableInitializedNonFinalLocal;
@@ -93,48 +93,48 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t21) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t21;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   function #nonNullableInitializedNonFinalLocal#get() → core::int
-    return let final core::int? #t22 = #nonNullableInitializedNonFinalLocal in #t22 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t22{core::int};
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t23) → dynamic
-    return #nonNullableInitializedNonFinalLocal = #t23;
+    return let final core::int? #t12 = #nonNullableInitializedNonFinalLocal in #t12 == null ?{core::int} #nonNullableInitializedNonFinalLocal = 0 : #t12{core::int};
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t24 = 0;
+      final core::int? #t13 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t24;
+      #nullableInitializedFinalLocal = #t13;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
   }
   lowered final core::int? #nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t25 = #nonNullableInitializedFinalLocal in #t25 == null ?{core::int} let final core::int #t26 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t26 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t25{core::int};
+    return let final core::int? #t14 = #nonNullableInitializedFinalLocal in #t14 == null ?{core::int} let final core::int #t15 = 0 in #nonNullableInitializedFinalLocal == null ?{core::int} #nonNullableInitializedFinalLocal = #t15 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t14{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t28) → void
-  self::_#uninitializedNonFinalTopLevelField = #t28;
+  return let final core::int? #t16 = self::_#uninitializedNonFinalTopLevelField in #t16 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t16{core::int};
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
-static set uninitializedFinalTopLevelField(core::int #t30) → void
+  return let final core::int? #t17 = self::_#uninitializedFinalTopLevelField in #t17 == null ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t17{core::int};
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField == null)
-    self::_#uninitializedFinalTopLevelField = #t30;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
-static set initializedNonFinalTopLevelField(core::int #t32) → void
-  self::_#initializedNonFinalTopLevelField = #t32;
+  return let final core::int? #t18 = self::_#initializedNonFinalTopLevelField in #t18 == null ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t18{core::int};
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33 == null ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
+  return let final core::int? #t19 = self::_#initializedFinalTopLevelField in #t19 == null ?{core::int} let final core::int #t20 = 0 in self::_#initializedFinalTopLevelField == null ?{core::int} self::_#initializedFinalTopLevelField = #t20 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t19{core::int};
 
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
index bfdde61..35fcde8 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
@@ -24,69 +24,69 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t10) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t10;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t11{core::int};
+    return let final core::int? #t7 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t7{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t12) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t12;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t13;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t8;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t14 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t14{core::int};
+    return let final core::int? #t9 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t9{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -103,39 +103,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t15) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t15;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t16) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t16;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t17) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t17;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t18) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t18;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -146,9 +146,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t19) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t19;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -159,18 +159,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t20) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t20;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t21 = 0;
+      final core::int? #t10 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t21;
+      #nullableInitializedFinalLocal = #t10;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -179,48 +179,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t22 = 0;
+      final core::int #t11 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t22;
+      #nonNullableInitializedFinalLocal = #t11;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t12 = self::_#uninitializedNonFinalTopLevelField in #t12{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t24;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t26) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t26;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
+  return let final core::int? #t14 = self::_#initializedNonFinalTopLevelField in #t14{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t28) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t28;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t29 = 0;
+    final core::int #t15 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t29;
+    self::_#initializedFinalTopLevelField = #t15;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
+  return let final core::int? #t16 = self::_#initializedFinalTopLevelField in #t16{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.modular.expect
index bfdde61..35fcde8 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.modular.expect
@@ -24,69 +24,69 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t10) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t10;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t11{core::int};
+    return let final core::int? #t7 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t7{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t12) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t12;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t13;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t8;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t14 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t14{core::int};
+    return let final core::int? #t9 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t9{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -103,39 +103,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t15) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t15;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t16) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t16;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t17) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t17;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t18) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t18;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -146,9 +146,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t19) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t19;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -159,18 +159,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t20) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t20;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t21 = 0;
+      final core::int? #t10 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t21;
+      #nullableInitializedFinalLocal = #t10;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -179,48 +179,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t22 = 0;
+      final core::int #t11 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t22;
+      #nonNullableInitializedFinalLocal = #t11;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t12 = self::_#uninitializedNonFinalTopLevelField in #t12{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t24;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t26) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t26;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
+  return let final core::int? #t14 = self::_#initializedNonFinalTopLevelField in #t14{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t28) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t28;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t29 = 0;
+    final core::int #t15 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t29;
+    self::_#initializedFinalTopLevelField = #t15;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
+  return let final core::int? #t16 = self::_#initializedFinalTopLevelField in #t16{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.outline.expect
index 99d4dee..61b98c7 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.outline.expect
@@ -21,16 +21,16 @@
   synthetic constructor •() → self::Class
     ;
   static get uninitializedNonFinalStaticField() → core::int;
-  static set uninitializedNonFinalStaticField(core::int #t1) → void;
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void;
   static get uninitializedFinalStaticField() → core::int;
-  static set uninitializedFinalStaticField(core::int #t2) → void;
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void;
   static get initializedNonFinalStaticField() → core::int;
-  static set initializedNonFinalStaticField(core::int #t3) → void;
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void;
   static get initializedFinalStaticField() → core::int;
   get uninitializedFinalInstanceField() → core::int;
-  set uninitializedFinalInstanceField(core::int #t4) → void;
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void;
   get initializedNonFinalInstanceField() → core::int;
-  set initializedNonFinalInstanceField(core::int #t5) → void;
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void;
   get initializedFinalInstanceField() → core::int;
 }
 static field core::int? _#uninitializedNonFinalTopLevelField;
@@ -46,9 +46,9 @@
 static method method() → dynamic
   ;
 static get uninitializedNonFinalTopLevelField() → core::int;
-static set uninitializedNonFinalTopLevelField(core::int #t6) → void;
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void;
 static get uninitializedFinalTopLevelField() → core::int;
-static set uninitializedFinalTopLevelField(core::int #t7) → void;
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void;
 static get initializedNonFinalTopLevelField() → core::int;
-static set initializedNonFinalTopLevelField(core::int #t8) → void;
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void;
 static get initializedFinalTopLevelField() → core::int;
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
index bfdde61..35fcde8 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
@@ -24,69 +24,69 @@
     ;
   static get uninitializedNonFinalStaticField() → core::int
     return self::Class::_#uninitializedNonFinalStaticField#isSet ?{core::int} let final core::int? #t1 = self::Class::_#uninitializedNonFinalStaticField in #t1{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalStaticField");
-  static set uninitializedNonFinalStaticField(core::int #t2) → void {
+  static set uninitializedNonFinalStaticField(core::int uninitializedNonFinalStaticField#param) → void {
     self::Class::_#uninitializedNonFinalStaticField#isSet = true;
-    self::Class::_#uninitializedNonFinalStaticField = #t2;
+    self::Class::_#uninitializedNonFinalStaticField = uninitializedNonFinalStaticField#param;
   }
   static get uninitializedFinalStaticField() → core::int
-    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t3 = self::Class::_#uninitializedFinalStaticField in #t3{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
-  static set uninitializedFinalStaticField(core::int #t4) → void
+    return self::Class::_#uninitializedFinalStaticField#isSet ?{core::int} let final core::int? #t2 = self::Class::_#uninitializedFinalStaticField in #t2{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalStaticField");
+  static set uninitializedFinalStaticField(core::int uninitializedFinalStaticField#param) → void
     if(self::Class::_#uninitializedFinalStaticField#isSet)
       throw new _in::LateError::fieldAI("uninitializedFinalStaticField");
     else {
       self::Class::_#uninitializedFinalStaticField#isSet = true;
-      self::Class::_#uninitializedFinalStaticField = #t4;
+      self::Class::_#uninitializedFinalStaticField = uninitializedFinalStaticField#param;
     }
   static get initializedNonFinalStaticField() → core::int {
     if(!self::Class::_#initializedNonFinalStaticField#isSet) {
       self::Class::_#initializedNonFinalStaticField = 0;
       self::Class::_#initializedNonFinalStaticField#isSet = true;
     }
-    return let final core::int? #t5 = self::Class::_#initializedNonFinalStaticField in #t5{core::int};
+    return let final core::int? #t3 = self::Class::_#initializedNonFinalStaticField in #t3{core::int};
   }
-  static set initializedNonFinalStaticField(core::int #t6) → void {
+  static set initializedNonFinalStaticField(core::int initializedNonFinalStaticField#param) → void {
     self::Class::_#initializedNonFinalStaticField#isSet = true;
-    self::Class::_#initializedNonFinalStaticField = #t6;
+    self::Class::_#initializedNonFinalStaticField = initializedNonFinalStaticField#param;
   }
   static get initializedFinalStaticField() → core::int {
     if(!self::Class::_#initializedFinalStaticField#isSet) {
-      final core::int #t7 = 0;
+      final core::int #t4 = 0;
       if(self::Class::_#initializedFinalStaticField#isSet)
         throw new _in::LateError::fieldADI("initializedFinalStaticField");
-      self::Class::_#initializedFinalStaticField = #t7;
+      self::Class::_#initializedFinalStaticField = #t4;
       self::Class::_#initializedFinalStaticField#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#initializedFinalStaticField in #t8{core::int};
+    return let final core::int? #t5 = self::Class::_#initializedFinalStaticField in #t5{core::int};
   }
   get uninitializedFinalInstanceField() → core::int
-    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t9 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t9{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
-  set uninitializedFinalInstanceField(core::int #t10) → void
+    return this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool} ?{core::int} let final core::int? #t6 = this.{self::Class::_#Class#uninitializedFinalInstanceField}{core::int?} in #t6{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalInstanceField");
+  set uninitializedFinalInstanceField(core::int uninitializedFinalInstanceField#param) → void
     if(this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet}{core::bool})
       throw new _in::LateError::fieldAI("uninitializedFinalInstanceField");
     else {
       this.{self::Class::_#Class#uninitializedFinalInstanceField#isSet} = true;
-      this.{self::Class::_#Class#uninitializedFinalInstanceField} = #t10;
+      this.{self::Class::_#Class#uninitializedFinalInstanceField} = uninitializedFinalInstanceField#param;
     }
   get initializedNonFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet}{core::bool}) {
       this.{self::Class::_#Class#initializedNonFinalInstanceField} = 0;
       this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t11 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t11{core::int};
+    return let final core::int? #t7 = this.{self::Class::_#Class#initializedNonFinalInstanceField}{core::int?} in #t7{core::int};
   }
-  set initializedNonFinalInstanceField(core::int #t12) → void {
+  set initializedNonFinalInstanceField(core::int initializedNonFinalInstanceField#param) → void {
     this.{self::Class::_#Class#initializedNonFinalInstanceField#isSet} = true;
-    this.{self::Class::_#Class#initializedNonFinalInstanceField} = #t12;
+    this.{self::Class::_#Class#initializedNonFinalInstanceField} = initializedNonFinalInstanceField#param;
   }
   get initializedFinalInstanceField() → core::int {
     if(!this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool}) {
-      final core::int #t13 = 0;
+      final core::int #t8 = 0;
       if(this.{self::Class::_#Class#initializedFinalInstanceField#isSet}{core::bool})
         throw new _in::LateError::fieldADI("initializedFinalInstanceField");
-      this.{self::Class::_#Class#initializedFinalInstanceField} = #t13;
+      this.{self::Class::_#Class#initializedFinalInstanceField} = #t8;
       this.{self::Class::_#Class#initializedFinalInstanceField#isSet} = true;
     }
-    return let final core::int? #t14 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t14{core::int};
+    return let final core::int? #t9 = this.{self::Class::_#Class#initializedFinalInstanceField}{core::int?} in #t9{core::int};
   }
 }
 static field core::int? _#uninitializedNonFinalTopLevelField = null;
@@ -103,39 +103,39 @@
   lowered core::bool #nullableUninitializedNonFinalLocal#isSet = false;
   function #nullableUninitializedNonFinalLocal#get() → core::int?
     return #nullableUninitializedNonFinalLocal#isSet ?{core::int?} #nullableUninitializedNonFinalLocal : throw new _in::LateError::localNI("nullableUninitializedNonFinalLocal");
-  function #nullableUninitializedNonFinalLocal#set(core::int? #t15) → dynamic {
+  function #nullableUninitializedNonFinalLocal#set(core::int? nullableUninitializedNonFinalLocal#param) → dynamic {
     #nullableUninitializedNonFinalLocal#isSet = true;
-    return #nullableUninitializedNonFinalLocal = #t15;
+    return #nullableUninitializedNonFinalLocal = nullableUninitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableUninitializedNonFinalLocal;
   lowered core::bool #nonNullableUninitializedNonFinalLocal#isSet = false;
   function #nonNullableUninitializedNonFinalLocal#get() → core::int
     return #nonNullableUninitializedNonFinalLocal#isSet ?{core::int} #nonNullableUninitializedNonFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedNonFinalLocal");
-  function #nonNullableUninitializedNonFinalLocal#set(core::int #t16) → dynamic {
+  function #nonNullableUninitializedNonFinalLocal#set(core::int nonNullableUninitializedNonFinalLocal#param) → dynamic {
     #nonNullableUninitializedNonFinalLocal#isSet = true;
-    return #nonNullableUninitializedNonFinalLocal = #t16;
+    return #nonNullableUninitializedNonFinalLocal = nonNullableUninitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableUninitializedFinalLocal;
   lowered core::bool #nullableUninitializedFinalLocal#isSet = false;
   function #nullableUninitializedFinalLocal#get() → core::int?
     return #nullableUninitializedFinalLocal#isSet ?{core::int?} #nullableUninitializedFinalLocal : throw new _in::LateError::localNI("nullableUninitializedFinalLocal");
-  function #nullableUninitializedFinalLocal#set(core::int? #t17) → dynamic
+  function #nullableUninitializedFinalLocal#set(core::int? nullableUninitializedFinalLocal#param) → dynamic
     if(#nullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nullableUninitializedFinalLocal");
     else {
       #nullableUninitializedFinalLocal#isSet = true;
-      return #nullableUninitializedFinalLocal = #t17;
+      return #nullableUninitializedFinalLocal = nullableUninitializedFinalLocal#param;
     }
   lowered final core::int? #nonNullableUninitializedFinalLocal;
   lowered core::bool #nonNullableUninitializedFinalLocal#isSet = false;
   function #nonNullableUninitializedFinalLocal#get() → core::int
     return #nonNullableUninitializedFinalLocal#isSet ?{core::int} #nonNullableUninitializedFinalLocal{core::int} : throw new _in::LateError::localNI("nonNullableUninitializedFinalLocal");
-  function #nonNullableUninitializedFinalLocal#set(core::int #t18) → dynamic
+  function #nonNullableUninitializedFinalLocal#set(core::int nonNullableUninitializedFinalLocal#param) → dynamic
     if(#nonNullableUninitializedFinalLocal#isSet)
       throw new _in::LateError::localAI("nonNullableUninitializedFinalLocal");
     else {
       #nonNullableUninitializedFinalLocal#isSet = true;
-      return #nonNullableUninitializedFinalLocal = #t18;
+      return #nonNullableUninitializedFinalLocal = nonNullableUninitializedFinalLocal#param;
     }
   lowered core::int? #nullableInitializedNonFinalLocal;
   lowered core::bool #nullableInitializedNonFinalLocal#isSet = false;
@@ -146,9 +146,9 @@
     }
     return #nullableInitializedNonFinalLocal;
   }
-  function #nullableInitializedNonFinalLocal#set(core::int? #t19) → dynamic {
+  function #nullableInitializedNonFinalLocal#set(core::int? nullableInitializedNonFinalLocal#param) → dynamic {
     #nullableInitializedNonFinalLocal#isSet = true;
-    return #nullableInitializedNonFinalLocal = #t19;
+    return #nullableInitializedNonFinalLocal = nullableInitializedNonFinalLocal#param;
   }
   lowered core::int? #nonNullableInitializedNonFinalLocal;
   lowered core::bool #nonNullableInitializedNonFinalLocal#isSet = false;
@@ -159,18 +159,18 @@
     }
     return #nonNullableInitializedNonFinalLocal{core::int};
   }
-  function #nonNullableInitializedNonFinalLocal#set(core::int #t20) → dynamic {
+  function #nonNullableInitializedNonFinalLocal#set(core::int nonNullableInitializedNonFinalLocal#param) → dynamic {
     #nonNullableInitializedNonFinalLocal#isSet = true;
-    return #nonNullableInitializedNonFinalLocal = #t20;
+    return #nonNullableInitializedNonFinalLocal = nonNullableInitializedNonFinalLocal#param;
   }
   lowered final core::int? #nullableInitializedFinalLocal;
   lowered core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      final core::int? #t21 = 0;
+      final core::int? #t10 = 0;
       if(#nullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nullableInitializedFinalLocal");
-      #nullableInitializedFinalLocal = #t21;
+      #nullableInitializedFinalLocal = #t10;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return #nullableInitializedFinalLocal;
@@ -179,48 +179,48 @@
   lowered core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      final core::int #t22 = 0;
+      final core::int #t11 = 0;
       if(#nonNullableInitializedFinalLocal#isSet)
         throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
-      #nonNullableInitializedFinalLocal = #t22;
+      #nonNullableInitializedFinalLocal = #t11;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return #nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t12 = self::_#uninitializedNonFinalTopLevelField in #t12{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int uninitializedNonFinalTopLevelField#param) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t24;
+  self::_#uninitializedNonFinalTopLevelField = uninitializedNonFinalTopLevelField#param;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t26) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t13 = self::_#uninitializedFinalTopLevelField in #t13{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int uninitializedFinalTopLevelField#param) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t26;
+    self::_#uninitializedFinalTopLevelField = uninitializedFinalTopLevelField#param;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
+  return let final core::int? #t14 = self::_#initializedNonFinalTopLevelField in #t14{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t28) → void {
+static set initializedNonFinalTopLevelField(core::int initializedNonFinalTopLevelField#param) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t28;
+  self::_#initializedNonFinalTopLevelField = initializedNonFinalTopLevelField#param;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t29 = 0;
+    final core::int #t15 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t29;
+    self::_#initializedFinalTopLevelField = #t15;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
+  return let final core::int? #t16 = self::_#initializedFinalTopLevelField in #t16{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.expect
index aaa46cf..c42c449 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.expect
@@ -13,7 +13,7 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{self::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{self::A::_#A#x} = x#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.transformed.expect
index aaa46cf..c42c449 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
     ;
   get x() → core::int
     return let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("x") : #t1{core::int};
-  set x(core::int #t2) → void
-    this.{self::A::_#A#x} = #t2;
+  set x(core::int x#param) → void
+    this.{self::A::_#A#x} = x#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
index 13fee7d..5a51a9a 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
@@ -14,9 +14,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.modular.expect
index 13fee7d..5a51a9a 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.modular.expect
@@ -14,9 +14,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.outline.expect
index 347f1cf..bd0156b 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.outline.expect
@@ -10,7 +10,7 @@
   constructor bar() → self::A
     ;
   get x() → core::int;
-  set x(core::int #t1) → void;
+  set x(core::int x#param) → void;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
index 13fee7d..5a51a9a 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
@@ -14,9 +14,9 @@
     ;
   get x() → core::int
     return this.{self::A::_#A#x#isSet}{core::bool} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x}{core::int?} in #t1{core::int} : throw new _in::LateError::fieldNI("x");
-  set x(core::int #t2) → void {
+  set x(core::int x#param) → void {
     this.{self::A::_#A#x#isSet} = true;
-    this.{self::A::_#A#x} = #t2;
+    this.{self::A::_#A#x} = x#param;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect
index 1d4a7c3..894932f 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect
@@ -14,40 +14,40 @@
 static field Never? _#neverTopLevelField = null;
 static get nullableTopLevelField() → core::int?
   return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::fieldNI("nullableTopLevelField") : #t1{core::int?};
-static set nullableTopLevelField(core::int? #t2) → void
-  self::_#nullableTopLevelField = #t2;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t3{core::int};
-static set nonNullableTopLevelField(core::int #t4) → void
-  self::_#nonNullableTopLevelField = #t4;
+  return let final core::int? #t2 = self::_#nonNullableTopLevelField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t2{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
-static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
-  self::_#nullableTopLevelFieldWithInitializer = #t6;
+  return let final core::int? #t3 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t3) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t3{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 static get nonNullableTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
-static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
-  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+  return let final core::int? #t4 = self::_#nonNullableTopLevelFieldWithInitializer in #t4 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t4{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = nonNullableTopLevelFieldWithInitializer#param;
 static get nullableFinalTopLevelField() → core::int?
-  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t9{core::int?};
-static set nullableFinalTopLevelField(core::int? #t10) → void
+  return let final core::int? #t5 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t5{core::int?};
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nullableFinalTopLevelField))
-    self::_#nullableFinalTopLevelField = #t10;
+    self::_#nullableFinalTopLevelField = nullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nullableFinalTopLevelField");
 static get nonNullableFinalTopLevelField() → core::int
-  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t11{core::int};
-static set nonNullableFinalTopLevelField(core::int #t12) → void
+  return let final core::int? #t6 = self::_#nonNullableFinalTopLevelField in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t6{core::int};
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void
   if(self::_#nonNullableFinalTopLevelField == null)
-    self::_#nonNullableFinalTopLevelField = #t12;
+    self::_#nonNullableFinalTopLevelField = nonNullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nonNullableFinalTopLevelField");
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t13;
+  return let final core::int? #t7 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t8 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t7;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15 == null ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t15{core::int};
+  return let final core::int? #t9 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t9 == null ?{core::int} let final core::int #t10 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t10 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t9{core::int};
 static get neverTopLevelField() → Never
-  return let final Never? #t17 = self::_#neverTopLevelField in #t17 == null ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t17{Never};
-static set neverTopLevelField(Never #t18) → void
-  self::_#neverTopLevelField = #t18;
+  return let final Never? #t11 = self::_#neverTopLevelField in #t11 == null ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t11{Never};
+static set neverTopLevelField(Never neverTopLevelField#param) → void
+  self::_#neverTopLevelField = neverTopLevelField#param;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect
index 2f61bd0..8450f92 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect
@@ -14,42 +14,42 @@
 static field Never? _#neverTopLevelField = null;
 static get nullableTopLevelField() → core::int?
   return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::fieldNI("nullableTopLevelField") : #t1{core::int?};
-static set nullableTopLevelField(core::int? #t2) → void
-  self::_#nullableTopLevelField = #t2;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t3{core::int};
-static set nonNullableTopLevelField(core::int #t4) → void
-  self::_#nonNullableTopLevelField = #t4;
+  return let final core::int? #t2 = self::_#nonNullableTopLevelField in #t2 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t2{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
-static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
-  self::_#nullableTopLevelFieldWithInitializer = #t6;
+  return let final core::int? #t3 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t3) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t3{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 static get nonNullableTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
-static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
-  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+  return let final core::int? #t4 = self::_#nonNullableTopLevelFieldWithInitializer in #t4 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t4{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = nonNullableTopLevelFieldWithInitializer#param;
 static get nullableFinalTopLevelField() → core::int?
-  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t9{core::int?};
-static set nullableFinalTopLevelField(core::int? #t10) → void
+  return let final core::int? #t5 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t5{core::int?};
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nullableFinalTopLevelField))
-    self::_#nullableFinalTopLevelField = #t10;
+    self::_#nullableFinalTopLevelField = nullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nullableFinalTopLevelField");
 static get nonNullableFinalTopLevelField() → core::int
-  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t11{core::int};
-static set nonNullableFinalTopLevelField(core::int #t12) → void
+  return let final core::int? #t6 = self::_#nonNullableFinalTopLevelField in #t6 == null ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t6{core::int};
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void
   if(self::_#nonNullableFinalTopLevelField == null)
-    self::_#nonNullableFinalTopLevelField = #t12;
+    self::_#nonNullableFinalTopLevelField = nonNullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nonNullableFinalTopLevelField");
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t13;
+  return let final core::int? #t7 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t8 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t7;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15 == null ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t15{core::int};
+  return let final core::int? #t9 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t9 == null ?{core::int} let final core::int #t10 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t10 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t9{core::int};
 static get neverTopLevelField() → Never
-  return let final Never? #t17 = self::_#neverTopLevelField in #t17 == null ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t17{Never};
-static set neverTopLevelField(Never #t18) → void
-  self::_#neverTopLevelField = #t18;
+  return let final Never? #t11 = self::_#neverTopLevelField in #t11 == null ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t11{Never};
+static set neverTopLevelField(Never neverTopLevelField#param) → void
+  self::_#neverTopLevelField = neverTopLevelField#param;
 static method main() → dynamic {}
 
 
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect
index c037d72..7386247 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect
@@ -14,40 +14,40 @@
 static field Never? _#neverTopLevelField = _in::createSentinel<Never>();
 static get nullableTopLevelField() → core::int?
   return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::fieldNI("nullableTopLevelField") : #t1{core::int?};
-static set nullableTopLevelField(core::int? #t2) → void
-  self::_#nullableTopLevelField = #t2;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t3 = self::_#nonNullableTopLevelField in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t3{core::int};
-static set nonNullableTopLevelField(core::int #t4) → void
-  self::_#nonNullableTopLevelField = #t4;
+  return let final core::int? #t2 = self::_#nonNullableTopLevelField in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t2{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
-static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
-  self::_#nullableTopLevelFieldWithInitializer = #t6;
+  return let final core::int? #t3 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t3) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t3{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 static get nonNullableTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
-static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
-  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+  return let final core::int? #t4 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t4) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t4{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = nonNullableTopLevelFieldWithInitializer#param;
 static get nullableFinalTopLevelField() → core::int?
-  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t9{core::int?};
-static set nullableFinalTopLevelField(core::int? #t10) → void
+  return let final core::int? #t5 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t5{core::int?};
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nullableFinalTopLevelField))
-    self::_#nullableFinalTopLevelField = #t10;
+    self::_#nullableFinalTopLevelField = nullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nullableFinalTopLevelField");
 static get nonNullableFinalTopLevelField() → core::int
-  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t11{core::int};
-static set nonNullableFinalTopLevelField(core::int #t12) → void
+  return let final core::int? #t6 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t6{core::int};
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nonNullableFinalTopLevelField))
-    self::_#nonNullableFinalTopLevelField = #t12;
+    self::_#nonNullableFinalTopLevelField = nonNullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nonNullableFinalTopLevelField");
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t13;
+  return let final core::int? #t7 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t8 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t7;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
-  return let final core::int #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t15;
+  return let final core::int #t9 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t10 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t9;
 static get neverTopLevelField() → Never
-  return let final Never? #t17 = self::_#neverTopLevelField in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t17{Never};
-static set neverTopLevelField(Never #t18) → void
-  self::_#neverTopLevelField = #t18;
+  return let final Never? #t11 = self::_#neverTopLevelField in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t11{Never};
+static set neverTopLevelField(Never neverTopLevelField#param) → void
+  self::_#neverTopLevelField = neverTopLevelField#param;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.modular.expect
index c037d72..7386247 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.modular.expect
@@ -14,40 +14,40 @@
 static field Never? _#neverTopLevelField = _in::createSentinel<Never>();
 static get nullableTopLevelField() → core::int?
   return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::fieldNI("nullableTopLevelField") : #t1{core::int?};
-static set nullableTopLevelField(core::int? #t2) → void
-  self::_#nullableTopLevelField = #t2;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t3 = self::_#nonNullableTopLevelField in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t3{core::int};
-static set nonNullableTopLevelField(core::int #t4) → void
-  self::_#nonNullableTopLevelField = #t4;
+  return let final core::int? #t2 = self::_#nonNullableTopLevelField in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t2{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
-static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
-  self::_#nullableTopLevelFieldWithInitializer = #t6;
+  return let final core::int? #t3 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t3) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t3{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 static get nonNullableTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
-static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
-  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+  return let final core::int? #t4 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t4) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t4{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = nonNullableTopLevelFieldWithInitializer#param;
 static get nullableFinalTopLevelField() → core::int?
-  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t9{core::int?};
-static set nullableFinalTopLevelField(core::int? #t10) → void
+  return let final core::int? #t5 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t5{core::int?};
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nullableFinalTopLevelField))
-    self::_#nullableFinalTopLevelField = #t10;
+    self::_#nullableFinalTopLevelField = nullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nullableFinalTopLevelField");
 static get nonNullableFinalTopLevelField() → core::int
-  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t11{core::int};
-static set nonNullableFinalTopLevelField(core::int #t12) → void
+  return let final core::int? #t6 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t6{core::int};
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nonNullableFinalTopLevelField))
-    self::_#nonNullableFinalTopLevelField = #t12;
+    self::_#nonNullableFinalTopLevelField = nonNullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nonNullableFinalTopLevelField");
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t13;
+  return let final core::int? #t7 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t8 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t7;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
-  return let final core::int #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t15;
+  return let final core::int #t9 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t10 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t9;
 static get neverTopLevelField() → Never
-  return let final Never? #t17 = self::_#neverTopLevelField in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t17{Never};
-static set neverTopLevelField(Never #t18) → void
-  self::_#neverTopLevelField = #t18;
+  return let final Never? #t11 = self::_#neverTopLevelField in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t11{Never};
+static set neverTopLevelField(Never neverTopLevelField#param) → void
+  self::_#neverTopLevelField = neverTopLevelField#param;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.outline.expect
index f88db33..5362416 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.outline.expect
@@ -12,20 +12,20 @@
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer;
 static field Never? _#neverTopLevelField;
 static get nullableTopLevelField() → core::int?;
-static set nullableTopLevelField(core::int? #t1) → void;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void;
 static get nonNullableTopLevelField() → core::int;
-static set nonNullableTopLevelField(core::int #t2) → void;
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void;
 static get nullableTopLevelFieldWithInitializer() → core::int?;
-static set nullableTopLevelFieldWithInitializer(core::int? #t3) → void;
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void;
 static get nonNullableTopLevelFieldWithInitializer() → core::int;
-static set nonNullableTopLevelFieldWithInitializer(core::int #t4) → void;
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void;
 static get nullableFinalTopLevelField() → core::int?;
-static set nullableFinalTopLevelField(core::int? #t5) → void;
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void;
 static get nonNullableFinalTopLevelField() → core::int;
-static set nonNullableFinalTopLevelField(core::int #t6) → void;
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void;
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int;
 static get neverTopLevelField() → Never;
-static set neverTopLevelField(Never #t7) → void;
+static set neverTopLevelField(Never neverTopLevelField#param) → void;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect
index 24976f8..e689c28 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect
@@ -14,42 +14,42 @@
 static field Never? _#neverTopLevelField = _in::createSentinel<Never>();
 static get nullableTopLevelField() → core::int?
   return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::fieldNI("nullableTopLevelField") : #t1{core::int?};
-static set nullableTopLevelField(core::int? #t2) → void
-  self::_#nullableTopLevelField = #t2;
+static set nullableTopLevelField(core::int? nullableTopLevelField#param) → void
+  self::_#nullableTopLevelField = nullableTopLevelField#param;
 static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t3 = self::_#nonNullableTopLevelField in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t3{core::int};
-static set nonNullableTopLevelField(core::int #t4) → void
-  self::_#nonNullableTopLevelField = #t4;
+  return let final core::int? #t2 = self::_#nonNullableTopLevelField in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::fieldNI("nonNullableTopLevelField") : #t2{core::int};
+static set nonNullableTopLevelField(core::int nonNullableTopLevelField#param) → void
+  self::_#nonNullableTopLevelField = nonNullableTopLevelField#param;
 static get nullableTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
-static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
-  self::_#nullableTopLevelFieldWithInitializer = #t6;
+  return let final core::int? #t3 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t3) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t3{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 static get nonNullableTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
-static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
-  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+  return let final core::int? #t4 = self::_#nonNullableTopLevelFieldWithInitializer in _in::isSentinel(#t4) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t4{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int nonNullableTopLevelFieldWithInitializer#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = nonNullableTopLevelFieldWithInitializer#param;
 static get nullableFinalTopLevelField() → core::int?
-  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t9{core::int?};
-static set nullableFinalTopLevelField(core::int? #t10) → void
+  return let final core::int? #t5 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::fieldNI("nullableFinalTopLevelField") : #t5{core::int?};
+static set nullableFinalTopLevelField(core::int? nullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nullableFinalTopLevelField))
-    self::_#nullableFinalTopLevelField = #t10;
+    self::_#nullableFinalTopLevelField = nullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nullableFinalTopLevelField");
 static get nonNullableFinalTopLevelField() → core::int
-  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t11{core::int};
-static set nonNullableFinalTopLevelField(core::int #t12) → void
+  return let final core::int? #t6 = self::_#nonNullableFinalTopLevelField in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::fieldNI("nonNullableFinalTopLevelField") : #t6{core::int};
+static set nonNullableFinalTopLevelField(core::int nonNullableFinalTopLevelField#param) → void
   if(_in::isSentinel(self::_#nonNullableFinalTopLevelField))
-    self::_#nonNullableFinalTopLevelField = #t12;
+    self::_#nonNullableFinalTopLevelField = nonNullableFinalTopLevelField#param;
   else
     throw new _in::LateError::fieldAI("nonNullableFinalTopLevelField");
 static get nullableFinalTopLevelFieldWithInitializer() → core::int?
-  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t13;
+  return let final core::int? #t7 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t8 : throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer") : #t7;
 static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
-  return let final core::int #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t15;
+  return let final core::int #t9 = self::_#nonNullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(self::_#nonNullableFinalTopLevelFieldWithInitializer) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t10 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer") : #t9;
 static get neverTopLevelField() → Never
-  return let final Never? #t17 = self::_#neverTopLevelField in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t17{Never};
-static set neverTopLevelField(Never #t18) → void
-  self::_#neverTopLevelField = #t18;
+  return let final Never? #t11 = self::_#neverTopLevelField in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::fieldNI("neverTopLevelField") : #t11{Never};
+static set neverTopLevelField(Never neverTopLevelField#param) → void
+  self::_#neverTopLevelField = neverTopLevelField#param;
 static method main() → dynamic {}
 
 
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
index 7b794cc..7f9c20d 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
@@ -7,49 +7,49 @@
   lowered core::int? #nullableTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocal#get() → core::int?
     return let final core::int? #t1 = #nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("nullableTopLevelLocal") : #t1{core::int?};
-  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
-    return #nullableTopLevelLocal = #t2;
+  function #nullableTopLevelLocal#set(core::int? nullableTopLevelLocal#param) → dynamic
+    return #nullableTopLevelLocal = nullableTopLevelLocal#param;
   lowered core::int? #nonNullableTopLevelLocal;
   function #nonNullableTopLevelLocal#get() → core::int
-    return let final core::int? #t3 = #nonNullableTopLevelLocal in #t3 == null ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t3{core::int};
-  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
-    return #nonNullableTopLevelLocal = #t4;
+    return let final core::int? #t2 = #nonNullableTopLevelLocal in #t2 == null ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t2{core::int};
+  function #nonNullableTopLevelLocal#set(core::int nonNullableTopLevelLocal#param) → dynamic
+    return #nonNullableTopLevelLocal = nonNullableTopLevelLocal#param;
   lowered core::int? #nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t5 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
-  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
-    return #nullableTopLevelLocalWithInitializer = #t6;
+    return let final core::int? #t3 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t3) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t3{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? nullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nullableTopLevelLocalWithInitializer = nullableTopLevelLocalWithInitializer#param;
   lowered core::int? #nonNullableTopLevelLocalWithInitializer;
   function #nonNullableTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t7 = #nonNullableTopLevelLocalWithInitializer in #t7 == null ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
-  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
-    return #nonNullableTopLevelLocalWithInitializer = #t8;
+    return let final core::int? #t4 = #nonNullableTopLevelLocalWithInitializer in #t4 == null ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t4{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int nonNullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nonNullableTopLevelLocalWithInitializer = nonNullableTopLevelLocalWithInitializer#param;
   lowered final core::int? #nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocal#get() → core::int?
-    return let final core::int? #t9 = #nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t9{core::int?};
-  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    return let final core::int? #t5 = #nullableFinalTopLevelLocal in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t5{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? nullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nullableFinalTopLevelLocal))
-      return #nullableFinalTopLevelLocal = #t10;
+      return #nullableFinalTopLevelLocal = nullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nullableFinalTopLevelLocal");
   lowered final core::int? #nonNullableFinalTopLevelLocal;
   function #nonNullableFinalTopLevelLocal#get() → core::int
-    return let final core::int? #t11 = #nonNullableFinalTopLevelLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t11{core::int};
-  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    return let final core::int? #t6 = #nonNullableFinalTopLevelLocal in #t6 == null ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t6{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int nonNullableFinalTopLevelLocal#param) → dynamic
     if(#nonNullableFinalTopLevelLocal == null)
-      return #nonNullableFinalTopLevelLocal = #t12;
+      return #nonNullableFinalTopLevelLocal = nonNullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   lowered final core::int? #nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
+    return let final core::int? #t7 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t8 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t7;
   lowered final core::int? #nonNullableFinalTopLevelLocalWithInitializer;
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t15 = #nonNullableFinalTopLevelLocalWithInitializer in #t15 == null ?{core::int} let final core::int #t16 = 0 in #nonNullableFinalTopLevelLocalWithInitializer == null ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15{core::int};
+    return let final core::int? #t9 = #nonNullableFinalTopLevelLocalWithInitializer in #t9 == null ?{core::int} let final core::int #t10 = 0 in #nonNullableFinalTopLevelLocalWithInitializer == null ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t10 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t9{core::int};
   lowered Null #neverLocal;
   function #neverLocal#get() → Never
-    return let final Never? #t17 = #neverLocal in #t17 == null ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
-  function #neverLocal#set(Never #t18) → dynamic
-    return #neverLocal = #t18;
+    return let final Never? #t11 = #neverLocal in #t11 == null ?{Never} throw new _in::LateError::localNI("neverLocal") : #t11{Never};
+  function #neverLocal#set(Never neverLocal#param) → dynamic
+    return #neverLocal = neverLocal#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
index c00b5b9..79e2a5d 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
@@ -7,50 +7,50 @@
   lowered core::int? #nullableTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocal#get() → core::int?
     return let final core::int? #t1 = #nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("nullableTopLevelLocal") : #t1{core::int?};
-  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
-    return #nullableTopLevelLocal = #t2;
+  function #nullableTopLevelLocal#set(core::int? nullableTopLevelLocal#param) → dynamic
+    return #nullableTopLevelLocal = nullableTopLevelLocal#param;
   lowered core::int? #nonNullableTopLevelLocal;
   function #nonNullableTopLevelLocal#get() → core::int
-    return let final core::int? #t3 = #nonNullableTopLevelLocal in #t3 == null ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t3{core::int};
-  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
-    return #nonNullableTopLevelLocal = #t4;
+    return let final core::int? #t2 = #nonNullableTopLevelLocal in #t2 == null ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t2{core::int};
+  function #nonNullableTopLevelLocal#set(core::int nonNullableTopLevelLocal#param) → dynamic
+    return #nonNullableTopLevelLocal = nonNullableTopLevelLocal#param;
   lowered core::int? #nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t5 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
-  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
-    return #nullableTopLevelLocalWithInitializer = #t6;
+    return let final core::int? #t3 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t3) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t3{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? nullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nullableTopLevelLocalWithInitializer = nullableTopLevelLocalWithInitializer#param;
   lowered core::int? #nonNullableTopLevelLocalWithInitializer;
   function #nonNullableTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t7 = #nonNullableTopLevelLocalWithInitializer in #t7 == null ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
-  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
-    return #nonNullableTopLevelLocalWithInitializer = #t8;
+    return let final core::int? #t4 = #nonNullableTopLevelLocalWithInitializer in #t4 == null ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t4{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int nonNullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nonNullableTopLevelLocalWithInitializer = nonNullableTopLevelLocalWithInitializer#param;
   lowered final core::int? #nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocal#get() → core::int?
-    return let final core::int? #t9 = #nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t9{core::int?};
-  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    return let final core::int? #t5 = #nullableFinalTopLevelLocal in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t5{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? nullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nullableFinalTopLevelLocal))
-      return #nullableFinalTopLevelLocal = #t10;
+      return #nullableFinalTopLevelLocal = nullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nullableFinalTopLevelLocal");
   lowered final core::int? #nonNullableFinalTopLevelLocal;
   function #nonNullableFinalTopLevelLocal#get() → core::int
-    return let final core::int? #t11 = #nonNullableFinalTopLevelLocal in #t11 == null ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t11{core::int};
-  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    return let final core::int? #t6 = #nonNullableFinalTopLevelLocal in #t6 == null ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t6{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int nonNullableFinalTopLevelLocal#param) → dynamic
     if(#nonNullableFinalTopLevelLocal == null)
-      return #nonNullableFinalTopLevelLocal = #t12;
+      return #nonNullableFinalTopLevelLocal = nonNullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   lowered final core::int? #nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
+    return let final core::int? #t7 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t8 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t7;
   lowered final core::int? #nonNullableFinalTopLevelLocalWithInitializer;
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t15 = #nonNullableFinalTopLevelLocalWithInitializer in #t15 == null ?{core::int} let final core::int #t16 = 0 in #nonNullableFinalTopLevelLocalWithInitializer == null ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15{core::int};
+    return let final core::int? #t9 = #nonNullableFinalTopLevelLocalWithInitializer in #t9 == null ?{core::int} let final core::int #t10 = 0 in #nonNullableFinalTopLevelLocalWithInitializer == null ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t10 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t9{core::int};
   lowered Null #neverLocal;
   function #neverLocal#get() → Never
-    return let final Never? #t17 = #neverLocal in #t17 == null ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
-  function #neverLocal#set(Never #t18) → dynamic
-    return #neverLocal = #t18;
+    return let final Never? #t11 = #neverLocal in #t11 == null ?{Never} throw new _in::LateError::localNI("neverLocal") : #t11{Never};
+  function #neverLocal#set(Never neverLocal#param) → dynamic
+    return #neverLocal = neverLocal#param;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
index 98019ae..544622d 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
@@ -7,49 +7,49 @@
   lowered core::int? #nullableTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocal#get() → core::int?
     return let final core::int? #t1 = #nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("nullableTopLevelLocal") : #t1{core::int?};
-  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
-    return #nullableTopLevelLocal = #t2;
+  function #nullableTopLevelLocal#set(core::int? nullableTopLevelLocal#param) → dynamic
+    return #nullableTopLevelLocal = nullableTopLevelLocal#param;
   lowered core::int? #nonNullableTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocal#get() → core::int
-    return let final core::int? #t3 = #nonNullableTopLevelLocal in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t3{core::int};
-  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
-    return #nonNullableTopLevelLocal = #t4;
+    return let final core::int? #t2 = #nonNullableTopLevelLocal in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t2{core::int};
+  function #nonNullableTopLevelLocal#set(core::int nonNullableTopLevelLocal#param) → dynamic
+    return #nonNullableTopLevelLocal = nonNullableTopLevelLocal#param;
   lowered core::int? #nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t5 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
-  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
-    return #nullableTopLevelLocalWithInitializer = #t6;
+    return let final core::int? #t3 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t3) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t3{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? nullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nullableTopLevelLocalWithInitializer = nullableTopLevelLocalWithInitializer#param;
   lowered core::int? #nonNullableTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t7 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
-  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
-    return #nonNullableTopLevelLocalWithInitializer = #t8;
+    return let final core::int? #t4 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t4) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t4{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int nonNullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nonNullableTopLevelLocalWithInitializer = nonNullableTopLevelLocalWithInitializer#param;
   lowered final core::int? #nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocal#get() → core::int?
-    return let final core::int? #t9 = #nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t9{core::int?};
-  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    return let final core::int? #t5 = #nullableFinalTopLevelLocal in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t5{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? nullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nullableFinalTopLevelLocal))
-      return #nullableFinalTopLevelLocal = #t10;
+      return #nullableFinalTopLevelLocal = nullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nullableFinalTopLevelLocal");
   lowered final core::int? #nonNullableFinalTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocal#get() → core::int
-    return let final core::int? #t11 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t11{core::int};
-  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    return let final core::int? #t6 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t6{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int nonNullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nonNullableFinalTopLevelLocal))
-      return #nonNullableFinalTopLevelLocal = #t12;
+      return #nonNullableFinalTopLevelLocal = nonNullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   lowered final core::int? #nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
+    return let final core::int? #t7 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t8 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t7;
   lowered final core::int? #nonNullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int #t15 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15;
+    return let final core::int #t9 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t10 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t9;
   lowered Null #neverLocal = _in::createSentinel<Never>();
   function #neverLocal#get() → Never
-    return let final Never? #t17 = #neverLocal in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
-  function #neverLocal#set(Never #t18) → dynamic
-    return #neverLocal = #t18;
+    return let final Never? #t11 = #neverLocal in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t11{Never};
+  function #neverLocal#set(Never neverLocal#param) → dynamic
+    return #neverLocal = neverLocal#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.modular.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.modular.expect
index 98019ae..544622d 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.modular.expect
@@ -7,49 +7,49 @@
   lowered core::int? #nullableTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocal#get() → core::int?
     return let final core::int? #t1 = #nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("nullableTopLevelLocal") : #t1{core::int?};
-  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
-    return #nullableTopLevelLocal = #t2;
+  function #nullableTopLevelLocal#set(core::int? nullableTopLevelLocal#param) → dynamic
+    return #nullableTopLevelLocal = nullableTopLevelLocal#param;
   lowered core::int? #nonNullableTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocal#get() → core::int
-    return let final core::int? #t3 = #nonNullableTopLevelLocal in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t3{core::int};
-  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
-    return #nonNullableTopLevelLocal = #t4;
+    return let final core::int? #t2 = #nonNullableTopLevelLocal in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t2{core::int};
+  function #nonNullableTopLevelLocal#set(core::int nonNullableTopLevelLocal#param) → dynamic
+    return #nonNullableTopLevelLocal = nonNullableTopLevelLocal#param;
   lowered core::int? #nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t5 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
-  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
-    return #nullableTopLevelLocalWithInitializer = #t6;
+    return let final core::int? #t3 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t3) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t3{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? nullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nullableTopLevelLocalWithInitializer = nullableTopLevelLocalWithInitializer#param;
   lowered core::int? #nonNullableTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t7 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
-  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
-    return #nonNullableTopLevelLocalWithInitializer = #t8;
+    return let final core::int? #t4 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t4) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t4{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int nonNullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nonNullableTopLevelLocalWithInitializer = nonNullableTopLevelLocalWithInitializer#param;
   lowered final core::int? #nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocal#get() → core::int?
-    return let final core::int? #t9 = #nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t9{core::int?};
-  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    return let final core::int? #t5 = #nullableFinalTopLevelLocal in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t5{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? nullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nullableFinalTopLevelLocal))
-      return #nullableFinalTopLevelLocal = #t10;
+      return #nullableFinalTopLevelLocal = nullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nullableFinalTopLevelLocal");
   lowered final core::int? #nonNullableFinalTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocal#get() → core::int
-    return let final core::int? #t11 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t11{core::int};
-  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    return let final core::int? #t6 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t6{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int nonNullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nonNullableFinalTopLevelLocal))
-      return #nonNullableFinalTopLevelLocal = #t12;
+      return #nonNullableFinalTopLevelLocal = nonNullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   lowered final core::int? #nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
+    return let final core::int? #t7 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t8 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t7;
   lowered final core::int? #nonNullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int #t15 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15;
+    return let final core::int #t9 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t10 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t9;
   lowered Null #neverLocal = _in::createSentinel<Never>();
   function #neverLocal#get() → Never
-    return let final Never? #t17 = #neverLocal in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
-  function #neverLocal#set(Never #t18) → dynamic
-    return #neverLocal = #t18;
+    return let final Never? #t11 = #neverLocal in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t11{Never};
+  function #neverLocal#set(Never neverLocal#param) → dynamic
+    return #neverLocal = neverLocal#param;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
index 01ccc85..c3a1322 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
@@ -7,50 +7,50 @@
   lowered core::int? #nullableTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocal#get() → core::int?
     return let final core::int? #t1 = #nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("nullableTopLevelLocal") : #t1{core::int?};
-  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
-    return #nullableTopLevelLocal = #t2;
+  function #nullableTopLevelLocal#set(core::int? nullableTopLevelLocal#param) → dynamic
+    return #nullableTopLevelLocal = nullableTopLevelLocal#param;
   lowered core::int? #nonNullableTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocal#get() → core::int
-    return let final core::int? #t3 = #nonNullableTopLevelLocal in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t3{core::int};
-  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
-    return #nonNullableTopLevelLocal = #t4;
+    return let final core::int? #t2 = #nonNullableTopLevelLocal in _in::isSentinel(#t2) ?{core::int} throw new _in::LateError::localNI("nonNullableTopLevelLocal") : #t2{core::int};
+  function #nonNullableTopLevelLocal#set(core::int nonNullableTopLevelLocal#param) → dynamic
+    return #nonNullableTopLevelLocal = nonNullableTopLevelLocal#param;
   lowered core::int? #nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t5 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
-  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
-    return #nullableTopLevelLocalWithInitializer = #t6;
+    return let final core::int? #t3 = #nullableTopLevelLocalWithInitializer in _in::isSentinel(#t3) ?{core::int?} #nullableTopLevelLocalWithInitializer = null : #t3{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? nullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nullableTopLevelLocalWithInitializer = nullableTopLevelLocalWithInitializer#param;
   lowered core::int? #nonNullableTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t7 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
-  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
-    return #nonNullableTopLevelLocalWithInitializer = #t8;
+    return let final core::int? #t4 = #nonNullableTopLevelLocalWithInitializer in _in::isSentinel(#t4) ?{core::int} #nonNullableTopLevelLocalWithInitializer = 0 : #t4{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int nonNullableTopLevelLocalWithInitializer#param) → dynamic
+    return #nonNullableTopLevelLocalWithInitializer = nonNullableTopLevelLocalWithInitializer#param;
   lowered final core::int? #nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocal#get() → core::int?
-    return let final core::int? #t9 = #nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t9{core::int?};
-  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    return let final core::int? #t5 = #nullableFinalTopLevelLocal in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("nullableFinalTopLevelLocal") : #t5{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? nullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nullableFinalTopLevelLocal))
-      return #nullableFinalTopLevelLocal = #t10;
+      return #nullableFinalTopLevelLocal = nullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nullableFinalTopLevelLocal");
   lowered final core::int? #nonNullableFinalTopLevelLocal = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocal#get() → core::int
-    return let final core::int? #t11 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t11) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t11{core::int};
-  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    return let final core::int? #t6 = #nonNullableFinalTopLevelLocal in _in::isSentinel(#t6) ?{core::int} throw new _in::LateError::localNI("nonNullableFinalTopLevelLocal") : #t6{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int nonNullableFinalTopLevelLocal#param) → dynamic
     if(_in::isSentinel(#nonNullableFinalTopLevelLocal))
-      return #nonNullableFinalTopLevelLocal = #t12;
+      return #nonNullableFinalTopLevelLocal = nonNullableFinalTopLevelLocal#param;
     else
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   lowered final core::int? #nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
+    return let final core::int? #t7 = #nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = null in _in::isSentinel(#nullableFinalTopLevelLocalWithInitializer) ?{core::int?} #nullableFinalTopLevelLocalWithInitializer = #t8 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t7;
   lowered final core::int? #nonNullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int #t15 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15;
+    return let final core::int #t9 = #nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t9) ?{core::int} let final core::int #t10 = 0 in _in::isSentinel(#nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} #nonNullableFinalTopLevelLocalWithInitializer = #t10 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t9;
   lowered Null #neverLocal = _in::createSentinel<Never>();
   function #neverLocal#get() → Never
-    return let final Never? #t17 = #neverLocal in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
-  function #neverLocal#set(Never #t18) → dynamic
-    return #neverLocal = #t18;
+    return let final Never? #t11 = #neverLocal in _in::isSentinel(#t11) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t11{Never};
+  function #neverLocal#set(Never neverLocal#param) → dynamic
+    return #neverLocal = neverLocal#param;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
index 4ca0a85..9f1c16a 100644
--- a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
@@ -3,8 +3,10 @@
   A.foo() : this(42, z: "foo", false);
   factory A.bar(int x, bool y, {required String z}) = A;
 }
+
 class B extends A {
   B() : super(42, z: "foo", false);
 }
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3d107d4
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A {
+  A(int x, bool y, {required String z});
+  A.foo() : this(42, z: "foo", false);
+  factory A.bar(int x, bool y, {required String z}) = A;
+}
+
+class B extends A {
+  B() : super(42, z: "foo", false);
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect
index 8fae114..b190b3a 100644
--- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect
@@ -34,7 +34,7 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect
index 6b19c1d..fccf634 100644
--- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect
@@ -24,9 +24,9 @@
   set y(core::double #externalFieldValue) → void
     return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C12.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
   get next() → ffi::Pointer<self::Coordinate>
-    return ffi::_fromAddress<self::Coordinate>(ffi::_loadIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
+    return ffi::_fromAddress<self::Coordinate>(ffi::_loadAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
   set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void
-    return ffi::_storeIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Pointer::address}{core::int});
+    return ffi::_storeAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Pointer::address}{core::int});
   static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
     return let final self::Coordinate #t1 = new self::Coordinate::#fromTypedDataBase(allocator.{ffi::Allocator::allocate}<self::Coordinate>(self::Coordinate::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::Coordinate>}!) in block {
       #t1.{self::Coordinate::x} = x;
@@ -50,22 +50,22 @@
   #C7 = core::pragma {name:#C1, options:#C6}
   #C8 = ffi::Double {}
   #C9 = 0
-  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect
index 8fae114..b190b3a 100644
--- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect
@@ -34,7 +34,7 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect
index 8fae114..b190b3a 100644
--- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect
@@ -34,7 +34,7 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect
index 6b19c1d..fccf634 100644
--- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect
@@ -24,9 +24,9 @@
   set y(core::double #externalFieldValue) → void
     return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C12.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
   get next() → ffi::Pointer<self::Coordinate>
-    return ffi::_fromAddress<self::Coordinate>(ffi::_loadIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
+    return ffi::_fromAddress<self::Coordinate>(ffi::_loadAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}));
   set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void
-    return ffi::_storeIntPtr(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Pointer::address}{core::int});
+    return ffi::_storeAbiSpecificInt<ffi::IntPtr>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C14.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Pointer::address}{core::int});
   static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
     return let final self::Coordinate #t1 = new self::Coordinate::#fromTypedDataBase(allocator.{ffi::Allocator::allocate}<self::Coordinate>(self::Coordinate::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::Coordinate>}!) in block {
       #t1.{self::Coordinate::x} = x;
@@ -50,22 +50,22 @@
   #C7 = core::pragma {name:#C1, options:#C6}
   #C8 = ffi::Double {}
   #C9 = 0
-  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
+  #C10 = <core::int*>[#C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9, #C9]
   #C11 = 8
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 16
-  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
+  #C14 = <core::int*>[#C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13, #C13]
   #C15 = "vm:prefer-inline"
   #C16 = core::pragma {name:#C15, options:#C5}
   #C17 = 24
   #C18 = 20
-  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17]
+  #C19 = <core::int*>[#C17, #C17, #C18, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C18, #C17, #C17, #C17, #C17, #C17, #C17, #C17, #C17]
 }
 
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_sample.dart:
-- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9)
 - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9)
 - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
index 0db513d..4d771b3 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
index b41e171..f3903c0 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
@@ -42,8 +42,8 @@
   #C8 = core::pragma {name:#C1, options:#C7}
   #C9 = ffi::_ArraySize<ffi::NativeType> {dimension1:#C3, dimension2:#C6, dimension3:#C6, dimension4:#C6, dimension5:#C6, dimensions:#C6}
   #C10 = 0
-  #C11 = <core::int*>[#C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10]
-  #C12 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
+  #C11 = <core::int*>[#C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10]
+  #C12 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
   #C13 = <core::int*>[]
   #C14 = "vm:prefer-inline"
   #C15 = core::pragma {name:#C14, options:#C6}
@@ -52,5 +52,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
index e6c0f95..e179ab5 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
index e6c0f95..e179ab5 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
index c21a02f..24cfa96 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
@@ -42,8 +42,8 @@
   #C8 = core::pragma {name:#C1, options:#C7}
   #C9 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C3, dimension2:#C6, dimension3:#C6, dimension4:#C6, dimension5:#C6, dimensions:#C6}
   #C10 = 0
-  #C11 = <core::int*>[#C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10]
-  #C12 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
+  #C11 = <core::int*>[#C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10]
+  #C12 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
   #C13 = <core::int*>[]
   #C14 = "vm:prefer-inline"
   #C15 = core::pragma {name:#C14, options:#C6}
@@ -52,5 +52,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
index 0e058b1..dd7fa30 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
index dec8714..a16945b 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
@@ -67,8 +67,8 @@
   #C9 = 2
   #C10 = ffi::_ArraySize<ffi::NativeType> {dimension1:#C9, dimension2:#C9, dimension3:#C9, dimension4:#C6, dimension5:#C6, dimensions:#C6}
   #C11 = 0
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
-  #C13 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C13 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
   #C14 = <core::int*>[#C9, #C9]
   #C15 = "vm:prefer-inline"
   #C16 = core::pragma {name:#C15, options:#C6}
@@ -84,5 +84,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
index 5e4b756..be09548 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
index 5e4b756..be09548 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
index e5881fb..a83a86b 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
@@ -67,8 +67,8 @@
   #C9 = 2
   #C10 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C9, dimension2:#C9, dimension3:#C9, dimension4:#C6, dimension5:#C6, dimensions:#C6}
   #C11 = 0
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
-  #C13 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C13 = <core::int*>[#C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3, #C3]
   #C14 = <core::int*>[#C9, #C9]
   #C15 = "vm:prefer-inline"
   #C16 = core::pragma {name:#C15, options:#C6}
@@ -84,5 +84,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart b/pkg/front_end/testcases/nnbd/issue48131.dart
new file mode 100644
index 0000000..cf58ea6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {
+  new B<Object>().foo<int>();
+}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.strong.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.strong.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.strong.transformed.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline.expect
new file mode 100644
index 0000000..2e5ec26
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2e5ec26
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+abstract class A<X> {
+  void foo<Y extends X>() {}
+}
+
+class B<Z> extends A<Z> {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.modular.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.modular.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.outline.expect
new file mode 100644
index 0000000..8eabec2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void
+    ;
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    ;
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue48131.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.transformed.expect
new file mode 100644
index 0000000..c09fc11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue48131.dart.weak.transformed.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+  method foo<covariant-by-class Y extends self::A::X%>() → void {}
+}
+class B<Z extends core::Object? = dynamic> extends self::A<self::B::Z%> {
+  synthetic constructor •() → self::B<self::B::Z%>
+    : super self::A::•()
+    ;
+}
+static method main() → void {
+  new self::B::•<core::Object>().{self::A::foo}<core::int>(){() → void};
+}
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart b/pkg/front_end/testcases/rasta/supports_reflection.dart
index 4b53e52..3aaf5ea 100644
--- a/pkg/front_end/testcases/rasta/supports_reflection.dart
+++ b/pkg/front_end/testcases/rasta/supports_reflection.dart
@@ -1,7 +1,9 @@
 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
+
 // @dart=2.9
+
 main() {
   print(const bool.fromEnvironment("dart.library.mirrors"));
 }
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.expect b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.expect
index d2d46a3..362665c 100644
--- a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.expect
@@ -7,5 +7,5 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
 }
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.modular.expect b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.modular.expect
index d2d46a3..362665c 100644
--- a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.modular.expect
@@ -7,5 +7,5 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
 }
diff --git a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.transformed.expect
index d2d46a3..362665c 100644
--- a/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/supports_reflection.dart.weak.transformed.expect
@@ -7,5 +7,5 @@
 }
 
 constants  {
-  #C1 = false
+  #C1 = true
 }
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.expect
index ea65452..44094c4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.expect
@@ -27,8 +27,8 @@
     ;
   static get nonNullableStaticFieldWithInitializer1() → core::int
     return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55) : #t1{core::int};
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void
-    self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void
+    self::Class::_#nonNullableStaticFieldWithInitializer1 = nonNullableStaticFieldWithInitializer1#param;
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer1 = self::init<core::int?>(17);
@@ -36,14 +36,14 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer1;
   }
-  static set nullableStaticFieldWithInitializer1(core::int? #t3) → void {
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
+    self::Class::_#nullableStaticFieldWithInitializer1 = nullableStaticFieldWithInitializer1#param;
   }
   static get nonNullableStaticFieldWithInitializer2() → core::int
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t4{core::int};
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void
-    self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+    return let final core::int? #t2 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t2 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t2{core::int};
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void
+    self::Class::_#nonNullableStaticFieldWithInitializer2 = nonNullableStaticFieldWithInitializer2#param;
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer2 = self::init<core::int?>(17);
@@ -51,38 +51,38 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer2;
   }
-  static set nullableStaticFieldWithInitializer2(core::int? #t6) → void {
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
+    self::Class::_#nullableStaticFieldWithInitializer2 = nullableStaticFieldWithInitializer2#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int
-    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t7 == null ?{core::int} let final core::int #t8 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t8 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1") : #t7{core::int};
+    return let final core::int? #t3 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t3 == null ?{core::int} let final core::int #t4 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t4 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1") : #t3{core::int};
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int? #t9 = self::init<core::int?>(19);
+      final core::int? #t5 = self::init<core::int?>(19);
       if(self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t9;
+      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t5;
       self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
   }
   static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t10{core::int};
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void
-    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
+    return let final core::int? #t6 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t6 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t6{core::int};
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = nonNullableStaticFinalFieldWithInitializer2Init#param;
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int
-    return let final core::int? #t12 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t12 == null ?{core::int} let final core::int #t13 = (let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t15 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t14.{core::num::+}(1){(core::num) → core::int} in #t14) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t13 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2") : #t12{core::int};
+    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t7 == null ?{core::int} let final core::int #t8 = (let final core::int #t9 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t10 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t9.{core::num::+}(1){(core::num) → core::int} in #t9) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t8 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2") : #t7{core::int};
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16 == null ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t16{core::int};
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void
-    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+    return let final core::int? #t11 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t11 == null ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t11{core::int};
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = nullableStaticFinalFieldWithInitializer2Init#param;
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1){(core::num) → core::int} in #t19) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+      final core::int? #t12 = (let final core::int #t13 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
       if(self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t18;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t12;
       self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer2;
@@ -110,9 +110,9 @@
   return value;
 }
 static get nonNullableTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t21{core::int};
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void
-  self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+  return let final core::int? #t15 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t15 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t15{core::int};
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer1 = nonNullableTopLevelFieldWithInitializer1#param;
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
     self::_#nullableTopLevelFieldWithInitializer = self::init<core::int?>(123);
@@ -120,14 +120,14 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer;
 }
-static set nullableTopLevelFieldWithInitializer(core::int? #t23) → void {
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void {
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer = #t23;
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 }
 static get nonNullableTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t24{core::int};
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void
-  self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+  return let final core::int? #t16 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t16 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t16{core::int};
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer2 = nonNullableTopLevelFieldWithInitializer2#param;
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nullableTopLevelFieldWithInitializer2 = self::init<core::int?>(123);
@@ -135,38 +135,38 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer2;
 }
-static set nullableTopLevelFieldWithInitializer2(core::int? #t26) → void {
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer2 = #t26;
+  self::_#nullableTopLevelFieldWithInitializer2 = nullableTopLevelFieldWithInitializer2#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t27 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t27 == null ?{core::int} let final core::int #t28 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t28 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1") : #t27{core::int};
+  return let final core::int? #t17 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t17 == null ?{core::int} let final core::int #t18 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t18 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1") : #t17{core::int};
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int? #t29 = self::init<core::int?>(32);
+    final core::int? #t19 = self::init<core::int?>(32);
     if(self::_#nullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer1");
-    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t29;
+    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t19;
     self::_#nullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t30{core::int};
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void
-  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
+  return let final core::int? #t20 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t20 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t20{core::int};
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = nonNullableFinalTopLevelFieldWithInitializer2Init#param;
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t32 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t32 == null ?{core::int} let final core::int #t33 = (let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t35 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t34.{core::num::+}(1){(core::num) → core::int} in #t34) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t33 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2") : #t32{core::int};
+  return let final core::int? #t21 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t21 == null ?{core::int} let final core::int #t22 = (let final core::int #t23 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t24 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t23.{core::num::+}(1){(core::num) → core::int} in #t23) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t22 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2") : #t21{core::int};
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36 == null ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t36{core::int};
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void
-  self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+  return let final core::int? #t25 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t25 == null ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t25{core::int};
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init = nullableFinalTopLevelFieldWithInitializer2Init#param;
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1){(core::num) → core::int} in #t39) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+    final core::int? #t26 = (let final core::int #t27 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t28 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t27.{core::num::+}(1){(core::num) → core::int} in #t27) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
     if(self::_#nullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer2");
-    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t38;
+    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t26;
     self::_#nullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer2;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.transformed.expect
index ea65452..44094c4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.strong.transformed.expect
@@ -27,8 +27,8 @@
     ;
   static get nonNullableStaticFieldWithInitializer1() → core::int
     return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55) : #t1{core::int};
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void
-    self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void
+    self::Class::_#nonNullableStaticFieldWithInitializer1 = nonNullableStaticFieldWithInitializer1#param;
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer1 = self::init<core::int?>(17);
@@ -36,14 +36,14 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer1;
   }
-  static set nullableStaticFieldWithInitializer1(core::int? #t3) → void {
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
+    self::Class::_#nullableStaticFieldWithInitializer1 = nullableStaticFieldWithInitializer1#param;
   }
   static get nonNullableStaticFieldWithInitializer2() → core::int
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t4{core::int};
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void
-    self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+    return let final core::int? #t2 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t2 == null ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t2{core::int};
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void
+    self::Class::_#nonNullableStaticFieldWithInitializer2 = nonNullableStaticFieldWithInitializer2#param;
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer2 = self::init<core::int?>(17);
@@ -51,38 +51,38 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer2;
   }
-  static set nullableStaticFieldWithInitializer2(core::int? #t6) → void {
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
+    self::Class::_#nullableStaticFieldWithInitializer2 = nullableStaticFieldWithInitializer2#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int
-    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t7 == null ?{core::int} let final core::int #t8 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t8 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1") : #t7{core::int};
+    return let final core::int? #t3 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t3 == null ?{core::int} let final core::int #t4 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t4 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1") : #t3{core::int};
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int? #t9 = self::init<core::int?>(19);
+      final core::int? #t5 = self::init<core::int?>(19);
       if(self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t9;
+      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t5;
       self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
   }
   static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t10{core::int};
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void
-    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
+    return let final core::int? #t6 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t6 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t6{core::int};
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = nonNullableStaticFinalFieldWithInitializer2Init#param;
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int
-    return let final core::int? #t12 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t12 == null ?{core::int} let final core::int #t13 = (let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t15 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t14.{core::num::+}(1){(core::num) → core::int} in #t14) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t13 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2") : #t12{core::int};
+    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t7 == null ?{core::int} let final core::int #t8 = (let final core::int #t9 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t10 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t9.{core::num::+}(1){(core::num) → core::int} in #t9) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2 == null ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t8 : throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2") : #t7{core::int};
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16 == null ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t16{core::int};
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void
-    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+    return let final core::int? #t11 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t11 == null ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t11{core::int};
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = nullableStaticFinalFieldWithInitializer2Init#param;
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1){(core::num) → core::int} in #t19) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+      final core::int? #t12 = (let final core::int #t13 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
       if(self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t18;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t12;
       self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer2;
@@ -110,9 +110,9 @@
   return value;
 }
 static get nonNullableTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t21{core::int};
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void
-  self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+  return let final core::int? #t15 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t15 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t15{core::int};
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer1 = nonNullableTopLevelFieldWithInitializer1#param;
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
     self::_#nullableTopLevelFieldWithInitializer = self::init<core::int?>(123);
@@ -120,14 +120,14 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer;
 }
-static set nullableTopLevelFieldWithInitializer(core::int? #t23) → void {
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void {
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer = #t23;
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 }
 static get nonNullableTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t24{core::int};
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void
-  self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+  return let final core::int? #t16 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t16 == null ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t16{core::int};
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void
+  self::_#nonNullableTopLevelFieldWithInitializer2 = nonNullableTopLevelFieldWithInitializer2#param;
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nullableTopLevelFieldWithInitializer2 = self::init<core::int?>(123);
@@ -135,38 +135,38 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer2;
 }
-static set nullableTopLevelFieldWithInitializer2(core::int? #t26) → void {
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer2 = #t26;
+  self::_#nullableTopLevelFieldWithInitializer2 = nullableTopLevelFieldWithInitializer2#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t27 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t27 == null ?{core::int} let final core::int #t28 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t28 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1") : #t27{core::int};
+  return let final core::int? #t17 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t17 == null ?{core::int} let final core::int #t18 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t18 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1") : #t17{core::int};
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int? #t29 = self::init<core::int?>(32);
+    final core::int? #t19 = self::init<core::int?>(32);
     if(self::_#nullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer1");
-    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t29;
+    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t19;
     self::_#nullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t30{core::int};
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void
-  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
+  return let final core::int? #t20 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t20 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t20{core::int};
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = nonNullableFinalTopLevelFieldWithInitializer2Init#param;
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t32 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t32 == null ?{core::int} let final core::int #t33 = (let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t35 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t34.{core::num::+}(1){(core::num) → core::int} in #t34) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t33 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2") : #t32{core::int};
+  return let final core::int? #t21 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t21 == null ?{core::int} let final core::int #t22 = (let final core::int #t23 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t24 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t23.{core::num::+}(1){(core::num) → core::int} in #t23) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2 == null ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t22 : throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2") : #t21{core::int};
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36 == null ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t36{core::int};
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void
-  self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+  return let final core::int? #t25 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t25 == null ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t25{core::int};
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init = nullableFinalTopLevelFieldWithInitializer2Init#param;
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1){(core::num) → core::int} in #t39) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+    final core::int? #t26 = (let final core::int #t27 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t28 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t27.{core::num::+}(1){(core::num) → core::int} in #t27) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
     if(self::_#nullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer2");
-    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t38;
+    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t26;
     self::_#nullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer2;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
index bae037b..ca912ed 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
@@ -38,9 +38,9 @@
     }
     return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void {
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+    self::Class::_#nonNullableStaticFieldWithInitializer1 = nonNullableStaticFieldWithInitializer1#param;
   }
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
@@ -49,20 +49,20 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer1;
   }
-  static set nullableStaticFieldWithInitializer1(core::int? #t3) → void {
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
+    self::Class::_#nullableStaticFieldWithInitializer1 = nullableStaticFieldWithInitializer1#param;
   }
   static get nonNullableStaticFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55);
       self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4{core::int};
+    return let final core::int? #t2 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t2{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void {
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+    self::Class::_#nonNullableStaticFieldWithInitializer2 = nonNullableStaticFieldWithInitializer2#param;
   }
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
@@ -71,26 +71,26 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer2;
   }
-  static set nullableStaticFieldWithInitializer2(core::int? #t6) → void {
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
+    self::Class::_#nullableStaticFieldWithInitializer2 = nullableStaticFieldWithInitializer2#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int #t7 = self::init<core::int>(73);
+      final core::int #t3 = self::init<core::int>(73);
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t7;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t3;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t8{core::int};
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t4{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int? #t9 = self::init<core::int?>(19);
+      final core::int? #t5 = self::init<core::int?>(19);
       if(self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t9;
+      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t5;
       self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
@@ -100,39 +100,39 @@
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10{core::int};
+    return let final core::int? #t6 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t6{core::int};
   }
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void {
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = nonNullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int #t12 = (let final core::int #t13 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+      final core::int #t7 = (let final core::int #t8 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t9 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t8.{core::num::+}(1){(core::num) → core::int} in #t8) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t12;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t7;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t15 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t15{core::int};
+    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t10{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet) {
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16{core::int};
+    return let final core::int? #t11 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t11{core::int};
   }
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void {
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = nullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1){(core::num) → core::int} in #t19) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+      final core::int? #t12 = (let final core::int #t13 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
       if(self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t18;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t12;
       self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer2;
@@ -170,11 +170,11 @@
     self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21{core::int};
+  return let final core::int? #t15 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t15{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void {
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+  self::_#nonNullableTopLevelFieldWithInitializer1 = nonNullableTopLevelFieldWithInitializer1#param;
 }
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
@@ -183,20 +183,20 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer;
 }
-static set nullableTopLevelFieldWithInitializer(core::int? #t23) → void {
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void {
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer = #t23;
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 }
 static get nonNullableTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24{core::int};
+  return let final core::int? #t16 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t16{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void {
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+  self::_#nonNullableTopLevelFieldWithInitializer2 = nonNullableTopLevelFieldWithInitializer2#param;
 }
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
@@ -205,26 +205,26 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer2;
 }
-static set nullableTopLevelFieldWithInitializer2(core::int? #t26) → void {
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer2 = #t26;
+  self::_#nullableTopLevelFieldWithInitializer2 = nullableTopLevelFieldWithInitializer2#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int #t27 = self::init<core::int>(87);
+    final core::int #t17 = self::init<core::int>(87);
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t27;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t17;
     self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t28 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t28{core::int};
+  return let final core::int? #t18 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t18{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int? #t29 = self::init<core::int?>(32);
+    final core::int? #t19 = self::init<core::int?>(32);
     if(self::_#nullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer1");
-    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t29;
+    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t19;
     self::_#nullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
@@ -234,39 +234,39 @@
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30{core::int};
+  return let final core::int? #t20 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t20{core::int};
 }
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void {
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = nonNullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int #t32 = (let final core::int #t33 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t33.{core::num::+}(1){(core::num) → core::int} in #t33) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+    final core::int #t21 = (let final core::int #t22 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t23 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t22.{core::num::+}(1){(core::num) → core::int} in #t22) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t32;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t21;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t35 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t35{core::int};
+  return let final core::int? #t24 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t24{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet) {
     self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36{core::int};
+  return let final core::int? #t25 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t25{core::int};
 }
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void {
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init = nullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1){(core::num) → core::int} in #t39) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+    final core::int? #t26 = (let final core::int #t27 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t28 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t27.{core::num::+}(1){(core::num) → core::int} in #t27) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
     if(self::_#nullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer2");
-    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t38;
+    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t26;
     self::_#nullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer2;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.modular.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.modular.expect
index bae037b..ca912ed 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.modular.expect
@@ -38,9 +38,9 @@
     }
     return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void {
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+    self::Class::_#nonNullableStaticFieldWithInitializer1 = nonNullableStaticFieldWithInitializer1#param;
   }
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
@@ -49,20 +49,20 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer1;
   }
-  static set nullableStaticFieldWithInitializer1(core::int? #t3) → void {
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
+    self::Class::_#nullableStaticFieldWithInitializer1 = nullableStaticFieldWithInitializer1#param;
   }
   static get nonNullableStaticFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55);
       self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4{core::int};
+    return let final core::int? #t2 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t2{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void {
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+    self::Class::_#nonNullableStaticFieldWithInitializer2 = nonNullableStaticFieldWithInitializer2#param;
   }
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
@@ -71,26 +71,26 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer2;
   }
-  static set nullableStaticFieldWithInitializer2(core::int? #t6) → void {
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
+    self::Class::_#nullableStaticFieldWithInitializer2 = nullableStaticFieldWithInitializer2#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int #t7 = self::init<core::int>(73);
+      final core::int #t3 = self::init<core::int>(73);
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t7;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t3;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t8{core::int};
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t4{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int? #t9 = self::init<core::int?>(19);
+      final core::int? #t5 = self::init<core::int?>(19);
       if(self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t9;
+      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t5;
       self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
@@ -100,39 +100,39 @@
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10{core::int};
+    return let final core::int? #t6 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t6{core::int};
   }
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void {
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = nonNullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int #t12 = (let final core::int #t13 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+      final core::int #t7 = (let final core::int #t8 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t9 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t8.{core::num::+}(1){(core::num) → core::int} in #t8) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t12;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t7;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t15 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t15{core::int};
+    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t10{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet) {
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16{core::int};
+    return let final core::int? #t11 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t11{core::int};
   }
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void {
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = nullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1){(core::num) → core::int} in #t19) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+      final core::int? #t12 = (let final core::int #t13 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
       if(self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t18;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t12;
       self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer2;
@@ -170,11 +170,11 @@
     self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21{core::int};
+  return let final core::int? #t15 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t15{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void {
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+  self::_#nonNullableTopLevelFieldWithInitializer1 = nonNullableTopLevelFieldWithInitializer1#param;
 }
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
@@ -183,20 +183,20 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer;
 }
-static set nullableTopLevelFieldWithInitializer(core::int? #t23) → void {
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void {
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer = #t23;
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 }
 static get nonNullableTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24{core::int};
+  return let final core::int? #t16 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t16{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void {
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+  self::_#nonNullableTopLevelFieldWithInitializer2 = nonNullableTopLevelFieldWithInitializer2#param;
 }
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
@@ -205,26 +205,26 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer2;
 }
-static set nullableTopLevelFieldWithInitializer2(core::int? #t26) → void {
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer2 = #t26;
+  self::_#nullableTopLevelFieldWithInitializer2 = nullableTopLevelFieldWithInitializer2#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int #t27 = self::init<core::int>(87);
+    final core::int #t17 = self::init<core::int>(87);
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t27;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t17;
     self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t28 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t28{core::int};
+  return let final core::int? #t18 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t18{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int? #t29 = self::init<core::int?>(32);
+    final core::int? #t19 = self::init<core::int?>(32);
     if(self::_#nullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer1");
-    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t29;
+    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t19;
     self::_#nullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
@@ -234,39 +234,39 @@
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30{core::int};
+  return let final core::int? #t20 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t20{core::int};
 }
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void {
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = nonNullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int #t32 = (let final core::int #t33 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t33.{core::num::+}(1){(core::num) → core::int} in #t33) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+    final core::int #t21 = (let final core::int #t22 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t23 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t22.{core::num::+}(1){(core::num) → core::int} in #t22) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t32;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t21;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t35 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t35{core::int};
+  return let final core::int? #t24 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t24{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet) {
     self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36{core::int};
+  return let final core::int? #t25 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t25{core::int};
 }
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void {
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init = nullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1){(core::num) → core::int} in #t39) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+    final core::int? #t26 = (let final core::int #t27 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t28 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t27.{core::num::+}(1){(core::num) → core::int} in #t27) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
     if(self::_#nullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer2");
-    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t38;
+    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t26;
     self::_#nullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer2;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.outline.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.outline.expect
index 0a31045..8aa1361 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.outline.expect
@@ -30,20 +30,20 @@
   synthetic constructor •() → self::Class
     ;
   static get nonNullableStaticFieldWithInitializer1() → core::int;
-  static set nonNullableStaticFieldWithInitializer1(core::int #t1) → void;
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void;
   static get nullableStaticFieldWithInitializer1() → core::int?;
-  static set nullableStaticFieldWithInitializer1(core::int? #t2) → void;
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void;
   static get nonNullableStaticFieldWithInitializer2() → core::int;
-  static set nonNullableStaticFieldWithInitializer2(core::int #t3) → void;
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void;
   static get nullableStaticFieldWithInitializer2() → core::int?;
-  static set nullableStaticFieldWithInitializer2(core::int? #t4) → void;
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void;
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int;
   static get nullableStaticFinalFieldWithInitializer1() → core::int?;
   static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int;
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t5) → void;
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void;
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int;
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int;
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t6) → void;
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void;
   static get nullableStaticFinalFieldWithInitializer2() → core::int?;
 }
 static field dynamic lastInit;
@@ -72,20 +72,20 @@
 static method init<T extends core::Object? = dynamic>(self::init::T% value) → self::init::T%
   ;
 static get nonNullableTopLevelFieldWithInitializer1() → core::int;
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t7) → void;
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void;
 static get nullableTopLevelFieldWithInitializer() → core::int?;
-static set nullableTopLevelFieldWithInitializer(core::int? #t8) → void;
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void;
 static get nonNullableTopLevelFieldWithInitializer2() → core::int;
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t9) → void;
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void;
 static get nullableTopLevelFieldWithInitializer2() → core::int?;
-static set nullableTopLevelFieldWithInitializer2(core::int? #t10) → void;
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void;
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int;
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int?;
 static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int;
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t11) → void;
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void;
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int;
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int;
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t12) → void;
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void;
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int?;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
index bae037b..ca912ed 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
@@ -38,9 +38,9 @@
     }
     return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void {
+  static set nonNullableStaticFieldWithInitializer1(core::int nonNullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+    self::Class::_#nonNullableStaticFieldWithInitializer1 = nonNullableStaticFieldWithInitializer1#param;
   }
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
@@ -49,20 +49,20 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer1;
   }
-  static set nullableStaticFieldWithInitializer1(core::int? #t3) → void {
+  static set nullableStaticFieldWithInitializer1(core::int? nullableStaticFieldWithInitializer1#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
+    self::Class::_#nullableStaticFieldWithInitializer1 = nullableStaticFieldWithInitializer1#param;
   }
   static get nonNullableStaticFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55);
       self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4{core::int};
+    return let final core::int? #t2 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t2{core::int};
   }
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void {
+  static set nonNullableStaticFieldWithInitializer2(core::int nonNullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+    self::Class::_#nonNullableStaticFieldWithInitializer2 = nonNullableStaticFieldWithInitializer2#param;
   }
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
@@ -71,26 +71,26 @@
     }
     return self::Class::_#nullableStaticFieldWithInitializer2;
   }
-  static set nullableStaticFieldWithInitializer2(core::int? #t6) → void {
+  static set nullableStaticFieldWithInitializer2(core::int? nullableStaticFieldWithInitializer2#param) → void {
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
-    self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
+    self::Class::_#nullableStaticFieldWithInitializer2 = nullableStaticFieldWithInitializer2#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer1() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int #t7 = self::init<core::int>(73);
+      final core::int #t3 = self::init<core::int>(73);
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t7;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t3;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet = true;
     }
-    return let final core::int? #t8 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t8{core::int};
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t4{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
-      final core::int? #t9 = self::init<core::int?>(19);
+      final core::int? #t5 = self::init<core::int?>(19);
       if(self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer1");
-      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t9;
+      self::Class::_#nullableStaticFinalFieldWithInitializer1 = #t5;
       self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
@@ -100,39 +100,39 @@
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10{core::int};
+    return let final core::int? #t6 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t6{core::int};
   }
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void {
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int nonNullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = nonNullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nonNullableStaticFinalFieldWithInitializer2() → core::int {
     if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int #t12 = (let final core::int #t13 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+      final core::int #t7 = (let final core::int #t8 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t9 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t8.{core::num::+}(1){(core::num) → core::int} in #t8) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
       if(self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nonNullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t12;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t7;
       self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet = true;
     }
-    return let final core::int? #t15 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t15{core::int};
+    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t10{core::int};
   }
   static get nullableStaticFinalFieldWithInitializer2Init() → core::int {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet) {
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0;
       self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
     }
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16{core::int};
+    return let final core::int? #t11 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t11{core::int};
   }
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void {
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int nullableStaticFinalFieldWithInitializer2Init#param) → void {
     self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
-    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init = nullableStaticFinalFieldWithInitializer2Init#param;
   }
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
-      final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1){(core::num) → core::int} in #t19) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+      final core::int? #t12 = (let final core::int #t13 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1){(core::num) → core::int} in #t13) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
       if(self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet)
         throw new _in::LateError::fieldADI("nullableStaticFinalFieldWithInitializer2");
-      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t18;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2 = #t12;
       self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet = true;
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer2;
@@ -170,11 +170,11 @@
     self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21{core::int};
+  return let final core::int? #t15 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t15{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void {
+static set nonNullableTopLevelFieldWithInitializer1(core::int nonNullableTopLevelFieldWithInitializer1#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+  self::_#nonNullableTopLevelFieldWithInitializer1 = nonNullableTopLevelFieldWithInitializer1#param;
 }
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
@@ -183,20 +183,20 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer;
 }
-static set nullableTopLevelFieldWithInitializer(core::int? #t23) → void {
+static set nullableTopLevelFieldWithInitializer(core::int? nullableTopLevelFieldWithInitializer#param) → void {
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer = #t23;
+  self::_#nullableTopLevelFieldWithInitializer = nullableTopLevelFieldWithInitializer#param;
 }
 static get nonNullableTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42);
     self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24{core::int};
+  return let final core::int? #t16 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t16{core::int};
 }
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void {
+static set nonNullableTopLevelFieldWithInitializer2(core::int nonNullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+  self::_#nonNullableTopLevelFieldWithInitializer2 = nonNullableTopLevelFieldWithInitializer2#param;
 }
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
@@ -205,26 +205,26 @@
   }
   return self::_#nullableTopLevelFieldWithInitializer2;
 }
-static set nullableTopLevelFieldWithInitializer2(core::int? #t26) → void {
+static set nullableTopLevelFieldWithInitializer2(core::int? nullableTopLevelFieldWithInitializer2#param) → void {
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
-  self::_#nullableTopLevelFieldWithInitializer2 = #t26;
+  self::_#nullableTopLevelFieldWithInitializer2 = nullableTopLevelFieldWithInitializer2#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int #t27 = self::init<core::int>(87);
+    final core::int #t17 = self::init<core::int>(87);
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer1");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t27;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t17;
     self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
-  return let final core::int? #t28 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t28{core::int};
+  return let final core::int? #t18 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t18{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
-    final core::int? #t29 = self::init<core::int?>(32);
+    final core::int? #t19 = self::init<core::int?>(32);
     if(self::_#nullableFinalTopLevelFieldWithInitializer1#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer1");
-    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t29;
+    self::_#nullableFinalTopLevelFieldWithInitializer1 = #t19;
     self::_#nullableFinalTopLevelFieldWithInitializer1#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
@@ -234,39 +234,39 @@
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30{core::int};
+  return let final core::int? #t20 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t20{core::int};
 }
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void {
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int nonNullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = nonNullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int {
   if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int #t32 = (let final core::int #t33 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t33.{core::num::+}(1){(core::num) → core::int} in #t33) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
+    final core::int #t21 = (let final core::int #t22 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t23 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t22.{core::num::+}(1){(core::num) → core::int} in #t22) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1){(core::num) → core::int} : 87;
     if(self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nonNullableFinalTopLevelFieldWithInitializer2");
-    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t32;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t21;
     self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
-  return let final core::int? #t35 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t35{core::int};
+  return let final core::int? #t24 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t24{core::int};
 }
 static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet) {
     self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0;
     self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   }
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36{core::int};
+  return let final core::int? #t25 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t25{core::int};
 }
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void {
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int nullableFinalTopLevelFieldWithInitializer2Init#param) → void {
   self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
-  self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init = nullableFinalTopLevelFieldWithInitializer2Init#param;
 }
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
-    final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1){(core::num) → core::int} in #t39) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
+    final core::int? #t26 = (let final core::int #t27 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t28 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t27.{core::num::+}(1){(core::num) → core::int} in #t27) =={core::num::==}{(core::Object) → core::bool} 0 ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1){(core::num) → core::int} : 32;
     if(self::_#nullableFinalTopLevelFieldWithInitializer2#isSet)
       throw new _in::LateError::fieldADI("nullableFinalTopLevelFieldWithInitializer2");
-    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t38;
+    self::_#nullableFinalTopLevelFieldWithInitializer2 = #t26;
     self::_#nullableFinalTopLevelFieldWithInitializer2#isSet = true;
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer2;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 2aef19d..f57bbdf 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -15,6 +15,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+enhanced_enums/simple_mixins: RuntimeError
 extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/call_not_get: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart
new file mode 100644
index 0000000..9a48c68
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+B1 f1() => throw 42;
+
+class A1 {
+  var foo = f1(); // Ok.
+  A1(this.foo);
+}
+
+class B1 extends A1 {
+  B1(super.foo) : super();
+}
+
+class A2 {
+  var foo = B2.new; // Error.
+  A2(this.foo);
+}
+
+class B2 extends A2 {
+  B2(super.foo) : super();
+}
+
+class A3 {
+  var foo = C3.new; // Error.
+  A3();
+  A3.initializeFoo(this.foo);
+}
+
+class B3 extends A3 {
+  var bar = A3.initializeFoo;
+  B3(this.bar) : super();
+}
+
+class C3 extends B3 {
+  C3(super.bar) : super();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.expect
new file mode 100644
index 0000000..063d341
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo = self::f1();
+  constructor •(self::B1 foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo = #C1;
+  constructor •(invalid-type foo) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    : super self::A2::•(foo)
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo = #C2;
+  constructor •() → self::A3
+    : super core::Object::•()
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar = #C3;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    : self::B3::bar = bar, super self::A3::•()
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    : super self::B3::•(bar)
+    ;
+}
+static method f1() → self::B1
+  return throw 42;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::B2::•
+  #C2 = constructor-tearoff self::C3::•
+  #C3 = constructor-tearoff self::A3::initializeFoo
+}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.transformed.expect
new file mode 100644
index 0000000..063d341
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.strong.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo = self::f1();
+  constructor •(self::B1 foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo = #C1;
+  constructor •(invalid-type foo) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    : super self::A2::•(foo)
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo = #C2;
+  constructor •() → self::A3
+    : super core::Object::•()
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar = #C3;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    : self::B3::bar = bar, super self::A3::•()
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    : super self::B3::•(bar)
+    ;
+}
+static method f1() → self::B1
+  return throw 42;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::B2::•
+  #C2 = constructor-tearoff self::C3::•
+  #C3 = constructor-tearoff self::A3::initializeFoo
+}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.textual_outline.expect
new file mode 100644
index 0000000..94dbab2
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+B1 f1() => throw 42;
+class A1 {
+  var foo = f1();
+  A1(this.foo);
+}
+class B1 extends A1 {
+  B1(super.foo) : super();
+}
+class A2 {
+  var foo = B2.new;
+  A2(this.foo);
+}
+class B2 extends A2 {
+  B2(super.foo) : super();
+}
+class A3 {
+  var foo = C3.new;
+  A3();
+  A3.initializeFoo(this.foo);
+}
+class B3 extends A3 {
+  var bar = A3.initializeFoo;
+  B3(this.bar) : super();
+}
+class C3 extends B3 {
+  C3(super.bar) : super();
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.expect
new file mode 100644
index 0000000..063d341
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo = self::f1();
+  constructor •(self::B1 foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo = #C1;
+  constructor •(invalid-type foo) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    : super self::A2::•(foo)
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo = #C2;
+  constructor •() → self::A3
+    : super core::Object::•()
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar = #C3;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    : self::B3::bar = bar, super self::A3::•()
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    : super self::B3::•(bar)
+    ;
+}
+static method f1() → self::B1
+  return throw 42;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::B2::•
+  #C2 = constructor-tearoff self::C3::•
+  #C3 = constructor-tearoff self::A3::initializeFoo
+}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.modular.expect
new file mode 100644
index 0000000..063d341
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.modular.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo = self::f1();
+  constructor •(self::B1 foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo = #C1;
+  constructor •(invalid-type foo) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    : super self::A2::•(foo)
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo = #C2;
+  constructor •() → self::A3
+    : super core::Object::•()
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar = #C3;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    : self::B3::bar = bar, super self::A3::•()
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    : super self::B3::•(bar)
+    ;
+}
+static method f1() → self::B1
+  return throw 42;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::B2::•
+  #C2 = constructor-tearoff self::C3::•
+  #C3 = constructor-tearoff self::A3::initializeFoo
+}
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.outline.expect
new file mode 100644
index 0000000..1647019
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.outline.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo;
+  constructor •(self::B1 foo) → self::A1
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo;
+  constructor •(invalid-type foo) → self::A2
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo;
+  constructor •() → self::A3
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    ;
+}
+static method f1() → self::B1
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.transformed.expect
new file mode 100644
index 0000000..063d341
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart.weak.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:17:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = B2.new; // Error.
+//       ^^^
+//
+// pkg/front_end/testcases/super_parameters/circular_dependency_inference.dart:26:7: Error: Can't infer the type of 'foo': circularity found during type inference.
+// Specify the type explicitly.
+//   var foo = C3.new; // Error.
+//       ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  field self::B1 foo = self::f1();
+  constructor •(self::B1 foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(self::B1 foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  field invalid-type foo = #C1;
+  constructor •(invalid-type foo) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •(invalid-type foo) → self::B2
+    : super self::A2::•(foo)
+    ;
+}
+class A3 extends core::Object {
+  field invalid-type foo = #C2;
+  constructor •() → self::A3
+    : super core::Object::•()
+    ;
+  constructor initializeFoo(invalid-type foo) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  field (invalid-type) → self::A3 bar = #C3;
+  constructor •((invalid-type) → self::A3 bar) → self::B3
+    : self::B3::bar = bar, super self::A3::•()
+    ;
+}
+class C3 extends self::B3 {
+  constructor •((invalid-type) → self::A3 bar) → self::C3
+    : super self::B3::•(bar)
+    ;
+}
+static method f1() → self::B1
+  return throw 42;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::B2::•
+  #C2 = constructor-tearoff self::C3::•
+  #C3 = constructor-tearoff self::A3::initializeFoo
+}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart b/pkg/front_end/testcases/super_parameters/default_values.dart
new file mode 100644
index 0000000..515a046
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 S1 {
+  int s;
+  S1([int x = 0]) : s = x - 1;
+}
+
+class C1 extends S1 {
+  int c;
+  C1([super.x]) : c = x + 1; // Ok.
+}
+
+class S2 {
+  int s;
+  S2({int x = 0}) : s = x - 1;
+}
+
+class C2 extends S2 {
+  int c;
+  C2({super.x}) : c = x + 1; // Ok.
+}
+
+class S3 {
+  int s;
+  S3([int x = 0]) : s = x - 1;
+}
+
+class C3 extends S3 {
+  int c;
+  C3([super.x = 42]) : c = x + 1; // Ok.
+}
+
+class S4 {
+  int s;
+  S4({int x = 0}) : s = x - 1;
+}
+
+class C4 extends S4 {
+  int c;
+  C4({super.x = 42}) : c = x + 1; // Ok.
+}
+
+class S5 {
+  num a;
+  S5([num x = 3.14]) : a = x - 1;
+}
+
+class C5 extends S5 {
+  C5([int super.x]); // Error.
+}
+
+class S6 {
+  num? a;
+  S6([num? x = 3.14]) : a = x;
+}
+
+class C6 extends S6 {
+  int? b;
+  C6([int? super.x]); // Ok.
+}
+
+class S7 {
+  int s;
+  S7([int x = 0]) : s = x - 1;
+}
+
+class C7 extends S7 {
+  int c;
+  C7([super.x]) : c = x + 1;
+}
+
+class CC7 extends C7 {
+  int cc;
+  CC7([super.x]) : cc = x * 1;
+}
+
+class S8 {
+  int s;
+  S8([int x = 0]) : s = x - 1;
+}
+
+class CC8 extends C8 {
+  int cc;
+  CC8([super.x]) : cc = x * 1;
+}
+
+class C8 extends S8 {
+  int c;
+  C8([super.x]) : c = x + 1;
+}
+
+class CC9 extends C9 {
+  int cc;
+  CC9([super.x]) : cc = x * 1;
+}
+
+class C9 extends S9 {
+  int c;
+  C9([super.x]) : c = x + 1;
+}
+
+class S9 {
+  int s;
+  S9([int x = 0]) : s = x - 1;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.strong.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.strong.expect
new file mode 100644
index 0000000..29ffdbc
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.strong.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S1
+    : self::S1::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C1
+    : self::C1::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S1::•(x)
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S2
+    : self::S2::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = #C1}) → self::C2
+    : self::C2::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S2::•(x: x)
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S3
+    : self::S3::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = #C2]) → self::C3
+    : self::C3::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S3::•(x)
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S4
+    : self::S4::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = #C2}) → self::C4
+    : self::C4::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S4::•(x: x)
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = #C3]) → self::S5
+    : self::S5::a = x.{core::num::-}(1){(core::num) → core::num}, super core::Object::•()
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x = #C4]) → self::C5
+    : super self::S5::•(x)
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = #C3]) → self::S6
+    : self::S6::a = x, super core::Object::•()
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b = null;
+  constructor •([core::int? x = #C4]) → self::C6
+    : super self::S6::•(x)
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S7
+    : self::S7::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C7
+    : self::C7::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S7::•(x)
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC7
+    : self::CC7::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C7::•(x)
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S8
+    : self::S8::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC8
+    : self::CC8::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C8::•(x)
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C8
+    : self::C8::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S8::•(x)
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC9
+    : self::CC9::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C9::•(x)
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C9
+    : self::C9::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S9::•(x)
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S9
+    : self::S9::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+  #C3 = 3.14
+  #C4 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..29ffdbc
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.strong.transformed.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S1
+    : self::S1::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C1
+    : self::C1::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S1::•(x)
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S2
+    : self::S2::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = #C1}) → self::C2
+    : self::C2::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S2::•(x: x)
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S3
+    : self::S3::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = #C2]) → self::C3
+    : self::C3::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S3::•(x)
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S4
+    : self::S4::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = #C2}) → self::C4
+    : self::C4::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S4::•(x: x)
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = #C3]) → self::S5
+    : self::S5::a = x.{core::num::-}(1){(core::num) → core::num}, super core::Object::•()
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x = #C4]) → self::C5
+    : super self::S5::•(x)
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = #C3]) → self::S6
+    : self::S6::a = x, super core::Object::•()
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b = null;
+  constructor •([core::int? x = #C4]) → self::C6
+    : super self::S6::•(x)
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S7
+    : self::S7::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C7
+    : self::C7::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S7::•(x)
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC7
+    : self::CC7::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C7::•(x)
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S8
+    : self::S8::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC8
+    : self::CC8::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C8::•(x)
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C8
+    : self::C8::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S8::•(x)
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC9
+    : self::CC9::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C9::•(x)
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C9
+    : self::C9::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S9::•(x)
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S9
+    : self::S9::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+  #C3 = 3.14
+  #C4 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..1cb3689
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.textual_outline.expect
@@ -0,0 +1,84 @@
+class S1 {
+  int s;
+  S1([int x = 0]) : s = x - 1;
+}
+class C1 extends S1 {
+  int c;
+  C1([super.x]) : c = x + 1;
+}
+class S2 {
+  int s;
+  S2({int x = 0}) : s = x - 1;
+}
+class C2 extends S2 {
+  int c;
+  C2({super.x}) : c = x + 1;
+}
+class S3 {
+  int s;
+  S3([int x = 0]) : s = x - 1;
+}
+class C3 extends S3 {
+  int c;
+  C3([super.x = 42]) : c = x + 1;
+}
+class S4 {
+  int s;
+  S4({int x = 0}) : s = x - 1;
+}
+class C4 extends S4 {
+  int c;
+  C4({super.x = 42}) : c = x + 1;
+}
+class S5 {
+  num a;
+  S5([num x = 3.14]) : a = x - 1;
+}
+class C5 extends S5 {
+  C5([int super.x]);
+}
+class S6 {
+  num? a;
+  S6([num? x = 3.14]) : a = x;
+}
+class C6 extends S6 {
+  int? b;
+  C6([int? super.x]);
+}
+class S7 {
+  int s;
+  S7([int x = 0]) : s = x - 1;
+}
+class C7 extends S7 {
+  int c;
+  C7([super.x]) : c = x + 1;
+}
+class CC7 extends C7 {
+  int cc;
+  CC7([super.x]) : cc = x * 1;
+}
+class S8 {
+  int s;
+  S8([int x = 0]) : s = x - 1;
+}
+class CC8 extends C8 {
+  int cc;
+  CC8([super.x]) : cc = x * 1;
+}
+class C8 extends S8 {
+  int c;
+  C8([super.x]) : c = x + 1;
+}
+class CC9 extends C9 {
+  int cc;
+  CC9([super.x]) : cc = x * 1;
+}
+class C9 extends S9 {
+  int c;
+  C9([super.x]) : c = x + 1;
+}
+class S9 {
+  int s;
+  S9([int x = 0]) : s = x - 1;
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.weak.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.expect
new file mode 100644
index 0000000..29ffdbc
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S1
+    : self::S1::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C1
+    : self::C1::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S1::•(x)
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S2
+    : self::S2::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = #C1}) → self::C2
+    : self::C2::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S2::•(x: x)
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S3
+    : self::S3::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = #C2]) → self::C3
+    : self::C3::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S3::•(x)
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S4
+    : self::S4::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = #C2}) → self::C4
+    : self::C4::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S4::•(x: x)
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = #C3]) → self::S5
+    : self::S5::a = x.{core::num::-}(1){(core::num) → core::num}, super core::Object::•()
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x = #C4]) → self::C5
+    : super self::S5::•(x)
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = #C3]) → self::S6
+    : self::S6::a = x, super core::Object::•()
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b = null;
+  constructor •([core::int? x = #C4]) → self::C6
+    : super self::S6::•(x)
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S7
+    : self::S7::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C7
+    : self::C7::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S7::•(x)
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC7
+    : self::CC7::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C7::•(x)
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S8
+    : self::S8::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC8
+    : self::CC8::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C8::•(x)
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C8
+    : self::C8::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S8::•(x)
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC9
+    : self::CC9::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C9::•(x)
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C9
+    : self::C9::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S9::•(x)
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S9
+    : self::S9::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+  #C3 = 3.14
+  #C4 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.modular.expect
new file mode 100644
index 0000000..29ffdbc
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.modular.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S1
+    : self::S1::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C1
+    : self::C1::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S1::•(x)
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S2
+    : self::S2::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = #C1}) → self::C2
+    : self::C2::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S2::•(x: x)
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S3
+    : self::S3::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = #C2]) → self::C3
+    : self::C3::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S3::•(x)
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S4
+    : self::S4::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = #C2}) → self::C4
+    : self::C4::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S4::•(x: x)
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = #C3]) → self::S5
+    : self::S5::a = x.{core::num::-}(1){(core::num) → core::num}, super core::Object::•()
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x = #C4]) → self::C5
+    : super self::S5::•(x)
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = #C3]) → self::S6
+    : self::S6::a = x, super core::Object::•()
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b = null;
+  constructor •([core::int? x = #C4]) → self::C6
+    : super self::S6::•(x)
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S7
+    : self::S7::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C7
+    : self::C7::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S7::•(x)
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC7
+    : self::CC7::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C7::•(x)
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S8
+    : self::S8::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC8
+    : self::CC8::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C8::•(x)
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C8
+    : self::C8::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S8::•(x)
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC9
+    : self::CC9::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C9::•(x)
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C9
+    : self::C9::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S9::•(x)
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S9
+    : self::S9::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+  #C3 = 3.14
+  #C4 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..aca3fd0
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.outline.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = 0]) → self::S1
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = 0]) → self::C1
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = 0}) → self::S2
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = 0}) → self::C2
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = 0]) → self::S3
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = 42]) → self::C3
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = 0}) → self::S4
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = 42}) → self::C4
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = 3.14]) → self::S5
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x]) → self::C5
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = 3.14]) → self::S6
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b;
+  constructor •([core::int? x]) → self::C6
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = 0]) → self::S7
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = 0]) → self::C7
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = 0]) → self::CC7
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = 0]) → self::S8
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = 0]) → self::CC8
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = 0]) → self::C8
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = 0]) → self::CC9
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = 0]) → self::C9
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = 0]) → self::S9
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..29ffdbc
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/default_values.dart.weak.transformed.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/default_values.dart:51:17: Error: The parameter 'x' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
+// Try adding either an explicit non-'null' default value or the 'required' modifier.
+//   C5([int super.x]); // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S1
+    : self::S1::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C1
+    : self::C1::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S1::•(x)
+    ;
+}
+class S2 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S2
+    : self::S2::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C2 extends self::S2 {
+  field core::int c;
+  constructor •({core::int x = #C1}) → self::C2
+    : self::C2::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S2::•(x: x)
+    ;
+}
+class S3 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S3
+    : self::S3::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C3 extends self::S3 {
+  field core::int c;
+  constructor •([core::int x = #C2]) → self::C3
+    : self::C3::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S3::•(x)
+    ;
+}
+class S4 extends core::Object {
+  field core::int s;
+  constructor •({core::int x = #C1}) → self::S4
+    : self::S4::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C4 extends self::S4 {
+  field core::int c;
+  constructor •({core::int x = #C2}) → self::C4
+    : self::C4::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S4::•(x: x)
+    ;
+}
+class S5 extends core::Object {
+  field core::num a;
+  constructor •([core::num x = #C3]) → self::S5
+    : self::S5::a = x.{core::num::-}(1){(core::num) → core::num}, super core::Object::•()
+    ;
+}
+class C5 extends self::S5 {
+  constructor •([core::int x = #C4]) → self::C5
+    : super self::S5::•(x)
+    ;
+}
+class S6 extends core::Object {
+  field core::num? a;
+  constructor •([core::num? x = #C3]) → self::S6
+    : self::S6::a = x, super core::Object::•()
+    ;
+}
+class C6 extends self::S6 {
+  field core::int? b = null;
+  constructor •([core::int? x = #C4]) → self::C6
+    : super self::S6::•(x)
+    ;
+}
+class S7 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S7
+    : self::S7::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class C7 extends self::S7 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C7
+    : self::C7::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S7::•(x)
+    ;
+}
+class CC7 extends self::C7 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC7
+    : self::CC7::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C7::•(x)
+    ;
+}
+class S8 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S8
+    : self::S8::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+class CC8 extends self::C8 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC8
+    : self::CC8::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C8::•(x)
+    ;
+}
+class C8 extends self::S8 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C8
+    : self::C8::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S8::•(x)
+    ;
+}
+class CC9 extends self::C9 {
+  field core::int cc;
+  constructor •([core::int x = #C1]) → self::CC9
+    : self::CC9::cc = x.{core::num::*}(1){(core::num) → core::int}, super self::C9::•(x)
+    ;
+}
+class C9 extends self::S9 {
+  field core::int c;
+  constructor •([core::int x = #C1]) → self::C9
+    : self::C9::c = x.{core::num::+}(1){(core::num) → core::int}, super self::S9::•(x)
+    ;
+}
+class S9 extends core::Object {
+  field core::int s;
+  constructor •([core::int x = #C1]) → self::S9
+    : self::S9::s = x.{core::num::-}(1){(core::num) → core::int}, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+  #C3 = 3.14
+  #C4 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart b/pkg/front_end/testcases/super_parameters/issue48142.dart
new file mode 100644
index 0000000..d700eaf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 S1 {
+  int s1;
+  int s2;
+  S1(this.s1, [this.s2 = 42]);
+}
+
+class C1 extends S1 {
+  int i1;
+  int i2;
+  C1(this.i1, super.s1, int x, [super.s2]) : this.i2 = x;
+}
+
+class S2 {
+  S2({String one = "1", bool two = false, int three = 3, double four = 4,
+      num five = 3.14, List<String> six = const ["six"]});
+}
+
+class C21 extends S2 {
+  C21({dynamic foo, super.one, dynamic bar, dynamic baz, super.three,
+      super.five});
+}
+
+class C22 extends S2 {
+  C22({dynamic foo, super.six, dynamic bar, dynamic baz, super.four,
+      super.two});
+}
+
+class C23 extends S2 {
+  C23({super.three, dynamic foo, super.one, super.four, dynamic bar, super.two,
+      dynamic baz});
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.expect
new file mode 100644
index 0000000..c7cebd9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = #C1]) → self::S1
+    : self::S1::s1 = s1, self::S1::s2 = s2, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = #C1]) → self::C1
+    : self::C1::i1 = i1, self::C1::i2 = x, super self::S1::•(s1, s2)
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = #C2, core::bool two = #C3, core::int three = #C4, core::double four = #C5, core::num five = #C6, core::List<core::String> six = #C8}) → self::S2
+    : super core::Object::•()
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::String one = #C2, dynamic bar = #C9, dynamic baz = #C9, core::int three = #C4, core::num five = #C6}) → self::C21
+    : super self::S2::•(one: one, three: three, five: five)
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::List<core::String> six = #C8, dynamic bar = #C9, dynamic baz = #C9, core::double four = #C5, core::bool two = #C3}) → self::C22
+    : super self::S2::•(six: six, four: four, two: two)
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = #C4, dynamic foo = #C9, core::String one = #C2, core::double four = #C5, dynamic bar = #C9, core::bool two = #C3, dynamic baz = #C9}) → self::C23
+    : super self::S2::•(three: three, one: one, four: four, two: two)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 42
+  #C2 = "1"
+  #C3 = false
+  #C4 = 3
+  #C5 = 4.0
+  #C6 = 3.14
+  #C7 = "six"
+  #C8 = <core::String>[#C7]
+  #C9 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.transformed.expect
new file mode 100644
index 0000000..c7cebd9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.strong.transformed.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = #C1]) → self::S1
+    : self::S1::s1 = s1, self::S1::s2 = s2, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = #C1]) → self::C1
+    : self::C1::i1 = i1, self::C1::i2 = x, super self::S1::•(s1, s2)
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = #C2, core::bool two = #C3, core::int three = #C4, core::double four = #C5, core::num five = #C6, core::List<core::String> six = #C8}) → self::S2
+    : super core::Object::•()
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::String one = #C2, dynamic bar = #C9, dynamic baz = #C9, core::int three = #C4, core::num five = #C6}) → self::C21
+    : super self::S2::•(one: one, three: three, five: five)
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::List<core::String> six = #C8, dynamic bar = #C9, dynamic baz = #C9, core::double four = #C5, core::bool two = #C3}) → self::C22
+    : super self::S2::•(six: six, four: four, two: two)
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = #C4, dynamic foo = #C9, core::String one = #C2, core::double four = #C5, dynamic bar = #C9, core::bool two = #C3, dynamic baz = #C9}) → self::C23
+    : super self::S2::•(three: three, one: one, four: four, two: two)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 42
+  #C2 = "1"
+  #C3 = false
+  #C4 = 3
+  #C5 = 4.0
+  #C6 = 3.14
+  #C7 = "six"
+  #C8 = <core::String>[#C7]
+  #C9 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.textual_outline.expect
new file mode 100644
index 0000000..d25be67
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.textual_outline.expect
@@ -0,0 +1,23 @@
+class S1 {
+  int s1;
+  int s2;
+  S1(this.s1, [this.s2 = 42]);
+}
+class C1 extends S1 {
+  int i1;
+  int i2;
+  C1(this.i1, super.s1, int x, [super.s2]) : this.i2 = x;
+}
+class S2 {
+  S2({String one = "1", bool two = false, int three = 3, double four = 4, num five = 3.14, List<String> six = const ["six"]});
+}
+class C21 extends S2 {
+  C21({dynamic foo, super.one, dynamic bar, dynamic baz, super.three, super.five});
+}
+class C22 extends S2 {
+  C22({dynamic foo, super.six, dynamic bar, dynamic baz, super.four, super.two});
+}
+class C23 extends S2 {
+  C23({super.three, dynamic foo, super.one, super.four, dynamic bar, super.two, dynamic baz});
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.expect
new file mode 100644
index 0000000..e86004a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = #C1]) → self::S1
+    : self::S1::s1 = s1, self::S1::s2 = s2, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = #C1]) → self::C1
+    : self::C1::i1 = i1, self::C1::i2 = x, super self::S1::•(s1, s2)
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = #C2, core::bool two = #C3, core::int three = #C4, core::double four = #C5, core::num five = #C6, core::List<core::String> six = #C8}) → self::S2
+    : super core::Object::•()
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::String one = #C2, dynamic bar = #C9, dynamic baz = #C9, core::int three = #C4, core::num five = #C6}) → self::C21
+    : super self::S2::•(one: one, three: three, five: five)
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::List<core::String> six = #C8, dynamic bar = #C9, dynamic baz = #C9, core::double four = #C5, core::bool two = #C3}) → self::C22
+    : super self::S2::•(six: six, four: four, two: two)
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = #C4, dynamic foo = #C9, core::String one = #C2, core::double four = #C5, dynamic bar = #C9, core::bool two = #C3, dynamic baz = #C9}) → self::C23
+    : super self::S2::•(three: three, one: one, four: four, two: two)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 42
+  #C2 = "1"
+  #C3 = false
+  #C4 = 3
+  #C5 = 4.0
+  #C6 = 3.14
+  #C7 = "six"
+  #C8 = <core::String*>[#C7]
+  #C9 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.modular.expect
new file mode 100644
index 0000000..e86004a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.modular.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = #C1]) → self::S1
+    : self::S1::s1 = s1, self::S1::s2 = s2, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = #C1]) → self::C1
+    : self::C1::i1 = i1, self::C1::i2 = x, super self::S1::•(s1, s2)
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = #C2, core::bool two = #C3, core::int three = #C4, core::double four = #C5, core::num five = #C6, core::List<core::String> six = #C8}) → self::S2
+    : super core::Object::•()
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::String one = #C2, dynamic bar = #C9, dynamic baz = #C9, core::int three = #C4, core::num five = #C6}) → self::C21
+    : super self::S2::•(one: one, three: three, five: five)
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::List<core::String> six = #C8, dynamic bar = #C9, dynamic baz = #C9, core::double four = #C5, core::bool two = #C3}) → self::C22
+    : super self::S2::•(six: six, four: four, two: two)
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = #C4, dynamic foo = #C9, core::String one = #C2, core::double four = #C5, dynamic bar = #C9, core::bool two = #C3, dynamic baz = #C9}) → self::C23
+    : super self::S2::•(three: three, one: one, four: four, two: two)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 42
+  #C2 = "1"
+  #C3 = false
+  #C4 = 3
+  #C5 = 4.0
+  #C6 = 3.14
+  #C7 = "six"
+  #C8 = <core::String*>[#C7]
+  #C9 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.outline.expect
new file mode 100644
index 0000000..00d1860
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.outline.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = 42]) → self::S1
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = 42]) → self::C1
+    : self::C1::i1 = i1
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = "1", core::bool two = false, core::int three = 3, core::double four = 4.0, core::num five = 3.14, core::List<core::String> six = const <core::String>["six"]}) → self::S2
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo, core::String one = "1", dynamic bar, dynamic baz, core::int three = 3, core::num five = 3.14}) → self::C21
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo, core::List<core::String> six = const <core::String>["six"], dynamic bar, dynamic baz, core::double four = 4.0, core::bool two = false}) → self::C22
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = 3, dynamic foo, core::String one = "1", core::double four = 4.0, dynamic bar, core::bool two = false, dynamic baz}) → self::C23
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue48142.dart:19:43 -> ListConstant(const <String*>["six"])
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue48142.dart:28:27 -> ListConstant(const <String*>["six"])
+Extra constant evaluation: evaluated: 3, effectively constant: 2
diff --git a/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.transformed.expect
new file mode 100644
index 0000000..e86004a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48142.dart.weak.transformed.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S1 extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •(core::int s1, [core::int s2 = #C1]) → self::S1
+    : self::S1::s1 = s1, self::S1::s2 = s2, super core::Object::•()
+    ;
+}
+class C1 extends self::S1 {
+  field core::int i1;
+  field core::int i2;
+  constructor •(core::int i1, core::int s1, core::int x, [core::int s2 = #C1]) → self::C1
+    : self::C1::i1 = i1, self::C1::i2 = x, super self::S1::•(s1, s2)
+    ;
+}
+class S2 extends core::Object {
+  constructor •({core::String one = #C2, core::bool two = #C3, core::int three = #C4, core::double four = #C5, core::num five = #C6, core::List<core::String> six = #C8}) → self::S2
+    : super core::Object::•()
+    ;
+}
+class C21 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::String one = #C2, dynamic bar = #C9, dynamic baz = #C9, core::int three = #C4, core::num five = #C6}) → self::C21
+    : super self::S2::•(one: one, three: three, five: five)
+    ;
+}
+class C22 extends self::S2 {
+  constructor •({dynamic foo = #C9, core::List<core::String> six = #C8, dynamic bar = #C9, dynamic baz = #C9, core::double four = #C5, core::bool two = #C3}) → self::C22
+    : super self::S2::•(six: six, four: four, two: two)
+    ;
+}
+class C23 extends self::S2 {
+  constructor •({core::int three = #C4, dynamic foo = #C9, core::String one = #C2, core::double four = #C5, dynamic bar = #C9, core::bool two = #C3, dynamic baz = #C9}) → self::C23
+    : super self::S2::•(three: three, one: one, four: four, two: two)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 42
+  #C2 = "1"
+  #C3 = false
+  #C4 = 3
+  #C5 = 4.0
+  #C6 = 3.14
+  #C7 = "six"
+  #C8 = <core::String*>[#C7]
+  #C9 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.strong.expect b/pkg/front_end/testcases/super_parameters/simple.dart.strong.expect
index 2738e5e..1b2cab9 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.strong.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.strong.expect
@@ -9,7 +9,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     : super self::A::•(foo)
     ;
 }
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/simple.dart.strong.transformed.expect
index 2738e5e..1b2cab9 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     : super self::A::•(foo)
     ;
 }
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.weak.expect b/pkg/front_end/testcases/super_parameters/simple.dart.weak.expect
index 2738e5e..1b2cab9 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.weak.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.weak.expect
@@ -9,7 +9,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     : super self::A::•(foo)
     ;
 }
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/simple.dart.weak.modular.expect
index 2738e5e..1b2cab9 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.weak.modular.expect
@@ -9,7 +9,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     : super self::A::•(foo)
     ;
 }
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/simple.dart.weak.outline.expect
index 997a20e..61584c5 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.weak.outline.expect
@@ -8,7 +8,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/super_parameters/simple.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/simple.dart.weak.transformed.expect
index 2738e5e..1b2cab9 100644
--- a/pkg/front_end/testcases/super_parameters/simple.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
     ;
 }
 class B extends self::A {
-  constructor •(dynamic foo) → self::B
+  constructor •(core::int foo) → self::B
     : super self::A::•(foo)
     ;
 }
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart b/pkg/front_end/testcases/super_parameters/simple_inference.dart
new file mode 100644
index 0000000..41034252
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 A1 {
+  final int foo;
+  A1(this.foo);
+  A1.named(this.foo);
+  A1.named2(int foo) : foo = foo;
+  A1.named3({required int foo}) : foo = foo;
+}
+
+class B1 extends A1 {
+  B1(super.foo);
+  B1.named(super.foo) : super.named();
+  B1.named2(super.foo) : super.named2();
+  B1.named3({required super.foo}) : super.named3();
+}
+
+class A2 {
+  final int foo;
+  final String bar;
+  A2({required int this.foo, required String this.bar});
+}
+
+class B2 extends A2 {
+  B2({required super.bar, required super.foo});
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.expect
new file mode 100644
index 0000000..2422e10
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named2(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named3({required core::int foo = #C1}) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+  constructor named(core::int foo) → self::B1
+    : super self::A1::named(foo)
+    ;
+  constructor named2(core::int foo) → self::B1
+    : super self::A1::named2(foo)
+    ;
+  constructor named3({required dynamic foo = #C1}) → self::B1
+    : super self::A1::named3(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo = #C1, required core::String bar = #C1}) → self::A2
+    : self::A2::foo = foo, self::A2::bar = bar, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar = #C1, required core::int foo = #C1}) → self::B2
+    : super self::A2::•(bar: bar, foo: foo)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.transformed.expect
new file mode 100644
index 0000000..2422e10
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.strong.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named2(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named3({required core::int foo = #C1}) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+  constructor named(core::int foo) → self::B1
+    : super self::A1::named(foo)
+    ;
+  constructor named2(core::int foo) → self::B1
+    : super self::A1::named2(foo)
+    ;
+  constructor named3({required dynamic foo = #C1}) → self::B1
+    : super self::A1::named3(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo = #C1, required core::String bar = #C1}) → self::A2
+    : self::A2::foo = foo, self::A2::bar = bar, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar = #C1, required core::int foo = #C1}) → self::B2
+    : super self::A2::•(bar: bar, foo: foo)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.textual_outline.expect
new file mode 100644
index 0000000..a194020
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class A1 {
+  final int foo;
+  A1(this.foo);
+  A1.named(this.foo);
+  A1.named2(int foo) : foo = foo;
+  A1.named3({required int foo}) : foo = foo;
+}
+class B1 extends A1 {
+  B1(super.foo);
+  B1.named(super.foo) : super.named();
+  B1.named2(super.foo) : super.named2();
+  B1.named3({required super.foo}) : super.named3();
+}
+class A2 {
+  final int foo;
+  final String bar;
+  A2({required int this.foo, required String this.bar});
+}
+class B2 extends A2 {
+  B2({required super.bar, required super.foo});
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.expect
new file mode 100644
index 0000000..2422e10
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named2(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named3({required core::int foo = #C1}) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+  constructor named(core::int foo) → self::B1
+    : super self::A1::named(foo)
+    ;
+  constructor named2(core::int foo) → self::B1
+    : super self::A1::named2(foo)
+    ;
+  constructor named3({required dynamic foo = #C1}) → self::B1
+    : super self::A1::named3(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo = #C1, required core::String bar = #C1}) → self::A2
+    : self::A2::foo = foo, self::A2::bar = bar, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar = #C1, required core::int foo = #C1}) → self::B2
+    : super self::A2::•(bar: bar, foo: foo)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.modular.expect
new file mode 100644
index 0000000..2422e10
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.modular.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named2(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named3({required core::int foo = #C1}) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+  constructor named(core::int foo) → self::B1
+    : super self::A1::named(foo)
+    ;
+  constructor named2(core::int foo) → self::B1
+    : super self::A1::named2(foo)
+    ;
+  constructor named3({required dynamic foo = #C1}) → self::B1
+    : super self::A1::named3(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo = #C1, required core::String bar = #C1}) → self::A2
+    : self::A2::foo = foo, self::A2::bar = bar, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar = #C1, required core::int foo = #C1}) → self::B2
+    : super self::A2::•(bar: bar, foo: foo)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.outline.expect
new file mode 100644
index 0000000..c7b816c
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    ;
+  constructor named(core::int foo) → self::A1
+    ;
+  constructor named2(core::int foo) → self::A1
+    ;
+  constructor named3({required core::int foo}) → self::A1
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    ;
+  constructor named(core::int foo) → self::B1
+    ;
+  constructor named2(core::int foo) → self::B1
+    ;
+  constructor named3({required dynamic foo}) → self::B1
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo, required core::String bar}) → self::A2
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar, required core::int foo}) → self::B2
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.transformed.expect
new file mode 100644
index 0000000..2422e10
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/simple_inference.dart.weak.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int foo;
+  constructor •(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named2(core::int foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+  constructor named3({required core::int foo = #C1}) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
+    ;
+  constructor named(core::int foo) → self::B1
+    : super self::A1::named(foo)
+    ;
+  constructor named2(core::int foo) → self::B1
+    : super self::A1::named2(foo)
+    ;
+  constructor named3({required dynamic foo = #C1}) → self::B1
+    : super self::A1::named3(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int foo;
+  final field core::String bar;
+  constructor •({required core::int foo = #C1, required core::String bar = #C1}) → self::A2
+    : self::A2::foo = foo, self::A2::bar = bar, super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor •({required core::String bar = #C1, required core::int foo = #C1}) → self::B2
+    : super self::A2::•(bar: bar, foo: foo)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.expect
index 01051cd..ad7ea47 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.expect
@@ -24,17 +24,17 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::B1
-    : super self::A1::•(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •({required core::int foo = #C1}) → self::B1
+    : super self::A1::•(foo: foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::C1
+  constructor •({required core::int foo = #C1}) → self::C1
     : super self::A1::•(foo: invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:15:22: Error: Duplicated named argument 'foo'.
   C1({required super.foo}) : super(foo: foo); // Error.
                      ^^^" in block {
       foo;
-    } =>foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    } =>foo)
     ;
 }
 class A2 extends core::Object {
@@ -52,13 +52,13 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo = #C1}) → self::C2
+  constructor •({required core::int foo = #C1}) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:29:35: Error: Required named parameter 'bar' must be provided.
   C2({required super.foo}) : super(); // Error.
                                   ^"
     ;
-  constructor other({required dynamic foo = #C1}) → self::C2
-    : super self::A2::•(bar: "bar", foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor other({required core::int foo = #C1}) → self::C2
+    : super self::A2::•(bar: "bar", foo: foo)
     ;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.transformed.expect
index 74cac10..ad7ea47 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.strong.transformed.expect
@@ -24,12 +24,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::B1
-    : super self::A1::•(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •({required core::int foo = #C1}) → self::B1
+    : super self::A1::•(foo: foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::C1
+  constructor •({required core::int foo = #C1}) → self::C1
     : super self::A1::•(foo: invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:15:22: Error: Duplicated named argument 'foo'.
   C1({required super.foo}) : super(foo: foo); // Error.
                      ^^^" in block {
@@ -52,13 +52,13 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo = #C1}) → self::C2
+  constructor •({required core::int foo = #C1}) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:29:35: Error: Required named parameter 'bar' must be provided.
   C2({required super.foo}) : super(); // Error.
                                   ^"
     ;
-  constructor other({required dynamic foo = #C1}) → self::C2
-    : super self::A2::•(bar: "bar", foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor other({required core::int foo = #C1}) → self::C2
+    : super self::A2::•(bar: "bar", foo: foo)
     ;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.expect
index 01051cd..ad7ea47 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.expect
@@ -24,17 +24,17 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::B1
-    : super self::A1::•(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •({required core::int foo = #C1}) → self::B1
+    : super self::A1::•(foo: foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::C1
+  constructor •({required core::int foo = #C1}) → self::C1
     : super self::A1::•(foo: invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:15:22: Error: Duplicated named argument 'foo'.
   C1({required super.foo}) : super(foo: foo); // Error.
                      ^^^" in block {
       foo;
-    } =>foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    } =>foo)
     ;
 }
 class A2 extends core::Object {
@@ -52,13 +52,13 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo = #C1}) → self::C2
+  constructor •({required core::int foo = #C1}) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:29:35: Error: Required named parameter 'bar' must be provided.
   C2({required super.foo}) : super(); // Error.
                                   ^"
     ;
-  constructor other({required dynamic foo = #C1}) → self::C2
-    : super self::A2::•(bar: "bar", foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor other({required core::int foo = #C1}) → self::C2
+    : super self::A2::•(bar: "bar", foo: foo)
     ;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.modular.expect
index 01051cd..ad7ea47 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.modular.expect
@@ -24,17 +24,17 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::B1
-    : super self::A1::•(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •({required core::int foo = #C1}) → self::B1
+    : super self::A1::•(foo: foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::C1
+  constructor •({required core::int foo = #C1}) → self::C1
     : super self::A1::•(foo: invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:15:22: Error: Duplicated named argument 'foo'.
   C1({required super.foo}) : super(foo: foo); // Error.
                      ^^^" in block {
       foo;
-    } =>foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+    } =>foo)
     ;
 }
 class A2 extends core::Object {
@@ -52,13 +52,13 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo = #C1}) → self::C2
+  constructor •({required core::int foo = #C1}) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:29:35: Error: Required named parameter 'bar' must be provided.
   C2({required super.foo}) : super(); // Error.
                                   ^"
     ;
-  constructor other({required dynamic foo = #C1}) → self::C2
-    : super self::A2::•(bar: "bar", foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor other({required core::int foo = #C1}) → self::C2
+    : super self::A2::•(bar: "bar", foo: foo)
     ;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.outline.expect
index f3d5bdd..99e1ef3 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.outline.expect
@@ -8,11 +8,11 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo}) → self::B1
+  constructor •({required core::int foo}) → self::B1
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo}) → self::C1
+  constructor •({required core::int foo}) → self::C1
     ;
 }
 class A2 extends core::Object {
@@ -26,9 +26,9 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo}) → self::C2
+  constructor •({required core::int foo}) → self::C2
     ;
-  constructor other({required dynamic foo}) → self::C2
+  constructor other({required core::int foo}) → self::C2
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.transformed.expect
index 74cac10..ad7ea47 100644
--- a/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart.weak.transformed.expect
@@ -24,12 +24,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::B1
-    : super self::A1::•(foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •({required core::int foo = #C1}) → self::B1
+    : super self::A1::•(foo: foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •({required dynamic foo = #C1}) → self::C1
+  constructor •({required core::int foo = #C1}) → self::C1
     : super self::A1::•(foo: invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:15:22: Error: Duplicated named argument 'foo'.
   C1({required super.foo}) : super(foo: foo); // Error.
                      ^^^" in block {
@@ -52,13 +52,13 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •({required dynamic foo = #C1}) → self::C2
+  constructor •({required core::int foo = #C1}) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_named_super_parameters.dart:29:35: Error: Required named parameter 'bar' must be provided.
   C2({required super.foo}) : super(); // Error.
                                   ^"
     ;
-  constructor other({required dynamic foo = #C1}) → self::C2
-    : super self::A2::•(bar: "bar", foo: foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor other({required core::int foo = #C1}) → self::C2
+    : super self::A2::•(bar: "bar", foo: foo)
     ;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.expect
index 228f432..4d064a8 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.expect
@@ -28,12 +28,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
-    : super self::A1::•(foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     : super self::A1::•(42)
     ;
 }
@@ -53,7 +53,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart:29:24: Error: Too few positional arguments: 2 required, 1 given.
   C2(super.foo) : super(); // Error.
                        ^"
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.transformed.expect
index 228f432..4d064a8 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.strong.transformed.expect
@@ -28,12 +28,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
-    : super self::A1::•(foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     : super self::A1::•(42)
     ;
 }
@@ -53,7 +53,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart:29:24: Error: Too few positional arguments: 2 required, 1 given.
   C2(super.foo) : super(); // Error.
                        ^"
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.expect
index 228f432..4d064a8 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.expect
@@ -28,12 +28,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
-    : super self::A1::•(foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     : super self::A1::•(42)
     ;
 }
@@ -53,7 +53,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart:29:24: Error: Too few positional arguments: 2 required, 1 given.
   C2(super.foo) : super(); // Error.
                        ^"
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.modular.expect
index 228f432..4d064a8 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.modular.expect
@@ -28,12 +28,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
-    : super self::A1::•(foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     : super self::A1::•(42)
     ;
 }
@@ -53,7 +53,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart:29:24: Error: Too few positional arguments: 2 required, 1 given.
   C2(super.foo) : super(); // Error.
                        ^"
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.outline.expect
index 184b3f4..383a149 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.outline.expect
@@ -8,11 +8,11 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
+  constructor •(core::int foo) → self::B1
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     ;
 }
 class A2 extends core::Object {
@@ -26,7 +26,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.transformed.expect
index 228f432..4d064a8 100644
--- a/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart.weak.transformed.expect
@@ -28,12 +28,12 @@
     ;
 }
 class B1 extends self::A1 {
-  constructor •(dynamic foo) → self::B1
-    : super self::A1::•(foo as{TypeError,ForDynamic,ForNonNullableByDefault} core::int)
+  constructor •(core::int foo) → self::B1
+    : super self::A1::•(foo)
     ;
 }
 class C1 extends self::A1 {
-  constructor •(dynamic foo) → self::C1
+  constructor •(core::int foo) → self::C1
     : super self::A1::•(42)
     ;
 }
@@ -53,7 +53,7 @@
     ;
 }
 class C2 extends self::A2 {
-  constructor •(dynamic foo) → self::C2
+  constructor •(core::int foo) → self::C2
     : final dynamic #t2 = invalid-expression "pkg/front_end/testcases/super_parameters/simple_positional_super_parameters.dart:29:24: Error: Too few positional arguments: 2 required, 1 given.
   C2(super.foo) : super(); // Error.
                        ^"
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
new file mode 100644
index 0000000..f5b1bd9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..7acd1b7
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..aae570e
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = 1, core::int s2 = 2]) → self::S
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = 1, core::int x = 0, dynamic s2 = 2]) → self::C
+    : self::C::c1 = c1
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart
new file mode 100644
index 0000000..71e4e70
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// 1. The base case.
+
+class A1 {
+  final int a;
+  A1(this.a);
+}
+
+class B1 {}
+
+// C1 has a synthesized constructor that takes a positional parameter.
+class C1 = A1 with B1;
+
+class D1 extends C1 {
+  D1(super.a);
+}
+
+// 2. The case of named parameters.
+
+class A2 {
+  final int a;
+  A2({this.a = 0});
+}
+
+class B2 {}
+
+// C2 has a synthesized constructor that takes a named parameter.
+class C2 = A2 with B2;
+
+class D2 extends C2 {
+  D2({super.a});
+}
+
+// 3. The case of optional positional parameters.
+
+class A3 {
+  final int a;
+  A3([this.a = 0]);
+}
+
+class B3 {}
+
+// C3 has a synthesized constructor that takes an optional positional parameter.
+class C3 = A3 with B3;
+
+class D3 extends C3 {
+  D3([super.a]);
+}
+
+// 4. The case of the inverted order of classes.
+
+class D4 extends C4 {
+  D4([super.foo]);
+}
+
+// C4 has a synthesized constructor that takes an optional parameter.
+class C4 = A4 with B4;
+
+class B4 {}
+
+class A4 extends AA4 {
+  A4([super.foo]);
+}
+
+class AA4 {
+  final int foo;
+  AA4([this.foo = 42]);
+}
+
+// 5. The case of a longer named mixin chain.
+
+class D5 extends C5c {
+  D5([super.foo]);
+}
+
+// C5a, C5b, C5c have synthesized constructors that take an optional parameter.
+class C5c = C5b with B5;
+class C5b = C5a with B5;
+class C5a = A5 with B5;
+
+class B5 {}
+
+class A5 extends AA5 {
+  A5([super.foo]);
+}
+
+class AA5 {
+  final int foo;
+  AA5([this.foo = 42]);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect
new file mode 100644
index 0000000..0a867e6
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect
@@ -0,0 +1,135 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    : self::A1::a = a, super core::Object::•()
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    : super core::Object::•()
+    ;
+}
+class C1 = self::A1 with self::B1 {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    : super self::C1::•(a)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = #C1}) → self::A2
+    : self::A2::a = a, super core::Object::•()
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+}
+class C2 = self::A2 with self::B2 {
+  synthetic constructor •({core::int a = #C1}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = #C1}) → self::D2
+    : super self::C2::•(a: a)
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = #C1]) → self::A3
+    : self::A3::a = a, super core::Object::•()
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    : super core::Object::•()
+    ;
+}
+class C3 = self::A3 with self::B3 {
+  synthetic constructor •([core::int a = #C1]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = #C1]) → self::D3
+    : super self::C3::•(a)
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = #C2]) → self::D4
+    : super self::C4::•(foo)
+    ;
+}
+class C4 = self::A4 with self::B4 {
+  synthetic constructor •([core::int foo = #C2]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    : super core::Object::•()
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = #C2]) → self::A4
+    : super self::AA4::•(foo)
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA4
+    : self::AA4::foo = foo, super core::Object::•()
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = #C2]) → self::D5
+    : super self::C5c::•(foo)
+    ;
+}
+class C5c = self::C5b with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b = self::C5a with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a = self::A5 with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    : super core::Object::•()
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = #C2]) → self::A5
+    : super self::AA5::•(foo)
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA5
+    : self::AA5::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect
new file mode 100644
index 0000000..cf81c26
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect
@@ -0,0 +1,135 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    : self::A1::a = a, super core::Object::•()
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    : super core::Object::•()
+    ;
+}
+class C1 extends self::A1 implements self::B1 /*isEliminatedMixin*/  {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    : super self::C1::•(a)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = #C1}) → self::A2
+    : self::A2::a = a, super core::Object::•()
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+}
+class C2 extends self::A2 implements self::B2 /*isEliminatedMixin*/  {
+  synthetic constructor •({core::int a = #C1}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = #C1}) → self::D2
+    : super self::C2::•(a: a)
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = #C1]) → self::A3
+    : self::A3::a = a, super core::Object::•()
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    : super core::Object::•()
+    ;
+}
+class C3 extends self::A3 implements self::B3 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int a = #C1]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = #C1]) → self::D3
+    : super self::C3::•(a)
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = #C2]) → self::D4
+    : super self::C4::•(foo)
+    ;
+}
+class C4 extends self::A4 implements self::B4 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    : super core::Object::•()
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = #C2]) → self::A4
+    : super self::AA4::•(foo)
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA4
+    : self::AA4::foo = foo, super core::Object::•()
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = #C2]) → self::D5
+    : super self::C5c::•(foo)
+    ;
+}
+class C5c extends self::C5b implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b extends self::C5a implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a extends self::A5 implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    : super core::Object::•()
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = #C2]) → self::A5
+    : super self::AA5::•(foo)
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA5
+    : self::AA5::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.textual_outline.expect
new file mode 100644
index 0000000..ed0e4f7
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.textual_outline.expect
@@ -0,0 +1,54 @@
+class A1 {
+  final int a;
+  A1(this.a);
+}
+class B1 {}
+class C1 = A1 with B1;
+class D1 extends C1 {
+  D1(super.a);
+}
+class A2 {
+  final int a;
+  A2({this.a = 0});
+}
+class B2 {}
+class C2 = A2 with B2;
+class D2 extends C2 {
+  D2({super.a});
+}
+class A3 {
+  final int a;
+  A3([this.a = 0]);
+}
+class B3 {}
+class C3 = A3 with B3;
+class D3 extends C3 {
+  D3([super.a]);
+}
+class D4 extends C4 {
+  D4([super.foo]);
+}
+class C4 = A4 with B4;
+class B4 {}
+class A4 extends AA4 {
+  A4([super.foo]);
+}
+class AA4 {
+  final int foo;
+  AA4([this.foo = 42]);
+}
+class D5 extends C5c {
+  D5([super.foo]);
+}
+class C5c = C5b with B5;
+class C5b = C5a with B5;
+class C5a = A5 with B5;
+class B5 {}
+class A5 extends AA5 {
+  A5([super.foo]);
+}
+class AA5 {
+  final int foo;
+  AA5([this.foo = 42]);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect
new file mode 100644
index 0000000..0a867e6
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect
@@ -0,0 +1,135 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    : self::A1::a = a, super core::Object::•()
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    : super core::Object::•()
+    ;
+}
+class C1 = self::A1 with self::B1 {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    : super self::C1::•(a)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = #C1}) → self::A2
+    : self::A2::a = a, super core::Object::•()
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+}
+class C2 = self::A2 with self::B2 {
+  synthetic constructor •({core::int a = #C1}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = #C1}) → self::D2
+    : super self::C2::•(a: a)
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = #C1]) → self::A3
+    : self::A3::a = a, super core::Object::•()
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    : super core::Object::•()
+    ;
+}
+class C3 = self::A3 with self::B3 {
+  synthetic constructor •([core::int a = #C1]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = #C1]) → self::D3
+    : super self::C3::•(a)
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = #C2]) → self::D4
+    : super self::C4::•(foo)
+    ;
+}
+class C4 = self::A4 with self::B4 {
+  synthetic constructor •([core::int foo = #C2]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    : super core::Object::•()
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = #C2]) → self::A4
+    : super self::AA4::•(foo)
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA4
+    : self::AA4::foo = foo, super core::Object::•()
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = #C2]) → self::D5
+    : super self::C5c::•(foo)
+    ;
+}
+class C5c = self::C5b with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b = self::C5a with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a = self::A5 with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    : super core::Object::•()
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = #C2]) → self::A5
+    : super self::AA5::•(foo)
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA5
+    : self::AA5::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect
new file mode 100644
index 0000000..0a867e6
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect
@@ -0,0 +1,135 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    : self::A1::a = a, super core::Object::•()
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    : super core::Object::•()
+    ;
+}
+class C1 = self::A1 with self::B1 {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    : super self::C1::•(a)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = #C1}) → self::A2
+    : self::A2::a = a, super core::Object::•()
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+}
+class C2 = self::A2 with self::B2 {
+  synthetic constructor •({core::int a = #C1}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = #C1}) → self::D2
+    : super self::C2::•(a: a)
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = #C1]) → self::A3
+    : self::A3::a = a, super core::Object::•()
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    : super core::Object::•()
+    ;
+}
+class C3 = self::A3 with self::B3 {
+  synthetic constructor •([core::int a = #C1]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = #C1]) → self::D3
+    : super self::C3::•(a)
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = #C2]) → self::D4
+    : super self::C4::•(foo)
+    ;
+}
+class C4 = self::A4 with self::B4 {
+  synthetic constructor •([core::int foo = #C2]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    : super core::Object::•()
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = #C2]) → self::A4
+    : super self::AA4::•(foo)
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA4
+    : self::AA4::foo = foo, super core::Object::•()
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = #C2]) → self::D5
+    : super self::C5c::•(foo)
+    ;
+}
+class C5c = self::C5b with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b = self::C5a with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a = self::A5 with self::B5 {
+  synthetic constructor •([core::int foo = #C2]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    : super core::Object::•()
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = #C2]) → self::A5
+    : super self::AA5::•(foo)
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA5
+    : self::AA5::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.outline.expect
new file mode 100644
index 0000000..ee7f775
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.outline.expect
@@ -0,0 +1,114 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    ;
+}
+class C1 = self::A1 with self::B1 {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = 0}) → self::A2
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    ;
+}
+class C2 = self::A2 with self::B2 {
+  synthetic constructor •({core::int a = 0}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = 0}) → self::D2
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = 0]) → self::A3
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    ;
+}
+class C3 = self::A3 with self::B3 {
+  synthetic constructor •([core::int a = 0]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = 0]) → self::D3
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = 42]) → self::D4
+    ;
+}
+class C4 = self::A4 with self::B4 {
+  synthetic constructor •([core::int foo = 42]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = 42]) → self::A4
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = 42]) → self::AA4
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = 42]) → self::D5
+    ;
+}
+class C5c = self::C5b with self::B5 {
+  synthetic constructor •([core::int foo = 42]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b = self::C5a with self::B5 {
+  synthetic constructor •([core::int foo = 42]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a = self::A5 with self::B5 {
+  synthetic constructor •([core::int foo = 42]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = 42]) → self::A5
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = 42]) → self::AA5
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect
new file mode 100644
index 0000000..cf81c26
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect
@@ -0,0 +1,135 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A1 extends core::Object {
+  final field core::int a;
+  constructor •(core::int a) → self::A1
+    : self::A1::a = a, super core::Object::•()
+    ;
+}
+class B1 extends core::Object {
+  synthetic constructor •() → self::B1
+    : super core::Object::•()
+    ;
+}
+class C1 extends self::A1 implements self::B1 /*isEliminatedMixin*/  {
+  synthetic constructor •(core::int a) → self::C1
+    : super self::A1::•(a)
+    ;
+}
+class D1 extends self::C1 {
+  constructor •(core::int a) → self::D1
+    : super self::C1::•(a)
+    ;
+}
+class A2 extends core::Object {
+  final field core::int a;
+  constructor •({core::int a = #C1}) → self::A2
+    : self::A2::a = a, super core::Object::•()
+    ;
+}
+class B2 extends core::Object {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+}
+class C2 extends self::A2 implements self::B2 /*isEliminatedMixin*/  {
+  synthetic constructor •({core::int a = #C1}) → self::C2
+    : super self::A2::•(a: a)
+    ;
+}
+class D2 extends self::C2 {
+  constructor •({core::int a = #C1}) → self::D2
+    : super self::C2::•(a: a)
+    ;
+}
+class A3 extends core::Object {
+  final field core::int a;
+  constructor •([core::int a = #C1]) → self::A3
+    : self::A3::a = a, super core::Object::•()
+    ;
+}
+class B3 extends core::Object {
+  synthetic constructor •() → self::B3
+    : super core::Object::•()
+    ;
+}
+class C3 extends self::A3 implements self::B3 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int a = #C1]) → self::C3
+    : super self::A3::•(a)
+    ;
+}
+class D3 extends self::C3 {
+  constructor •([core::int a = #C1]) → self::D3
+    : super self::C3::•(a)
+    ;
+}
+class D4 extends self::C4 {
+  constructor •([core::int foo = #C2]) → self::D4
+    : super self::C4::•(foo)
+    ;
+}
+class C4 extends self::A4 implements self::B4 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C4
+    : super self::A4::•(foo)
+    ;
+}
+class B4 extends core::Object {
+  synthetic constructor •() → self::B4
+    : super core::Object::•()
+    ;
+}
+class A4 extends self::AA4 {
+  constructor •([core::int foo = #C2]) → self::A4
+    : super self::AA4::•(foo)
+    ;
+}
+class AA4 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA4
+    : self::AA4::foo = foo, super core::Object::•()
+    ;
+}
+class D5 extends self::C5c {
+  constructor •([core::int foo = #C2]) → self::D5
+    : super self::C5c::•(foo)
+    ;
+}
+class C5c extends self::C5b implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5c
+    : super self::C5b::•(foo)
+    ;
+}
+class C5b extends self::C5a implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5b
+    : super self::C5a::•(foo)
+    ;
+}
+class C5a extends self::A5 implements self::B5 /*isEliminatedMixin*/  {
+  synthetic constructor •([core::int foo = #C2]) → self::C5a
+    : super self::A5::•(foo)
+    ;
+}
+class B5 extends core::Object {
+  synthetic constructor •() → self::B5
+    : super core::Object::•()
+    ;
+}
+class A5 extends self::AA5 {
+  constructor •([core::int foo = #C2]) → self::A5
+    : super self::AA5::•(foo)
+    ;
+}
+class AA5 extends core::Object {
+  final field core::int foo;
+  constructor •([core::int foo = #C2]) → self::AA5
+    : self::AA5::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 0
+  #C2 = 42
+}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart
new file mode 100644
index 0000000..efa62e9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// 1. The base case.
+
+class A1 {
+  final String foo;
+  A1(this.foo);
+}
+
+typedef TA1 = A1;
+
+typedef TTA1 = TA1;
+
+typedef TTTA1 = TTA1;
+
+typedef TTTTA1 = TTTA1;
+
+class D1 extends TTTTA1 {
+  D1(super.foo);
+}
+
+// 2. The case of named parameters.
+
+class A2 {
+  final String foo;
+  A2({this.foo = "bar"});
+}
+
+typedef TA2 = A2;
+
+typedef TTA2 = TA2;
+
+typedef TTTA2 = TTA2;
+
+typedef TTTTA2 = TTTA2;
+
+class D2 extends TTTTA2 {
+  D2({super.foo});
+}
+
+// 3. The case of optional positional parameters.
+
+class A3 {
+  final String foo;
+  A3([this.foo = "bar"]);
+}
+
+typedef TA3 = A3;
+
+typedef TTA3 = TA3;
+
+typedef TTTA3 = TTA3;
+
+typedef TTTTA3 = TTTA3;
+
+class D3 extends TTTTA3 {
+  D3([super.foo]);
+}
+
+// 4. The case of the inverted order of declarations.
+
+class D4 extends TTTTA4 {
+  D4([super.foo]);
+}
+
+typedef TTTTA4 = TTTA4;
+
+typedef TTTA4 = TTA4;
+
+typedef TTA4 = TA4;
+
+typedef TA4 = A4;
+
+class A4 {
+  final String foo;
+  A4([this.foo = "bar"]);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.expect
new file mode 100644
index 0000000..c64854a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = #C1}) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = #C1}) → self::D2
+    : super self::A2::•(foo: foo)
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = #C1]) → self::D3
+    : super self::A3::•(foo)
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = #C1]) → self::D4
+    : super self::A4::•(foo)
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A4
+    : self::A4::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "bar"
+}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.transformed.expect
new file mode 100644
index 0000000..c64854a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = #C1}) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = #C1}) → self::D2
+    : super self::A2::•(foo: foo)
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = #C1]) → self::D3
+    : super self::A3::•(foo)
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = #C1]) → self::D4
+    : super self::A4::•(foo)
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A4
+    : self::A4::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "bar"
+}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.textual_outline.expect
new file mode 100644
index 0000000..1e4deb1
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.textual_outline.expect
@@ -0,0 +1,45 @@
+class A1 {
+  final String foo;
+  A1(this.foo);
+}
+typedef TA1 = A1;
+typedef TTA1 = TA1;
+typedef TTTA1 = TTA1;
+typedef TTTTA1 = TTTA1;
+class D1 extends TTTTA1 {
+  D1(super.foo);
+}
+class A2 {
+  final String foo;
+  A2({this.foo = "bar"});
+}
+typedef TA2 = A2;
+typedef TTA2 = TA2;
+typedef TTTA2 = TTA2;
+typedef TTTTA2 = TTTA2;
+class D2 extends TTTTA2 {
+  D2({super.foo});
+}
+class A3 {
+  final String foo;
+  A3([this.foo = "bar"]);
+}
+typedef TA3 = A3;
+typedef TTA3 = TA3;
+typedef TTTA3 = TTA3;
+typedef TTTTA3 = TTTA3;
+class D3 extends TTTTA3 {
+  D3([super.foo]);
+}
+class D4 extends TTTTA4 {
+  D4([super.foo]);
+}
+typedef TTTTA4 = TTTA4;
+typedef TTTA4 = TTA4;
+typedef TTA4 = TA4;
+typedef TA4 = A4;
+class A4 {
+  final String foo;
+  A4([this.foo = "bar"]);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.expect
new file mode 100644
index 0000000..c64854a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = #C1}) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = #C1}) → self::D2
+    : super self::A2::•(foo: foo)
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = #C1]) → self::D3
+    : super self::A3::•(foo)
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = #C1]) → self::D4
+    : super self::A4::•(foo)
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A4
+    : self::A4::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "bar"
+}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.modular.expect
new file mode 100644
index 0000000..c64854a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.modular.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = #C1}) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = #C1}) → self::D2
+    : super self::A2::•(foo: foo)
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = #C1]) → self::D3
+    : super self::A3::•(foo)
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = #C1]) → self::D4
+    : super self::A4::•(foo)
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A4
+    : self::A4::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "bar"
+}
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.outline.expect
new file mode 100644
index 0000000..f4d87e2
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = "bar"}) → self::A2
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = "bar"}) → self::D2
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = "bar"]) → self::A3
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = "bar"]) → self::D3
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = "bar"]) → self::D4
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = "bar"]) → self::A4
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.transformed.expect
new file mode 100644
index 0000000..c64854a
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/type_alias_in_supertype.dart.weak.transformed.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef TA1 = self::A1;
+typedef TTA1 = self::A1;
+typedef TTTA1 = self::A1;
+typedef TTTTA1 = self::A1;
+typedef TA2 = self::A2;
+typedef TTA2 = self::A2;
+typedef TTTA2 = self::A2;
+typedef TTTTA2 = self::A2;
+typedef TA3 = self::A3;
+typedef TTA3 = self::A3;
+typedef TTTA3 = self::A3;
+typedef TTTTA3 = self::A3;
+typedef TTTTA4 = self::A4;
+typedef TTTA4 = self::A4;
+typedef TTA4 = self::A4;
+typedef TA4 = self::A4;
+class A1 extends core::Object {
+  final field core::String foo;
+  constructor •(core::String foo) → self::A1
+    : self::A1::foo = foo, super core::Object::•()
+    ;
+}
+class D1 extends self::A1 {
+  constructor •(core::String foo) → self::D1
+    : super self::A1::•(foo)
+    ;
+}
+class A2 extends core::Object {
+  final field core::String foo;
+  constructor •({core::String foo = #C1}) → self::A2
+    : self::A2::foo = foo, super core::Object::•()
+    ;
+}
+class D2 extends self::A2 {
+  constructor •({core::String foo = #C1}) → self::D2
+    : super self::A2::•(foo: foo)
+    ;
+}
+class A3 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A3
+    : self::A3::foo = foo, super core::Object::•()
+    ;
+}
+class D3 extends self::A3 {
+  constructor •([core::String foo = #C1]) → self::D3
+    : super self::A3::•(foo)
+    ;
+}
+class D4 extends self::A4 {
+  constructor •([core::String foo = #C1]) → self::D4
+    : super self::A4::•(foo)
+    ;
+}
+class A4 extends core::Object {
+  final field core::String foo;
+  constructor •([core::String foo = #C1]) → self::A4
+    : self::A4::foo = foo, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "bar"
+}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 8d551bb..5a838fa 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -8,6 +8,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+enhanced_enums/simple_mixins: RuntimeError
 extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/call_not_get: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
@@ -33,7 +34,6 @@
 general/bug31124: RuntimeError
 general/call: RuntimeError
 general/cascade: RuntimeError
-general/conditional_import: RuntimeError # Issue 47814
 general/constructor_initializer_invalid: RuntimeError
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
@@ -90,6 +90,7 @@
 general/issue41210b/issue41210.no_link: TypeCheckError
 general/issue41210b/issue41210: TypeCheckError
 general/issue44733: TypeCheckError
+general/issue47994b: RuntimeError # Assertions are not enabled
 general/issue_46886: RuntimeError
 general/micro: RuntimeError
 general/mixin_application_override: TypeCheckError
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 5ebd7e2..ca04916 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -29,7 +29,19 @@
 dart2js/late_fields: FormatterCrash
 dart2js/late_statics: FormatterCrash
 enhanced_enums/entries_with_type_arguments: FormatterCrash
+enhanced_enums/enum_as_supertype: FormatterCrash
+enhanced_enums/inference_in_constructor_parameters: FormatterCrash
+enhanced_enums/instantiated_generic_enum_types: FormatterCrash
+enhanced_enums/issue48084: FormatterCrash
+enhanced_enums/issue48181: FormatterCrash
+enhanced_enums/members: FormatterCrash
+enhanced_enums/named_arguments: FormatterCrash
 enhanced_enums/qualified_names_with_no_type_arguments: FormatterCrash
+enhanced_enums/redirecting_initializers: FormatterCrash
+enhanced_enums/simple_fields: FormatterCrash
+enhanced_enums/simple_interfaces: FormatterCrash
+enhanced_enums/simple_mixins: FormatterCrash
+enhanced_enums/supertype_resolved_before_checking: FormatterCrash
 extension_types/basic_show: FormatterCrash
 extension_types/call_not_get: FormatterCrash
 extension_types/keyword_in_show_hide_element: FormatterCrash
@@ -92,6 +104,7 @@
 general/issue47495: FormatterCrash
 general/issue47728_2: FormatterCrash
 general/issue47728_3: FormatterCrash
+general/issue_46886: FormatterCrash
 general/macro_class: FormatterCrash
 general/many_errors: FormatterCrash
 general/missing_prefix_name: FormatterCrash
@@ -140,7 +153,6 @@
 late_lowering/skip_late_final_uninitialized_instance_fields/main: FormatterCrash
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
 macros/macro_class: FormatterCrash
-named_arguments_anywhere/redirecting_constructor_initializers: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
 nnbd/duplicates_instance: FormatterCrash
@@ -201,9 +213,16 @@
 regress/issue_39091_1: FormatterCrash
 regress/issue_41265.crash: Crash
 regress/issue_41265.crash: FormatterCrash
+super_parameters/circular_dependency_inference: FormatterCrash
+super_parameters/default_values: FormatterCrash
+super_parameters/issue48142: FormatterCrash
 super_parameters/simple: FormatterCrash
+super_parameters/simple_inference: FormatterCrash
 super_parameters/simple_named_super_parameters: FormatterCrash
 super_parameters/simple_positional_super_parameters: FormatterCrash
+super_parameters/super_parameters_with_types_and_default_values: FormatterCrash
+super_parameters/synthesized_super_constructor_with_parameters: FormatterCrash
+super_parameters/type_alias_in_supertype: FormatterCrash
 super_parameters/typed_super_parameter: FormatterCrash
 triple_shift/invalid_operator: FormatterCrash
 variance/class_type_parameter_modifier: FormatterCrash
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index ae8b870..f75594a 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -22,6 +22,7 @@
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
+enhanced_enums/simple_mixins: RuntimeError
 extension_types/access_setter_as_getter: ExpectationFileMismatchSerialized # Expected.
 extension_types/call_not_get: ExpectationFileMismatchSerialized # Expected.
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
@@ -47,7 +48,6 @@
 general/bug31124: RuntimeError # Test has no main method (and we shouldn't add one).
 general/call: RuntimeError
 general/cascade: RuntimeError
-general/conditional_import: RuntimeError # Issue 47814
 general/constructor_initializer_invalid: RuntimeError # Fails execution after recovery
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
@@ -104,6 +104,7 @@
 general/issue41210b/issue41210.no_link: TypeCheckError
 general/issue41210b/issue41210: TypeCheckError
 general/issue44733: TypeCheckError
+general/issue47994b: RuntimeError # Assertions are not enabled
 general/issue_46886: RuntimeError
 general/micro: RuntimeError
 general/mixin_application_override: ExpectationFileMismatch # Too many errors.
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index d0f87bb..9b60daf 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -494,6 +494,7 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
+      "test/macro_application/data/",
       "test/macros/data/",
       "test/patching/data",
       "test/predicates/data",
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 70b5606..24fad8f 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -37,7 +37,7 @@
     show IncrementalCompiler;
 
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
-    show KernelTarget;
+    show BuildResult, KernelTarget;
 
 import 'package:front_end/src/fasta/kernel/utils.dart'
     show printComponentText, writeComponentToFile;
@@ -304,10 +304,27 @@
       {Uri? output,
       bool omitPlatform: false,
       bool supportAdditionalDills: true}) async {
+    KernelTarget kernelTarget = await _createKernelTarget();
+    BuildResult buildResult = await _buildOutline(kernelTarget,
+        output: output,
+        omitPlatform: omitPlatform,
+        supportAdditionalDills: supportAdditionalDills);
+    buildResult.macroApplications?.close();
+    return kernelTarget;
+  }
+
+  Future<KernelTarget> _createKernelTarget() async {
     UriTranslator uriTranslator = await c.options.getUriTranslator();
     ticker.logMs("Read packages file");
     DillTarget dillTarget = createDillTarget(uriTranslator);
-    KernelTarget kernelTarget = createKernelTarget(dillTarget, uriTranslator);
+    return createKernelTarget(dillTarget, uriTranslator);
+  }
+
+  Future<BuildResult> _buildOutline(KernelTarget kernelTarget,
+      {Uri? output,
+      bool omitPlatform: false,
+      bool supportAdditionalDills: true}) async {
+    DillTarget dillTarget = kernelTarget.dillTarget;
 
     if (supportAdditionalDills) {
       Component? sdkSummary = await c.options.loadSdkSummary(null);
@@ -329,7 +346,8 @@
 
     kernelTarget.setEntryPoints(c.options.inputs);
     dillTarget.buildOutlines();
-    var outline = await kernelTarget.buildOutlines();
+    BuildResult buildResult = await kernelTarget.buildOutlines();
+    Component? outline = buildResult.component;
     if (c.options.debugDump && output != null) {
       printComponentText(outline,
           libraryFilter: kernelTarget.isSourceLibraryForDebugging);
@@ -353,17 +371,21 @@
       await writeComponentToFile(outline!, output);
       ticker.logMs("Wrote outline to ${output.toFilePath()}");
     }
-    return kernelTarget;
+    return buildResult;
   }
 
   Future<Uri> compile(
       {bool omitPlatform: false, bool supportAdditionalDills: true}) async {
     c.options.reportNullSafetyCompilationModeInfo();
-    KernelTarget kernelTarget =
-        await buildOutline(supportAdditionalDills: supportAdditionalDills);
+    KernelTarget kernelTarget = await _createKernelTarget();
+    BuildResult buildResult = await _buildOutline(kernelTarget,
+        supportAdditionalDills: supportAdditionalDills);
     Uri uri = c.options.output!;
-    Component component =
-        (await kernelTarget.buildComponent(verify: c.options.verify))!;
+    buildResult = await kernelTarget.buildComponent(
+        macroApplications: buildResult.macroApplications,
+        verify: c.options.verify);
+    buildResult.macroApplications?.close();
+    Component component = buildResult.component!;
     if (c.options.debugDump) {
       printComponentText(component,
           libraryFilter: kernelTarget.isSourceLibraryForDebugging);
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index b03351a..6481a4c 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -321,7 +321,6 @@
     options.target = target;
     options.omitPlatform = true;
     options.onDiagnostic = (DiagnosticMessage message) {
-      if (message.codeName == "InferredPackageUri") return;
       _print(message.plainTextFormatted.first);
       if (message.severity == Severity.error) {
         errors = true;
@@ -830,8 +829,11 @@
       packageLanguageVersion:
           new ImplicitLanguageVersion(libraryBuilder.library.languageVersion),
       loader: loader,
+      // TODO(jensj): Should probably set up scopes the same was as it's done
+      // (now) for expression compilation.
       scope: libraryBuilder.scope.createNestedScope("dartdoctest"),
       nameOrigin: libraryBuilder,
+      isUnsupported: false,
     );
 
     if (libraryBuilder is DillLibraryBuilder) {
diff --git a/pkg/front_end/tool/generate_ast_coverage.dart b/pkg/front_end/tool/generate_ast_coverage.dart
index 833e707..7471ac0 100644
--- a/pkg/front_end/tool/generate_ast_coverage.dart
+++ b/pkg/front_end/tool/generate_ast_coverage.dart
@@ -114,7 +114,7 @@
 /// Returns the set of [${innerName}Kind]s that were not visited by [visitor].
 Set<${innerName}Kind> missing${innerName}s($visitorName visitor) {
   Set<${innerName}Kind> all = 
-    new Set<${innerName}Kind>.from(${innerName}Kind.values);
+    new Set<${innerName}Kind>.of(${innerName}Kind.values);
   all.removeAll(visitor.visited);
   return all;
 }''');
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 7563736..c1dac11 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -51,6 +51,10 @@
   ..addFlag('aot',
       help: 'Run compiler in AOT mode (enables whole-program transformations)',
       defaultsTo: false)
+  ..addFlag('support-mirrors',
+      help: 'Whether dart:mirrors is supported. By default dart:mirrors is '
+          'supported when --aot and --minimal-kernel are not used.',
+      defaultsTo: null)
   ..addFlag('tfa',
       help:
           'Enable global type flow analysis and related transformations in AOT mode.',
@@ -487,6 +491,18 @@
       }
     }
 
+    if (options['support-mirrors'] == true) {
+      if (options['aot']) {
+        print('Error: --support-mirrors option cannot be used with --aot');
+        return false;
+      }
+      if (options['minimal-kernel']) {
+        print('Error: --support-mirrors option cannot be used with '
+            '--minimal-kernel');
+        return false;
+      }
+    }
+
     if (options['incremental']) {
       if (options['from-dill'] != null) {
         print('Error: --from-dill option cannot be used with --incremental');
@@ -505,6 +521,8 @@
       options['target'],
       trackWidgetCreation: options['track-widget-creation'],
       nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong,
+      supportMirrors: options['support-mirrors'] ??
+          !(options['aot'] || options['minimal-kernel']),
     );
     if (compilerOptions.target == null) {
       print('Failed to create front-end target ${options['target']}.');
diff --git a/pkg/js_ast/lib/src/equivalence_visitor.dart b/pkg/js_ast/lib/src/equivalence_visitor.dart
index 8068319..b1a150b 100644
--- a/pkg/js_ast/lib/src/equivalence_visitor.dart
+++ b/pkg/js_ast/lib/src/equivalence_visitor.dart
@@ -340,8 +340,6 @@
     if (arg is! VariableInitialization) return failAt(node, arg);
     VariableInitialization other = arg;
     return testNodes(node.declaration, other.declaration) &&
-        testNodes(node.leftHandSide, other.leftHandSide) &&
-        testValues(node, node.op, other, other.op) &&
         testNodes(node.value, other.value);
   }
 
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 56a2b40..7c62eab 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -126,13 +126,8 @@
   T visitVariableDeclarationList(VariableDeclarationList node) =>
       visitExpression(node);
   T visitAssignment(Assignment node) => visitExpression(node);
-  T visitVariableInitialization(VariableInitialization node) {
-    if (node.value != null) {
-      return visitAssignment(node);
-    } else {
-      return visitExpression(node);
-    }
-  }
+  T visitVariableInitialization(VariableInitialization node) =>
+      visitExpression(node);
 
   T visitConditional(Conditional node) => visitExpression(node);
   T visitNew(New node) => visitExpression(node);
@@ -338,13 +333,8 @@
   R visitVariableDeclarationList(VariableDeclarationList node, A arg) =>
       visitExpression(node, arg);
   R visitAssignment(Assignment node, A arg) => visitExpression(node, arg);
-  R visitVariableInitialization(VariableInitialization node, A arg) {
-    if (node.value != null) {
-      return visitAssignment(node, arg);
-    } else {
-      return visitExpression(node, arg);
-    }
-  }
+  R visitVariableInitialization(VariableInitialization node, A arg) =>
+      visitExpression(node, arg);
 
   R visitConditional(Conditional node, A arg) => visitExpression(node, arg);
   R visitNew(New node, A arg) => visitExpression(node, arg);
@@ -1162,12 +1152,13 @@
 class Assignment extends Expression {
   final Expression leftHandSide;
   final String op; // Null, if the assignment is not compound.
-  final Expression value; // May be null, for [VariableInitialization]s.
+  final Expression value;
 
   Assignment(leftHandSide, value) : this.compound(leftHandSide, null, value);
 
   // If `this.op == null` this will be a non-compound assignment.
-  Assignment.compound(this.leftHandSide, this.op, this.value);
+  Assignment.compound(this.leftHandSide, this.op, this.value)
+      : assert(value != null);
 
   int get precedenceLevel => ASSIGNMENT;
 
@@ -1180,23 +1171,26 @@
 
   void visitChildren<T>(NodeVisitor<T> visitor) {
     leftHandSide.accept(visitor);
-    if (value != null) value.accept(visitor);
+    value.accept(visitor);
   }
 
   void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {
     leftHandSide.accept1(visitor, arg);
-    if (value != null) value.accept1(visitor, arg);
+    value.accept1(visitor, arg);
   }
 
   Assignment _clone() => Assignment.compound(leftHandSide, op, value);
 }
 
-class VariableInitialization extends Assignment {
-  /// [value] may be null.
-  VariableInitialization(Declaration declaration, Expression value)
-      : super(declaration, value);
+class VariableInitialization extends Expression {
+  // TODO(sra): Can [VariableInitialization] be a non-expression?
 
-  Declaration get declaration => leftHandSide;
+  final Declaration declaration;
+  final Expression value; // [value] may be null.
+
+  VariableInitialization(this.declaration, this.value);
+
+  int get precedenceLevel => ASSIGNMENT;
 
   T accept<T>(NodeVisitor<T> visitor) =>
       visitor.visitVariableInitialization(this);
@@ -1204,6 +1198,16 @@
   R accept1<R, A>(NodeVisitor1<R, A> visitor, A arg) =>
       visitor.visitVariableInitialization(this, arg);
 
+  void visitChildren<T>(NodeVisitor<T> visitor) {
+    declaration.accept(visitor);
+    value?.accept(visitor);
+  }
+
+  void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {
+    declaration.accept1(visitor, arg);
+    value?.accept1(visitor, arg);
+  }
+
   VariableInitialization _clone() => VariableInitialization(declaration, value);
 }
 
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index d5eb576..562107f 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -840,7 +840,15 @@
 
   @override
   visitVariableInitialization(VariableInitialization initialization) {
-    visitAssignment(initialization);
+    visitNestedExpression(initialization.declaration, CALL,
+        newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
+    if (initialization.value != null) {
+      spaceOut();
+      out("=");
+      spaceOut();
+      visitNestedExpression(initialization.value, ASSIGNMENT,
+          newInForInit: inForInit, newAtStatementBegin: false);
+    }
   }
 
   @override
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index b75aba6..3df728f 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 75;
+  UInt32 formatVersion = 76;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -237,7 +237,7 @@
 }
 
 type Library {
-  Byte flags (isSynthetic, isNonNullableByDefault, nnbdModeBit1, nnbdModeBit2);
+  Byte flags (isSynthetic, isNonNullableByDefault, nnbdModeBit1, nnbdModeBit2, isUnsupported);
   UInt languageVersionMajor;
   UInt languageVersionMinor;
   CanonicalNameReference canonicalName;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 99a2f86..a2fce2f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -273,6 +273,7 @@
   static const int NonNullableByDefaultFlag = 1 << 1;
   static const int NonNullableByDefaultModeBit1 = 1 << 2;
   static const int NonNullableByDefaultModeBit2 = 1 << 3;
+  static const int IsUnsupportedFlag = 1 << 4;
 
   int flags = 0;
 
@@ -322,6 +323,13 @@
     }
   }
 
+  /// If true, the library is not supported through the 'dart.library.*' value
+  /// used in conditional imports and `bool.fromEnvironment` constants.
+  bool get isUnsupported => flags & IsUnsupportedFlag != 0;
+  void set isUnsupported(bool value) {
+    flags = value ? (flags | IsUnsupportedFlag) : (flags & ~IsUnsupportedFlag);
+  }
+
   String? name;
 
   /// Problems in this [Library] encoded as json objects.
@@ -3732,7 +3740,7 @@
     named.sort();
     // We need create a copy of the list of type parameters, otherwise
     // transformations like erasure don't work.
-    List<TypeParameter> typeParametersCopy = new List<TypeParameter>.from(
+    List<TypeParameter> typeParametersCopy = new List<TypeParameter>.of(
         parent is Constructor
             ? parent.enclosingClass.typeParameters
             : typeParameters);
@@ -3782,9 +3790,9 @@
     // We need create a copy of the list of type parameters, otherwise
     // transformations like erasure don't work.
     List<TypeParameter> classTypeParametersCopy =
-        List.from(parentConstructor.enclosingClass.typeParameters);
+        List.of(parentConstructor.enclosingClass.typeParameters);
     List<TypeParameter> typedefTypeParametersCopy =
-        List.from(typedef.typeParameters);
+        List.of(typedef.typeParameters);
     List<DartType> asTypeArguments =
         getAsTypeArguments(typedefTypeParametersCopy, library);
     TypedefType typedefType =
@@ -3826,9 +3834,9 @@
         "Only run this method on a factory");
     // We need create a copy of the list of type parameters, otherwise
     // transformations like erasure don't work.
-    List<TypeParameter> classTypeParametersCopy = List.from(typeParameters);
+    List<TypeParameter> classTypeParametersCopy = List.of(typeParameters);
     List<TypeParameter> typedefTypeParametersCopy =
-        List.from(typedef.typeParameters);
+        List.of(typedef.typeParameters);
     List<DartType> asTypeArguments =
         getAsTypeArguments(typedefTypeParametersCopy, library);
     TypedefType typedefType =
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b1f1dcd..e067807 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -598,7 +598,7 @@
       _byteOffset = start - 4;
     }
     _byteOffset = savedByteOffset;
-    return new List.from(index.reversed);
+    return new List.of(index.reversed);
   }
 
   void _checkEmptyInput() {
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index ceaae4a..a8a29ff 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -176,7 +176,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 75;
+  static const int BinaryFormatVersion = 76;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index e231e8f..cf9320c 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -929,7 +929,7 @@
     if (_recordedAmbiguousSupertypes.isNotEmpty &&
         reissueAmbiguousSupertypesFor != null) {
       Set<Library> libs =
-          new Set<Library>.from(reissueAmbiguousSupertypesFor.libraries);
+          new Set<Library>.of(reissueAmbiguousSupertypesFor.libraries);
       for (Class class_ in _recordedAmbiguousSupertypes.keys) {
         if (!libs.contains(class_.enclosingLibrary)) continue;
         List<Supertype> recorded = _recordedAmbiguousSupertypes[class_]!;
@@ -1714,7 +1714,7 @@
   }
 
   ClassSet union(ClassSet other) {
-    Set<Class> result = new Set<Class>.from(_classes);
+    Set<Class> result = new Set<Class>.of(_classes);
     result.addAll(other._classes);
     return new ClassSet(result);
   }
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index a407a13..43d7c32 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -468,7 +468,7 @@
     for (SwitchCase switchCase in node.cases) {
       switchCases[switchCase] = new SwitchCase(
           switchCase.expressions.map(clone).toList(),
-          new List<int>.from(switchCase.expressionOffsets),
+          new List<int>.of(switchCase.expressionOffsets),
           dummyStatement,
           isDefault: switchCase.isDefault);
     }
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index d4c3163..cc7de77 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -9,4 +9,4 @@
 
 import "ast.dart";
 
-Version defaultLanguageVersion = const Version(2, 16);
+Version defaultLanguageVersion = const Version(2, 17);
diff --git a/pkg/kernel/lib/src/coverage.dart b/pkg/kernel/lib/src/coverage.dart
index 01b9483..35a5692 100644
--- a/pkg/kernel/lib/src/coverage.dart
+++ b/pkg/kernel/lib/src/coverage.dart
@@ -1145,7 +1145,7 @@
 
 /// Returns the set of [MemberKind]s that were not visited by [visitor].
 Set<MemberKind> missingMembers(CoverageVisitor visitor) {
-  Set<MemberKind> all = new Set<MemberKind>.from(MemberKind.values);
+  Set<MemberKind> all = new Set<MemberKind>.of(MemberKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
@@ -1153,35 +1153,35 @@
 /// Returns the set of [InitializerKind]s that were not visited by [visitor].
 Set<InitializerKind> missingInitializers(CoverageVisitor visitor) {
   Set<InitializerKind> all =
-      new Set<InitializerKind>.from(InitializerKind.values);
+      new Set<InitializerKind>.of(InitializerKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
 
 /// Returns the set of [ExpressionKind]s that were not visited by [visitor].
 Set<ExpressionKind> missingExpressions(CoverageVisitor visitor) {
-  Set<ExpressionKind> all = new Set<ExpressionKind>.from(ExpressionKind.values);
+  Set<ExpressionKind> all = new Set<ExpressionKind>.of(ExpressionKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
 
 /// Returns the set of [StatementKind]s that were not visited by [visitor].
 Set<StatementKind> missingStatements(CoverageVisitor visitor) {
-  Set<StatementKind> all = new Set<StatementKind>.from(StatementKind.values);
+  Set<StatementKind> all = new Set<StatementKind>.of(StatementKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
 
 /// Returns the set of [DartTypeKind]s that were not visited by [visitor].
 Set<DartTypeKind> missingDartTypes(CoverageVisitor visitor) {
-  Set<DartTypeKind> all = new Set<DartTypeKind>.from(DartTypeKind.values);
+  Set<DartTypeKind> all = new Set<DartTypeKind>.of(DartTypeKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
 
 /// Returns the set of [ConstantKind]s that were not visited by [visitor].
 Set<ConstantKind> missingConstants(CoverageVisitor visitor) {
-  Set<ConstantKind> all = new Set<ConstantKind>.from(ConstantKind.values);
+  Set<ConstantKind> all = new Set<ConstantKind>.of(ConstantKind.values);
   all.removeAll(visitor.visited);
   return all;
 }
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index 61590da..9dc32175 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.dart
@@ -849,7 +849,7 @@
         int n = klass.typeParameters.length;
         List<DartType> leftArguments = type1.typeArguments;
         List<DartType> rightArguments = type2.typeArguments;
-        List<DartType> typeArguments = new List<DartType>.from(leftArguments);
+        List<DartType> typeArguments = new List<DartType>.of(leftArguments);
         for (int i = 0; i < n; ++i) {
           int variance = klass.typeParameters[i].variance;
           if (variance == Variance.contravariant) {
diff --git a/pkg/kernel/lib/src/types.dart b/pkg/kernel/lib/src/types.dart
index b78578c..f207418 100644
--- a/pkg/kernel/lib/src/types.dart
+++ b/pkg/kernel/lib/src/types.dart
@@ -404,12 +404,11 @@
   IsSubtypeOf isFutureOrRelated(FutureOrType s, InterfaceType t, Types types) {
     // Rules 7.1 and 7.2.
     return types
-        .performNullabilityAwareSubtypeCheck(s.typeArgument, t)
-        .andSubtypeCheckFor(
+        .performNullabilityAwareSubtypeCheck(
             new InterfaceType(types.hierarchy.coreTypes.futureClass,
                 Nullability.nonNullable, [s.typeArgument]),
-            t,
-            types)
+            t)
+        .andSubtypeCheckFor(s.typeArgument, t, types)
         .and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 804f26a..ea7721a 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -15,16 +15,20 @@
 class TargetFlags {
   final bool trackWidgetCreation;
   final bool enableNullSafety;
+  final bool supportMirrors;
 
   const TargetFlags(
-      {this.trackWidgetCreation = false, this.enableNullSafety = false});
+      {this.trackWidgetCreation = false,
+      this.enableNullSafety = false,
+      this.supportMirrors = true});
 
   @override
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return other is TargetFlags &&
         trackWidgetCreation == other.trackWidgetCreation &&
-        enableNullSafety == other.enableNullSafety;
+        enableNullSafety == other.enableNullSafety &&
+        supportMirrors == other.supportMirrors;
   }
 
   @override
@@ -32,6 +36,7 @@
     int hash = 485786;
     hash = 0x3fffffff & (hash * 31 + (hash ^ trackWidgetCreation.hashCode));
     hash = 0x3fffffff & (hash * 31 + (hash ^ enableNullSafety.hashCode));
+    hash = 0x3fffffff & (hash * 31 + (hash ^ supportMirrors.hashCode));
     return hash;
   }
 }
@@ -151,6 +156,95 @@
   bool get keepLocals => false;
 }
 
+/// Interface used for determining whether a `dart:*` is considered supported
+/// for the current target.
+abstract class DartLibrarySupport {
+  /// Returns `true` if the 'dart:[libraryName]' library is supported.
+  ///
+  /// [isSupportedBySpec] is `true` if the dart library was supported by the
+  /// libraries specification.
+  ///
+  /// This is used to allow AOT to consider `dart:mirrors` as unsupported
+  /// despite it being supported in the platform dill, and dart2js to consider
+  /// `dart:_dart2js_runtime_metrics` to be supported despite it being an
+  /// internal library.
+  bool computeDartLibrarySupport(String libraryName,
+      {required bool isSupportedBySpec});
+
+  static const String dartLibraryPrefix = "dart.library.";
+
+  static bool isDartLibraryQualifier(String dottedName) {
+    return dottedName.startsWith(dartLibraryPrefix);
+  }
+
+  static String getDartLibraryName(String dottedName) {
+    assert(isDartLibraryQualifier(dottedName));
+    return dottedName.substring(dartLibraryPrefix.length);
+  }
+
+  /// Returns `"true"` if the "dart:[libraryName]" is supported and `""`
+  /// otherwise.
+  ///
+  /// This is used to determine conditional imports and `bool.fromEnvironment`
+  /// constant values for "dart.library.[libraryName]" values.
+  static String getDartLibrarySupportValue(String libraryName,
+      {required bool libraryExists,
+      required bool isSynthetic,
+      required bool isUnsupported,
+      required DartLibrarySupport dartLibrarySupport}) {
+    // A `dart:` library can be unsupported for several reasons:
+    // * If the library doesn't exist from source or from dill, it is not
+    //   supported.
+    // * If the library has been synthesized, then it doesn't exist, but has
+    //   been synthetically created due to an explicit import or export of it,
+    //   in which case it is also not supported.
+    // * If the library is marked as not supported in the libraries
+    //   specification, it does exist, but is not supported.
+    // * If the library is marked as supported in the libraries specification,
+    //   it does exist and is potentially supported. Still the [Target] can
+    //   consider it unsupported. This is for instance used to consider
+    //   `dart:mirrors` as unsupported in AOT. The platform dill is shared with
+    //   JIT, so the library exists and is marked as supported, but for AOT
+    //   compilation it is still unsupported.
+    bool isSupported = libraryExists && !isSynthetic && !isUnsupported;
+    isSupported = dartLibrarySupport.computeDartLibrarySupport(libraryName,
+        isSupportedBySpec: isSupported);
+    return isSupported ? "true" : "";
+  }
+}
+
+/// [DartLibrarySupport] that only relies on the "supported" property of
+/// the libraries specification.
+class DefaultDartLibrarySupport implements DartLibrarySupport {
+  const DefaultDartLibrarySupport();
+
+  @override
+  bool computeDartLibrarySupport(String libraryName,
+          {required bool isSupportedBySpec}) =>
+      isSupportedBySpec;
+}
+
+/// [DartLibrarySupport] that supports overriding `dart:*` library support
+/// otherwise defined by the libraries specification.
+class CustomizedDartLibrarySupport implements DartLibrarySupport {
+  final Set<String> supported;
+  final Set<String> unsupported;
+
+  const CustomizedDartLibrarySupport(
+      {this.supported: const {}, this.unsupported: const {}});
+
+  @override
+  bool computeDartLibrarySupport(String libraryName,
+      {required bool isSupportedBySpec}) {
+    if (supported.contains(libraryName)) {
+      return true;
+    } else if (unsupported.contains(libraryName)) {
+      return false;
+    }
+    return isSupportedBySpec;
+  }
+}
+
 /// A target provides backend-specific options for generating kernel IR.
 abstract class Target {
   TargetFlags get flags;
@@ -434,7 +528,7 @@
   /// Returns the configured component.
   Component configureComponent(Component component) => component;
 
-  // Configure environment defines in a target-specific way.
+  /// Configure environment defines in a target-specific way.
   Map<String, String> updateEnvironmentDefines(Map<String, String> map) => map;
 
   @override
@@ -453,6 +547,16 @@
   Class? concreteStringLiteralClass(CoreTypes coreTypes, String value) => null;
 
   ConstantsBackend get constantsBackend;
+
+  /// Returns an [DartLibrarySupport] the defines which, if any, of the
+  /// `dart:` libraries supported in the platform, that should not be
+  /// considered supported when queried in conditional imports and
+  /// `bool.fromEnvironment` constants.
+  ///
+  /// This is used treat `dart:mirrors` as unsupported in AOT but supported
+  /// in JIT.
+  DartLibrarySupport get dartLibrarySupport =>
+      const DefaultDartLibrarySupport();
 }
 
 class NoneConstantsBackend extends ConstantsBackend {
@@ -657,6 +761,8 @@
   final bool? forceStaticFieldLoweringForTesting;
   final bool? forceNoExplicitGetterCallsForTesting;
   final int? forceConstructorTearOffLoweringForTesting;
+  final Set<String> supportedDartLibraries;
+  final Set<String> unsupportedDartLibraries;
 
   const TestTargetFlags(
       {bool trackWidgetCreation = false,
@@ -665,7 +771,9 @@
       this.forceStaticFieldLoweringForTesting,
       this.forceNoExplicitGetterCallsForTesting,
       this.forceConstructorTearOffLoweringForTesting,
-      bool enableNullSafety = false})
+      bool enableNullSafety = false,
+      this.supportedDartLibraries: const {},
+      this.unsupportedDartLibraries: const {}})
       : super(
             trackWidgetCreation: trackWidgetCreation,
             enableNullSafety: enableNullSafety);
@@ -698,6 +806,29 @@
   int get enabledConstructorTearOffLowerings =>
       flags.forceConstructorTearOffLoweringForTesting ??
       super.enabledConstructorTearOffLowerings;
+
+  @override
+  late final DartLibrarySupport dartLibrarySupport =
+      new TestDartLibrarySupport(super.dartLibrarySupport, flags);
+}
+
+class TestDartLibrarySupport implements DartLibrarySupport {
+  final DartLibrarySupport delegate;
+  final TestTargetFlags flags;
+
+  TestDartLibrarySupport(this.delegate, this.flags);
+
+  @override
+  bool computeDartLibrarySupport(String libraryName,
+      {required bool isSupportedBySpec}) {
+    if (flags.supportedDartLibraries.contains(libraryName)) {
+      return true;
+    } else if (flags.unsupportedDartLibraries.contains(libraryName)) {
+      return false;
+    }
+    return delegate.computeDartLibrarySupport(libraryName,
+        isSupportedBySpec: isSupportedBySpec);
+  }
 }
 
 class TargetWrapper extends Target {
@@ -939,7 +1070,7 @@
     super.performOutlineTransformations(component);
     if (!excludeNonSources) return;
 
-    List<Library> libraries = new List.from(component.libraries);
+    List<Library> libraries = new List.of(component.libraries);
     component.libraries.clear();
     Set<Uri> include = sources.toSet();
     for (Library library in libraries) {
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 4f718b9..7f0ce5d 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -454,8 +454,15 @@
     if (name != null) {
       writeWord(name);
     }
+    List<String> flags = [];
+    if (library.isUnsupported) {
+      flags.add('isUnsupported');
+    }
     if (library.isNonNullableByDefault) {
-      writeWord("/*isNonNullableByDefault*/");
+      flags.add('isNonNullableByDefault');
+    }
+    if (flags.isNotEmpty) {
+      writeWord('/*${flags.join(',')}*/');
     }
     endLine(';');
 
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index d6ef537..ad89d1f 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -223,7 +223,8 @@
           resultType: elementType)
         ..fileOffset = stmt.bodyOffset);
 
-    final Block body = Block([variable, stmt.body]);
+    final Block body = Block([variable, stmt.body])
+      ..fileOffset = stmt.bodyOffset;
 
     return transform(
         Block([syncForIterator, ForStatement([], condition, [], body)]));
diff --git a/pkg/kernel/lib/util/graph.dart b/pkg/kernel/lib/util/graph.dart
index 105b170b..7708269 100644
--- a/pkg/kernel/lib/util/graph.dart
+++ b/pkg/kernel/lib/util/graph.dart
@@ -208,3 +208,37 @@
   /// That is, `layers[i]` contain the list of vertices with index `i`.
   final List<List<T>> layers = [];
 }
+
+/// Find vertices in [graph] that either is in [vertices], has a neighbor in
+/// [vertices], has a neighbor of a neighbor (etc) in [vertices].
+Set<T> calculateTransitiveDependenciesOf<T>(Graph<T> graph, Set<T> vertices) {
+  // Compute direct dependencies for each vertex (the reverse of the
+  // edges returned by `graph.neighborsOf`).
+  Map<T, Set<T>> directDependencies = <T, Set<T>>{};
+  List<T> workList = [];
+  {
+    for (T vertex in graph.vertices) {
+      if (vertices.contains(vertex)) workList.add(vertex);
+      for (T neighbor in graph.neighborsOf(vertex)) {
+        (directDependencies[neighbor] ??= new Set<T>()).add(vertex);
+        if (vertices.contains(neighbor)) workList.add(vertex);
+      }
+    }
+  }
+
+  // Collect and remove all dependencies.
+  Set<T> left = new Set<T>.of(graph.vertices);
+  Set<T> transitive = {};
+  while (workList.isNotEmpty) {
+    T removed = workList.removeLast();
+    if (left.remove(removed)) {
+      Set<T>? s = directDependencies[removed];
+      if (s != null) {
+        // [s] is null for leaves.
+        workList.addAll(s);
+      }
+      transitive.add(removed);
+    }
+  }
+  return transitive;
+}
diff --git a/pkg/kernel/test/graph_test.dart b/pkg/kernel/test/graph_test.dart
index 83827be..cbcb0d1 100644
--- a/pkg/kernel/test/graph_test.dart
+++ b/pkg/kernel/test/graph_test.dart
@@ -556,4 +556,103 @@
       [F]
     ]
   ]);
+
+  testTransitiveDependencies(graphData: {
+    A: [B],
+    B: [A],
+  }, of: {
+    A
+  }, expected: {
+    A,
+    B,
+  });
+
+  testTransitiveDependencies(graphData: {}, of: {
+    A,
+    B,
+    C,
+    D,
+    E,
+    F,
+  }, expected: {});
+
+  {
+    String MAIN = "MAIN";
+    String DARTFFI = "DARTFFI";
+    testTransitiveDependencies(graphData: {
+      MAIN: [DARTFFI],
+    }, of: {
+      DARTFFI
+    }, expected: {
+      MAIN,
+    });
+  }
+
+  testTransitiveDependencies(graphData: {
+    A: [B],
+    B: [C],
+    C: [B, D],
+    D: [C],
+    E: [A],
+    F: [B],
+  }, of: {
+    A
+  }, expected: {
+    A,
+    E
+  });
+
+  {
+    String MAIN = "MAIN";
+    String TARGET = "TARGET";
+
+    testTransitiveDependencies(graphData: {
+      MAIN: [A, E],
+      A: [B],
+      B: [A, C],
+      C: [TARGET],
+      D: [],
+      E: [D],
+    }, of: {
+      TARGET,
+    }, expected: {
+      C,
+      B,
+      A,
+      MAIN,
+    });
+
+    testTransitiveDependencies(graphData: {
+      MAIN: [A, E],
+      A: [B],
+      B: [A, C],
+      C: [],
+      D: [],
+      E: [D],
+    }, of: {
+      TARGET,
+    }, expected: {});
+
+    testTransitiveDependencies(graphData: {
+      MAIN: [A, C, E, TARGET],
+      A: [B],
+      B: [A, C],
+      C: [],
+      D: [],
+      E: [D],
+    }, of: {
+      TARGET,
+    }, expected: {
+      MAIN,
+    });
+  }
+}
+
+void testTransitiveDependencies(
+    {required Set<String> of,
+    required Set<String> expected,
+    required Map<String, List<String>> graphData}) {
+  Graph<String> graph = new TestGraph(graphData);
+  Set<String> actual = calculateTransitiveDependenciesOf(graph, of);
+  Expect.setEquals(expected, actual);
 }
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
index 9050017..825e679 100644
--- a/pkg/modular_test/lib/src/loader.dart
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -252,6 +252,7 @@
 /// Default entries for a .packages file with paths relative to the SDK root.
 List<int> _defaultPackagesInput = utf8.encode('''
 expect:pkg/expect/lib
+smith:pkg/smith/lib
 async_helper:pkg/async_helper/lib
 meta:pkg/meta/lib
 collection:third_party/pkg/collection/lib
@@ -264,7 +265,8 @@
 // import graph, or adding tests that validate this is always up to date.
 String _defaultPackagesSpec = '''
 dependencies:
-  expect: meta
+  expect: [meta, smith]
+  smith: []
   meta: []
   async_helper: []
   collection: []
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
index e00a4e2..3f41f4c 100644
--- a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
@@ -4,7 +4,8 @@
   is package? yes
   is shared?  yes
   is sdk?  no
-  dependencies: meta, sdk
+  dependencies: meta, smith, sdk
+  lib/config.dart
   lib/expect.dart
   lib/minitest.dart
 
@@ -31,3 +32,13 @@
   is sdk?  yes
   (no dependencies)
   (sdk sources omitted)
+
+smith
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
+  lib/builder.dart
+  lib/configuration.dart
+  lib/smith.dart
+  lib/test_matrix.dart
diff --git a/pkg/modular_test/test/loader/valid_packages/expectation.txt b/pkg/modular_test/test/loader/valid_packages/expectation.txt
index e3bfaeb..1274277 100644
--- a/pkg/modular_test/test/loader/valid_packages/expectation.txt
+++ b/pkg/modular_test/test/loader/valid_packages/expectation.txt
@@ -4,7 +4,8 @@
   is package? yes
   is shared?  yes
   is sdk?  no
-  dependencies: meta, sdk
+  dependencies: meta, smith, sdk
+  lib/config.dart
   lib/expect.dart
   lib/minitest.dart
 
@@ -40,3 +41,13 @@
   is sdk?  yes
   (no dependencies)
   (sdk sources omitted)
+
+smith
+  is package? yes
+  is shared?  yes
+  is sdk?  no
+  dependencies: sdk
+  lib/builder.dart
+  lib/configuration.dart
+  lib/smith.dart
+  lib/test_matrix.dart
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index 12bf080..5ad01eb 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.4.5
+
+- Handle stack traces larger than 100 entries.
+
 ## 0.4.5-dev
 
 - Require Dart >= 2.14
diff --git a/pkg/native_stack_traces/lib/src/convert.dart b/pkg/native_stack_traces/lib/src/convert.dart
index d0d43a1..0bc8f24 100644
--- a/pkg/native_stack_traces/lib/src/convert.dart
+++ b/pkg/native_stack_traces/lib/src/convert.dart
@@ -70,7 +70,7 @@
     r')\+(?<offset>(?:0x)?[\da-f]+)';
 final _symbolOffsetRE = RegExp(_symbolOffsetREString);
 final _traceLineRE = RegExp(
-    r'    #(\d{2}) abs (?<absolute>[\da-f]+)(?: virt (?<virtual>[\da-f]+))? '
+    r'    #(\d+) abs (?<absolute>[\da-f]+)(?: virt (?<virtual>[\da-f]+))? '
     r'(?<rest>.*)$');
 
 /// Parses strings of the format <static symbol>+<integer offset>, where
diff --git a/pkg/native_stack_traces/pubspec.yaml b/pkg/native_stack_traces/pubspec.yaml
index 1110d5c..0247ac9 100644
--- a/pkg/native_stack_traces/pubspec.yaml
+++ b/pkg/native_stack_traces/pubspec.yaml
@@ -1,6 +1,6 @@
 name: native_stack_traces
 description: Utilities for working with non-symbolic stack traces.
-version: 0.4.5-dev
+version: 0.4.5
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 0fc0c32..5ab9d26 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -3174,7 +3174,7 @@
       var argument = node.argumentList.arguments.first;
       if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
         var argumentType =
-            _variables!.decoratedElementType(argument.staticElement!);
+            getOrComputeElementType(argument, argument.staticElement!);
         _graph.makeNonNullable(
             argumentType.node, QuiverCheckNotNullOrigin(source, argument));
       }
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 0caee26..8da2940 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -331,6 +331,8 @@
   final Map<MethodInvocation, DartType Function(DartType)>
       _deferredMethodInvocationProcessing = {};
 
+  final Map<Expression, DartType?> _contextTypes = {};
+
   TypeProvider get typeProvider => _fixBuilder!.typeProvider;
 
   @override
@@ -514,8 +516,10 @@
   }
 
   @override
-  DartType modifyExpressionType(Expression node, DartType type) =>
+  DartType modifyExpressionType(
+          Expression node, DartType type, DartType? contextType) =>
       _wrapExceptions(node, () => type, () {
+        _contextTypes[node] = contextType;
         if (node is NamedExpression) {
           // Do not attempt to modify named expressions.  We should already have
           // been called for [node.expression], and we should have made the
@@ -554,6 +558,12 @@
   }
 
   @override
+  void reportBinaryExpressionContext(
+      BinaryExpression node, DartType? contextType) {
+    _contextTypes[node] = contextType;
+  }
+
+  @override
   void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
     assert(_assignmentLikeExpressionHandlers[node] == null);
     if (node is AssignmentExpression) {
@@ -720,8 +730,7 @@
     }
     if (type.isDynamic) return type;
     var ancestor = _findNullabilityContextAncestor(node);
-    context ??=
-        InferenceContext.getContext(ancestor) ?? DynamicTypeImpl.instance;
+    context ??= _contextTypes[ancestor] ?? DynamicTypeImpl.instance;
     if (!_isSubtypeOrCoercible(type, context)) {
       var transformationInfo =
           _fixBuilder!._whereOrNullTransformer.tryTransformOrElseArgument(node);
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 2dad8d1..0f1e8f4 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -476,7 +476,7 @@
         var type = decoratedType.positionalParameters![0];
         _variables!.recordDecoratedElementType(declaredElement.variable, type,
             soft: true);
-        if (_hasAngularChildAnnotation(node.metadata)) {
+        if (_getAngularAnnotation(node.metadata) == _AngularAnnotation.child) {
           _graph.makeNullable(
               type!.node!, AngularAnnotationOrigin(source, node));
         }
@@ -686,9 +686,18 @@
       _variables!.recordDecoratedElementType(declaredElement, type);
       variable.initializer?.accept(this);
       if (parent is FieldDeclaration) {
-        if (_hasAngularChildAnnotation(parent.metadata)) {
-          _graph.makeNullable(
-              type.node!, AngularAnnotationOrigin(source, node));
+        var angularAnnotation = _getAngularAnnotation(parent.metadata);
+        if (angularAnnotation != null) {
+          switch (angularAnnotation) {
+            case _AngularAnnotation.child:
+              _graph.makeNullable(
+                  type.node!, AngularAnnotationOrigin(source, node));
+              break;
+            case _AngularAnnotation.children:
+              _graph.preventLate(
+                  type.node!, AngularAnnotationOrigin(source, node));
+              break;
+          }
         }
       }
     }
@@ -712,6 +721,26 @@
     );
   }
 
+  /// Determines if the given [metadata] contains a reference to one of the
+  /// Angular annotations that we have special behaviors for.  If it does,
+  /// returns an enumerated value describing the type of annotation.
+  _AngularAnnotation? _getAngularAnnotation(NodeList<Annotation> metadata) {
+    for (var annotation in metadata) {
+      var element = annotation.element;
+      if (element is ConstructorElement) {
+        var name = element.enclosingElement.name;
+        if (_isAngularUri(element.librarySource.uri)) {
+          if (name == 'ViewChild' || name == 'ContentChild') {
+            return _AngularAnnotation.child;
+          } else if (name == 'ViewChildren' || name == 'ContentChildren') {
+            return _AngularAnnotation.children;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
   /// Common handling of function and method declarations.
   DecoratedType _handleExecutableDeclaration(
       AstNode node,
@@ -938,23 +967,6 @@
         .recordDecoratedDirectSupertypes(declaredElement, decoratedSupertypes);
   }
 
-  /// Determines if the given [metadata] contains a reference to one of the
-  /// Angular annotations `ViewChild` or `ContentChild`, either of which implies
-  /// nullability of the underlying property.
-  bool _hasAngularChildAnnotation(NodeList<Annotation> metadata) {
-    for (var annotation in metadata) {
-      var element = annotation.element;
-      if (element is ConstructorElement) {
-        var name = element.enclosingElement.name;
-        if ((name == 'ViewChild' || name == 'ContentChild') &&
-            _isAngularUri(element.librarySource.uri)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
   /// Determines whether the given [uri] comes from the Angular package.
   bool _isAngularUri(Uri uri) {
     if (uri.scheme != 'package') return false;
@@ -993,3 +1005,15 @@
     throw UnimplementedError(buffer.toString());
   }
 }
+
+/// Enum describing the kinds of annotations supplied by the angular package for
+/// which we have special migration behaviors.
+enum _AngularAnnotation {
+  /// Either the `@ViewChild` or `@ContentChild` annotation.  Fields with these
+  /// annotations should always be nullable and should never be late.
+  child,
+
+  /// Either the `@ViewChildren` or `@ContentChildren` annotation.  Fields with
+  /// these annotations should never be late.
+  children,
+}
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index 8030833..f730d53 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -337,6 +337,12 @@
     _pathsBeingMigrated.add(source.fullName);
   }
 
+  /// Creates a graph edge that will try to prevent the given [node] from being
+  /// marked `late`.
+  void preventLate(NullabilityNode node, EdgeOrigin origin) {
+    connect(node, always, origin);
+  }
+
   /// Determines the nullability of each node in the graph by propagating
   /// nullability information from one node to another.
   PropagationResult propagate() {
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
index 3d5267f..51c7632 100644
--- a/pkg/nnbd_migration/test/abstract_context.dart
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -60,12 +60,18 @@
 class ContentChild {
   const ContentChild(Object selector, {Object? read});
 }
+class ContentChildren {
+  const ContentChildren(Object selector, {Object? read});
+}
 class Optional {
   const Optional();
 }
 class ViewChild {
   const ViewChild(Object selector, {Object? read});
 }
+class ViewChildren {
+  const ViewChildren(Object selector, {Object? read});
+}
 ''');
     if (internalUris) {
       addPackageFile('angular', 'angular.dart', '''
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index a2bbb70..2301e5b 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -387,6 +387,88 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_angular_contentChild_field_not_late() async {
+    addAngularPackage();
+    var content = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class MyComponent {
+  @ContentChild('foo')
+  Element bar;
+  Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar.id;
+  h() => baz.id;
+}
+''';
+    // `late` heuristics are disabled for `bar` since it's marked with
+    // `ContentChild`.  But they do apply to `baz`.
+    var expected = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class MyComponent {
+  @ContentChild('foo')
+  Element? bar;
+  late Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar!.id;
+  h() => baz.id;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_angular_contentChildren_field_not_late() async {
+    addAngularPackage();
+    var content = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class myComponent {
+  @ContentChildren('foo')
+  Element bar;
+  Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar.id;
+  h() => baz.id;
+}
+''';
+    // `late` heuristics are disabled for `bar` since it's marked with
+    // `ContentChildren`.  But they do apply to `baz`.
+    var expected = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class myComponent {
+  @ContentChildren('foo')
+  Element? bar;
+  late Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar!.id;
+  h() => baz.id;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_angular_optional_constructor_param() async {
     addAngularPackage();
     var content = '''
@@ -508,6 +590,47 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_angular_viewChild_field_not_late() async {
+    addAngularPackage();
+    var content = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class MyComponent {
+  @ViewChild('foo')
+  Element bar;
+  Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar.id;
+  h() => baz.id;
+}
+''';
+    // `late` heuristics are disabled for `bar` since it's marked with
+    // `ViewChild`.  But they do apply to `baz`.
+    var expected = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class MyComponent {
+  @ViewChild('foo')
+  Element? bar;
+  late Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar!.id;
+  h() => baz.id;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_angular_viewChild_setter() async {
     addAngularPackage();
     var content = '''
@@ -531,6 +654,47 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_angular_viewChildren_field_not_late() async {
+    addAngularPackage();
+    var content = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class myComponent {
+  @ViewChildren('foo')
+  Element bar;
+  Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar.id;
+  h() => baz.id;
+}
+''';
+    // `late` heuristics are disabled for `bar` since it's marked with
+    // `ViewChildren`.  But they do apply to `baz`.
+    var expected = '''
+import 'dart:html';
+import 'package:angular/angular.dart';
+
+class myComponent {
+  @ViewChildren('foo')
+  Element? bar;
+  late Element baz;
+
+  f(Element e) {
+    bar = e;
+    baz = e;
+  }
+  g() => bar!.id;
+  h() => baz.id;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_argumentError_checkNotNull_implies_non_null_intent() async {
     var content = '''
 void f(int i) {
@@ -7574,6 +7738,47 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_quiver_checkNotNull_field_formal_initializer() async {
+    addQuiverPackage();
+    var content = '''
+import 'package:quiver/check.dart';
+class C {
+  final int i;
+  C(this.i) {
+    checkNotNull(i);
+  }
+}
+void f(bool b, int i) {
+  if (b) new C(i);
+}
+main() {
+  f(false, null);
+}
+''';
+    // Note: since the reference to `i` in `checkNotNull(i)` refers to the field
+    // rather than the formal parameter, this isn't considered sufficient to
+    // mark the field as non-nullable (even though that's the clear intention
+    // in this case).  Changing the behavior to match user intent would require
+    // more development work; for now we just want to make sure we provide a
+    // fairly reasonable migration without crashing.
+    var expected = '''
+import 'package:quiver/check.dart';
+class C {
+  final int? i;
+  C(this.i) {
+    checkNotNull(i);
+  }
+}
+void f(bool b, int? i) {
+  if (b) new C(i);
+}
+main() {
+  f(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_quiver_checkNotNull_implies_non_null_intent() async {
     addQuiverPackage();
     var content = '''
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index b1576bb7..bac7ac7 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -584,6 +584,10 @@
   static const simarmv6 = Architecture._('simarmv6');
   static const simarm64 = Architecture._('simarm64');
   static const simarm64c = Architecture._('simarm64c');
+  static const riscv32 = Architecture._('riscv32');
+  static const riscv64 = Architecture._('riscv64');
+  static const simriscv32 = Architecture._('simriscv32');
+  static const simriscv64 = Architecture._('simriscv64');
 
   static final List<String> names = _all.keys.toList();
 
@@ -600,6 +604,10 @@
     simarmv6,
     simarm64,
     simarm64c,
+    riscv32,
+    riscv64,
+    simriscv32,
+    simriscv64,
   ], key: (architecture) => (architecture as Architecture).name);
 
   static Architecture find(String name) {
diff --git a/pkg/test_runner/lib/src/browser.dart b/pkg/test_runner/lib/src/browser.dart
index 6625a5a..f7174a2 100644
--- a/pkg/test_runner/lib/src/browser.dart
+++ b/pkg/test_runner/lib/src/browser.dart
@@ -14,6 +14,7 @@
 <html>
 <head>
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta charset="utf-8">
   <meta name="dart.unittest" content="full-stack-traces">
   <title> Test $title </title>
   <style>
@@ -172,6 +173,7 @@
 <html>
 <head>
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta charset="utf-8">
   <meta name="dart.unittest" content="full-stack-traces">
   <title>Test $testName</title>
   <style>
diff --git a/pkg/test_runner/lib/src/browser_controller.dart b/pkg/test_runner/lib/src/browser_controller.dart
index 2920dc1..607c5f1 100644
--- a/pkg/test_runner/lib/src/browser_controller.dart
+++ b/pkg/test_runner/lib/src/browser_controller.dart
@@ -1342,6 +1342,7 @@
 <!DOCTYPE html><html>
 <head>
   <title>Driving page</title>
+  <meta charset="utf-8">
   <style>
 .big-notice {
   background-color: red;
diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart
index da28355..45fa5d2 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -124,7 +124,9 @@
         (io.Platform.operatingSystem == 'windows')
             ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
             : env.write('$key=${escapeCommandLineArgument(value)} '));
-    var command = ([executable]..addAll(batchArguments)..addAll(arguments))
+    var command = ([executable]
+          ..addAll(nonBatchArguments)
+          ..addAll(arguments))
         .map(escapeCommandLineArgument)
         .join(' ');
     if (workingDirectory != null) {
@@ -135,10 +137,13 @@
 
   bool get outputIsUpToDate => false;
 
-  /// Arguments that are passed to the process when starting batch mode.
-  ///
-  /// In non-batch mode, they should be passed before [arguments].
+  /// Additional arguments to prepend before [arguments] when running the
+  /// process in batch mode.
   List<String> get batchArguments => const [];
+
+  /// Additional arguments to prepend before [arguments] when running the
+  /// process in non-batch mode.
+  List<String> get nonBatchArguments => const [];
 }
 
 class CompilationCommand extends ProcessCommand {
@@ -181,12 +186,6 @@
     if (displayName == 'precompiler' || displayName == 'app_jit') {
       return VMCommandOutput(
           this, exitCode, timedOut, stdout, stderr, time, pid);
-    } else if (displayName == 'dart2js') {
-      return Dart2jsCompilerCommandOutput(
-          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
-    } else if (displayName == 'dartdevc') {
-      return DevCompilerCommandOutput(this, exitCode, timedOut, stdout, stderr,
-          time, compilationSkipped, pid);
     }
 
     return CompilationCommandOutput(
@@ -243,6 +242,116 @@
       deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
 }
 
+class Dart2jsCompilationCommand extends CompilationCommand {
+  final bool useSdk;
+
+  Dart2jsCompilationCommand(
+      String outputFile,
+      List<Uri> bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environmentOverrides,
+      {this.useSdk,
+      bool alwaysCompile,
+      String workingDirectory,
+      int index = 0})
+      : super("dart2js", outputFile, bootstrapDependencies, executable,
+            arguments, environmentOverrides,
+            alwaysCompile: alwaysCompile,
+            workingDirectory: workingDirectory,
+            index: index);
+
+  @override
+  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
+      List<int> stderr, Duration time, bool compilationSkipped,
+      [int pid = 0]) {
+    return Dart2jsCompilerCommandOutput(
+        this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
+  }
+
+  @override
+  List<String> get batchArguments {
+    return <String>[
+      if (useSdk) ...['compile', 'js'],
+      ...super.batchArguments,
+    ];
+  }
+
+  @override
+  List<String> get nonBatchArguments {
+    return <String>[
+      if (useSdk) ...['compile', 'js'],
+      ...super.nonBatchArguments,
+    ];
+  }
+
+  @override
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(useSdk);
+  }
+
+  @override
+  bool _equal(Dart2jsCompilationCommand other) {
+    return super._equal(other) && useSdk == other.useSdk;
+  }
+}
+
+class DevCompilerCompilationCommand extends CompilationCommand {
+  final String compilerPath;
+
+  DevCompilerCompilationCommand(
+      String outputFile,
+      List<Uri> bootstrapDependencies,
+      String executable,
+      List<String> arguments,
+      Map<String, String> environmentOverrides,
+      {this.compilerPath,
+      bool alwaysCompile,
+      String workingDirectory,
+      int index = 0})
+      : super("dartdevc", outputFile, bootstrapDependencies, executable,
+            arguments, environmentOverrides,
+            alwaysCompile: alwaysCompile,
+            workingDirectory: workingDirectory,
+            index: index);
+
+  @override
+  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
+      List<int> stderr, Duration time, bool compilationSkipped,
+      [int pid = 0]) {
+    return DevCompilerCommandOutput(this, exitCode, timedOut, stdout, stderr,
+        time, compilationSkipped, pid);
+  }
+
+  @override
+  List<String> get batchArguments {
+    return <String>[
+      compilerPath,
+      ...super.batchArguments,
+    ];
+  }
+
+  @override
+  List<String> get nonBatchArguments {
+    return <String>[
+      compilerPath,
+      ...super.nonBatchArguments,
+    ];
+  }
+
+  @override
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.addJson(compilerPath);
+  }
+
+  @override
+  bool _equal(DevCompilerCompilationCommand other) {
+    return super._equal(other) && compilerPath == other.compilerPath;
+  }
+}
+
 class FastaCompilationCommand extends CompilationCommand {
   final Uri _compilerLocation;
 
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index a32b394..6d72e22 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -99,6 +99,8 @@
         if (configuration.architecture == Architecture.simarm ||
             configuration.architecture == Architecture.simarm64 ||
             configuration.architecture == Architecture.simarm64c ||
+            configuration.architecture == Architecture.simriscv32 ||
+            configuration.architecture == Architecture.simriscv64 ||
             configuration.system == System.android) {
           return VMKernelCompilerConfiguration(configuration);
         }
@@ -376,37 +378,34 @@
   }
 }
 
-/// Common configuration for dart2js-based tools, such as dart2js.
-class Dart2xCompilerConfiguration extends CompilerConfiguration {
+/// Configuration for dart2js.
+class Dart2jsCompilerConfiguration extends CompilerConfiguration {
   static final Map<String, List<Uri>> _bootstrapDependenciesCache = {};
 
-  final String moniker;
-
-  Dart2xCompilerConfiguration(this.moniker, TestConfiguration configuration)
+  Dart2jsCompilerConfiguration(TestConfiguration configuration)
       : super._subclass(configuration);
 
   String computeCompilerPath() {
-    var prefix = 'sdk/bin';
-    var suffix = shellScriptExtension;
-
-    if (_isHostChecked) {
-      if (_useSdk) {
-        // Note: when [_useSdk] is true, dart2js is run from a snapshot that was
-        // built without checked mode. The VM cannot make such snapshot run in
-        // checked mode later. These two flags could be used together if we also
-        // build an sdk with checked snapshots.
-        throw "--host-checked and --use-sdk cannot be used together";
-      }
-      // The script dart2js_developer is not included in the
-      // shipped SDK, that is the script is not installed in
-      // "$buildDir/dart-sdk/bin/"
-      return '$prefix/dart2js_developer$suffix';
+    if (_isHostChecked && _useSdk) {
+      // When [_useSdk] is true, dart2js is compiled into a snapshot that was
+      // built without checked mode. The VM cannot make such snapshot run in
+      // checked mode later. These two flags could be used together if we also
+      // build an sdk with checked snapshots.
+      throw "--host-checked and --use-sdk cannot be used together";
     }
 
     if (_useSdk) {
-      prefix = '${_configuration.buildDirectory}/dart-sdk/bin';
+      var dartSdk = '${_configuration.buildDirectory}/dart-sdk';
+      // When using the shipped sdk, we invoke dart2js via the dart CLI using
+      // `dart compile js`.  The additional `compile js` arguments are added
+      // within [Dart2jsCompilationCommand]. This is because the arguments are
+      // added differently depending on whether the command is executed in batch
+      // mode or not.
+      return '$dartSdk/bin/dart$executableExtension';
+    } else {
+      var scriptName = _isHostChecked ? 'dart2js_developer' : 'dart2js';
+      return 'sdk/bin/$scriptName$shellScriptExtension';
     }
-    return '$prefix/dart2js$suffix';
   }
 
   Command computeCompilationCommand(String outputFileName,
@@ -414,9 +413,9 @@
     arguments = arguments.toList();
     arguments.add('--out=$outputFileName');
 
-    return CompilationCommand(moniker, outputFileName, bootstrapDependencies(),
+    return Dart2jsCompilationCommand(outputFileName, bootstrapDependencies(),
         computeCompilerPath(), arguments, environmentOverrides,
-        alwaysCompile: !_useSdk);
+        useSdk: _useSdk, alwaysCompile: !_useSdk);
   }
 
   List<Uri> bootstrapDependencies() {
@@ -429,12 +428,6 @@
                   .resolve('dart-sdk/bin/snapshots/dart2js.dart.snapshot')
             ]);
   }
-}
-
-/// Configuration for dart2js.
-class Dart2jsCompilerConfiguration extends Dart2xCompilerConfiguration {
-  Dart2jsCompilerConfiguration(TestConfiguration configuration)
-      : super('dart2js', configuration);
 
   List<String> computeCompilerArguments(
       TestFile testFile, List<String> vmOptions, List<String> args) {
@@ -511,11 +504,14 @@
   DevCompilerConfiguration(TestConfiguration configuration)
       : super._subclass(configuration);
 
-  bool get useKernel => _configuration.compiler == Compiler.dartdevk;
-
   String computeCompilerPath() {
-    var dir = _useSdk ? "${_configuration.buildDirectory}/dart-sdk" : "sdk";
-    return "$dir/bin/dartdevc$shellScriptExtension";
+    // The compiler is a Dart program and not an executable itself, so the
+    // command to spawn as a subprocess is a Dart VM. Internally the
+    // [DevCompilerCompilationCommand] will prepend the snapshot or Dart library
+    // entrypoint that is executed by the VM.
+    // This will change once we update the DDC to use AOT instead of a snapshot.
+    var dir = _useSdk ? '${_configuration.buildDirectory}/dart-sdk' : 'sdk';
+    return '$dir/bin/dart$executableExtension';
   }
 
   List<String> computeCompilerArguments(
@@ -588,11 +584,12 @@
       }
     }
 
-    var inputDir = Path(inputFile).append("..").canonicalize().toNativePath();
-    var displayName = useKernel ? 'dartdevk' : 'dartdevc';
-    return CompilationCommand(displayName, outputFile, bootstrapDependencies(),
+    var compilerPath = _useSdk
+        ? '${_configuration.buildDirectory}/dart-sdk/bin/snapshots/dartdevc.dart.snapshot'
+        : Repository.uri.resolve('pkg/dev_compiler/bin/dartdevc.dart').path;
+    return DevCompilerCompilationCommand(outputFile, bootstrapDependencies(),
         computeCompilerPath(), args, environment,
-        workingDirectory: inputDir);
+        compilerPath: compilerPath);
   }
 
   CommandArtifact computeCompilationArtifact(String tempDir,
@@ -705,6 +702,16 @@
 
   bool get _isIA32 => _configuration.architecture == Architecture.ia32;
 
+  bool get _isRiscv32 => _configuration.architecture == Architecture.riscv32;
+
+  bool get _isSimRiscv32 =>
+      _configuration.architecture == Architecture.simriscv32;
+
+  bool get _isRiscv64 => _configuration.architecture == Architecture.riscv64;
+
+  bool get _isSimRiscv64 =>
+      _configuration.architecture == Architecture.simriscv64;
+
   bool get _isAot => true;
 
   PrecompilerCompilerConfiguration(TestConfiguration configuration)
@@ -880,6 +887,10 @@
         cc = 'arm-linux-gnueabihf-gcc';
       } else if (_isSimArm64 || (_isArm64 && _configuration.useQemu)) {
         cc = 'aarch64-linux-gnu-gcc';
+      } else if (_isSimRiscv32 || (_isRiscv32 && _configuration.useQemu)) {
+        cc = 'riscv32-linux-gnu-gcc';
+      } else if (_isSimRiscv64 || (_isRiscv64 && _configuration.useQemu)) {
+        cc = 'riscv64-linux-gnu-gcc';
       } else {
         cc = 'gcc';
       }
@@ -911,6 +922,10 @@
       case Architecture.arm_x64:
       case Architecture.arm64:
       case Architecture.arm64c:
+      case Architecture.riscv32:
+      case Architecture.riscv64:
+      case Architecture.simriscv32:
+      case Architecture.simriscv64:
         ccFlags = null;
         break;
       default:
@@ -922,7 +937,6 @@
       if (ccFlags != null) ccFlags,
       if (ldFlags != null) ldFlags,
       shared,
-      '-nostdlib',
       '-o',
       '$tempDir/out.aotsnapshot',
       '$tempDir/out.S'
@@ -1087,13 +1101,7 @@
   String computeCompilerPath() {
     var prefix = 'sdk/bin';
     if (_isHostChecked) {
-      if (_useSdk) {
-        throw "--host-checked and --use-sdk cannot be used together";
-      }
-      // The script dartanalyzer_developer is not included in the
-      // shipped SDK, that is the script is not installed in
-      // "$buildDir/dart-sdk/bin/"
-      return '$prefix/dartanalyzer_developer$shellScriptExtension';
+      throw "--host-checked cannot be used for dartanalyzer";
     }
     if (_useSdk) {
       prefix = '${_configuration.buildDirectory}/dart-sdk/bin';
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index 51110c0..198c01a 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -64,6 +64,7 @@
       this.keepGeneratedFiles,
       this.sharedOptions,
       String packages,
+      this.serviceResponseSizesDirectory,
       this.suiteDirectory,
       this.outputDirectory,
       this.reproducingArguments,
@@ -176,6 +177,7 @@
     return _packages;
   }
 
+  final String serviceResponseSizesDirectory;
   final String outputDirectory;
   final String suiteDirectory;
   String get babel => configuration.babel;
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index dccb5f4..cd2c23c 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -143,8 +143,8 @@
 Allowed values are:
 all
 ia32, x64
-arm, armv6, arm64,
-simarm, simarmv6, simarm64, arm_x64''',
+arm, arm64, simarm, simarm64, arm_x64
+riscv32, riscv64, simriscv32, simriscv64''',
         abbr: 'a',
         values: ['all', ...Architecture.names],
         defaultsTo: Architecture.x64.name,
@@ -338,7 +338,10 @@
         hide: true),
     _Option.bool('print_passing_stdout',
         'Print the stdout of passing, as well as failing, tests.',
-        hide: true)
+        hide: true),
+    _Option('service_response_sizes_directory',
+        'Log VM service response sizes in CSV files in the provided directory',
+        hide: true),
   ];
 
   /// For printing out reproducing command lines, we don't want to add these
@@ -775,8 +778,13 @@
               data['test_server_cross_origin_port'] as int,
           testDriverErrorPort: data["test_driver_error_port"] as int,
           localIP: data["local_ip"] as String,
-          sharedOptions: sharedOptions,
+          sharedOptions: <String>[
+            ...sharedOptions,
+            "-Dtest_runner.configuration=${innerConfiguration.name}"
+          ],
           packages: data["packages"] as String,
+          serviceResponseSizesDirectory:
+              data['service_response_sizes_directory'] as String,
           suiteDirectory: data["suite_dir"] as String,
           outputDirectory: data["output_directory"] as String,
           reproducingArguments:
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index 1810702..2341361 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -220,10 +220,18 @@
 
 class QemuConfig {
   static const all = <Architecture, QemuConfig>{
+    Architecture.ia32:
+        QemuConfig('qemu-i386', ['-L', '/usr/lib/i386-linux-gnu/']),
+    Architecture.x64:
+        QemuConfig('qemu-x86_64', ['-L', '/usr/lib/x86_64-linux-gnu/']),
     Architecture.arm:
         QemuConfig('qemu-arm', ['-L', '/usr/arm-linux-gnueabihf/']),
     Architecture.arm64:
         QemuConfig('qemu-aarch64', ['-L', '/usr/aarch64-linux-gnu/']),
+    Architecture.riscv32:
+        QemuConfig('qemu-riscv32', ['-L', '/usr/riscv32-linux-gnu/']),
+    Architecture.riscv64:
+        QemuConfig('qemu-riscv64', ['-L', '/usr/riscv64-linux-gnu/']),
   };
 
   final String executable;
@@ -253,6 +261,8 @@
       case Architecture.armv6:
       case Architecture.simarm64:
       case Architecture.simarm64c:
+      case Architecture.simriscv32:
+      case Architecture.simriscv64:
         multiplier *= 4;
         break;
     }
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 995bf0a..72ed102 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -260,7 +260,7 @@
       _commandComplete(0);
     } else {
       var processEnvironment = _createProcessEnvironment();
-      var args = command.arguments;
+      var args = [...command.nonBatchArguments, ...command.arguments];
       var processFuture = io.Process.start(command.executable, args,
           environment: processEnvironment,
           workingDirectory: command.workingDirectory);
@@ -285,7 +285,9 @@
               executable = '/usr/bin/sample';
             } else if (io.Platform.isWindows) {
               var isX64 = command.executable.contains("X64") ||
-                  command.executable.contains("SIMARM64");
+                  command.executable.contains("SIMARM64") ||
+                  command.executable.contains("SIMARM64C") ||
+                  command.executable.contains("SIMRISCV64");
               if (configuration.windowsSdkPath != null) {
                 executable = configuration.windowsSdkPath +
                     "\\Debuggers\\${isX64 ? 'x64' : 'x86'}\\cdb.exe";
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 9a5d685..5aeaf54 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -399,6 +399,8 @@
     "x64_linux",
     "x64_macos",
     "x64_win",
+    "riscv32_linux",
+    "riscv64_linux",
   ];
 
   FfiTestSuite(TestConfiguration configuration)
@@ -763,6 +765,8 @@
           ...vmOptionsList[vmOptionsVariant],
           ...extraVmOptions,
           if (emitDdsTest) '-DUSE_DDS=true',
+          if (configuration.serviceResponseSizesDirectory != null)
+            '-DSERVICE_RESPONSE_SIZES_DIR=${configuration.serviceResponseSizesDirectory}',
         ];
         var isCrashExpected = expectations.contains(Expectation.crash);
         var commands = _makeCommands(
diff --git a/pkg/test_runner/lib/src/testing_servers.dart b/pkg/test_runner/lib/src/testing_servers.dart
index ca69031..ac04529 100644
--- a/pkg/test_runner/lib/src/testing_servers.dart
+++ b/pkg/test_runner/lib/src/testing_servers.dart
@@ -301,6 +301,7 @@
     <html>
     <head>
       <title>${request.uri.path}</title>
+      <meta charset="utf-8">
     </head>
     <body>
       <code>
diff --git a/pkg/vm/bin/compare_il.dart b/pkg/vm/bin/compare_il.dart
index 5b9caa3..7545b08 100644
--- a/pkg/vm/bin/compare_il.dart
+++ b/pkg/vm/bin/compare_il.dart
@@ -29,13 +29,14 @@
   final graphs = _loadGraphs(ilFile, rename);
   final tests = await _loadTestCases(testFile);
 
-  Map<String, FlowGraph> findMatchingGraphs(String name) {
-    final suffix = '_${rename(name)}';
+  Map<String, FlowGraph> findMatchingGraphs(String name, String? closureName) {
+    final closureSuffix = closureName != null ? '_${rename(closureName)}' : '';
+    final suffix = '_${rename(name)}${closureSuffix}';
     return graphs.entries.firstWhere((f) => f.key.contains(suffix)).value;
   }
 
   for (var test in tests) {
-    test.run(findMatchingGraphs(test.name));
+    test.run(findMatchingGraphs(test.name, test.closureName));
   }
 
   exit(0); // Success.
@@ -43,6 +44,7 @@
 
 class TestCase {
   final String name;
+  final String? closureName;
   final String phasesFilter;
   final LibraryMirror library;
 
@@ -51,13 +53,16 @@
 
   TestCase({
     required this.name,
+    this.closureName,
     required this.phasesFilter,
     required this.library,
   });
 
+  late final fullName = name + (closureName != null ? '_$closureName' : '');
+
   void run(Map<String, FlowGraph> graphs) {
-    print('matching IL (${phases.join(', ')}) for $name');
-    library.invoke(MirrorSystem.getSymbol('matchIL\$$name'),
+    print('matching IL (${phases.join(', ')}) for $fullName');
+    library.invoke(MirrorSystem.getSymbol('matchIL\$$fullName'),
         phases.map((phase) => graphs[phase]!).toList());
     print('... ok');
   }
@@ -104,20 +109,35 @@
       .firstWhereOrNull((p) => p.name == name);
 
   final cases = LinkedHashSet<TestCase>(
-    equals: (a, b) => a.name == b.name,
-    hashCode: (a) => a.name.hashCode,
+    equals: (a, b) => a.fullName == b.fullName,
+    hashCode: (a) => a.fullName.hashCode,
   );
 
   void processDeclaration(DeclarationMirror decl) {
-    final p = getPragma(decl, 'vm:testing:print-flow-graph');
+    TestCase? testCase;
+    pragma? p = getPragma(decl, 'vm:testing:print-flow-graph');
     if (p != null) {
       final name = MirrorSystem.getName(decl.simpleName);
-      final added = cases.add(TestCase(
+      testCase = TestCase(
         name: name,
         phasesFilter: (p.options as String?) ?? 'AllocateRegisters',
         library: library,
-      ));
-      if (!added) throw 'duplicate test case with name $name';
+      );
+    }
+    p = getPragma(decl, 'vm:testing:match-inner-flow-graph');
+    if (p != null) {
+      final name = MirrorSystem.getName(decl.simpleName);
+      final closureName = p.options as String;
+      testCase = TestCase(
+        name: name,
+        closureName: closureName,
+        phasesFilter: 'AllocateRegisters',
+        library: library,
+      );
+    }
+    if (testCase != null) {
+      final added = cases.add(testCase);
+      if (!added) throw 'duplicate test case with name ${testCase.fullName}';
     }
   }
 
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 871ee7d..74c8888 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -77,6 +77,10 @@
       help:
           'Produce kernel file for AOT compilation (enables global transformations).',
       defaultsTo: false);
+  args.addFlag('support-mirrors',
+      help: 'Whether dart:mirrors is supported. By default dart:mirrors is '
+          'supported when --aot and --minimal-kernel are not used.',
+      defaultsTo: null);
   args.addOption('depfile', help: 'Path to output Ninja depfile');
   args.addOption('from-dill',
       help: 'Read existing dill file instead of compiling from sources',
@@ -193,6 +197,7 @@
   final bool splitOutputByPackages = options['split-output-by-packages'];
   final String? manifestFilename = options['manifest'];
   final String? dataDir = options['component-name'] ?? options['data-dir'];
+  final bool? supportMirrors = options['support-mirrors'];
 
   final bool minimalKernel = options['minimal-kernel'];
   final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
@@ -215,6 +220,18 @@
     }
   }
 
+  if (supportMirrors == true) {
+    if (aot) {
+      print('Error: --support-mirrors option cannot be used with --aot');
+      return badUsageExitCode;
+    }
+    if (minimalKernel) {
+      print('Error: --support-mirrors option cannot be used with '
+          '--minimal-kernel');
+      return badUsageExitCode;
+    }
+  }
+
   final fileSystem =
       createFrontEndFileSystem(fileSystemScheme, fileSystemRoots);
 
@@ -258,11 +275,10 @@
     await autoDetectNullSafetyMode(mainUri, compilerOptions);
   }
 
-  compilerOptions.target = createFrontEndTarget(
-    targetName,
-    trackWidgetCreation: options['track-widget-creation'],
-    nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong,
-  );
+  compilerOptions.target = createFrontEndTarget(targetName,
+      trackWidgetCreation: options['track-widget-creation'],
+      nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong,
+      supportMirrors: supportMirrors ?? !(aot || minimalKernel));
   if (compilerOptions.target == null) {
     print('Failed to create front-end target $targetName.');
     return badUsageExitCode;
@@ -442,6 +458,7 @@
     {bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false,
     bool useRapidTypeAnalysis: true}) async {
+  assert(!target.flags.supportMirrors);
   if (errorDetector.hasCompilationErrors) return;
 
   final coreTypes = new CoreTypes(component);
@@ -585,12 +602,16 @@
 
 /// Create front-end target with given name.
 Target? createFrontEndTarget(String targetName,
-    {bool trackWidgetCreation = false, bool nullSafety = false}) {
+    {bool trackWidgetCreation = false,
+    bool nullSafety = false,
+    bool supportMirrors = true}) {
   // Make sure VM-specific targets are available.
   installAdditionalTargets();
 
   final TargetFlags targetFlags = new TargetFlags(
-      trackWidgetCreation: trackWidgetCreation, enableNullSafety: nullSafety);
+      trackWidgetCreation: trackWidgetCreation,
+      enableNullSafety: nullSafety,
+      supportMirrors: supportMirrors);
   return getTarget(targetName, targetFlags);
 }
 
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index cb866c8..b1a60d8 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -18,7 +18,8 @@
 import '../transformations/call_site_annotator.dart' as callSiteAnnotator;
 import '../transformations/lowering.dart' as lowering
     show transformLibraries, transformProcedure;
-import '../transformations/ffi/common.dart' as ffiHelper show importsFfi;
+import '../transformations/ffi/common.dart' as ffiHelper
+    show calculateTransitiveImportsOfDartFfiIfUsed;
 import '../transformations/ffi/definitions.dart' as transformFfiDefinitions
     show transformLibraries;
 import '../transformations/ffi/native.dart' as transformFfiNative
@@ -154,7 +155,9 @@
         this, coreTypes, hierarchy, libraries, referenceFromIndex);
     logger?.call("Transformed mixin applications");
 
-    if (!ffiHelper.importsFfi(component, libraries)) {
+    List<Library>? transitiveImportingDartFfi = ffiHelper
+        .calculateTransitiveImportsOfDartFfiIfUsed(component, libraries);
+    if (transitiveImportingDartFfi == null) {
       logger?.call("Skipped ffi transformation");
     } else {
       // Transform @FfiNative(..) functions into FFI native call functions.
@@ -163,21 +166,19 @@
       // Transform arguments that extend NativeFieldWrapperClass1 to Pointer if
       // the native function expects Pointer (to avoid Handle overhead).
       transformFfiNative.transformLibraries(component, coreTypes, hierarchy,
-          libraries, diagnosticReporter, referenceFromIndex);
+          transitiveImportingDartFfi, diagnosticReporter, referenceFromIndex);
       logger?.call("Transformed ffi natives");
 
-      // TODO(jensj/dacoharkes): We can probably limit the transformations to
-      // libraries that transitivley depend on dart:ffi.
       transformFfiDefinitions.transformLibraries(
           component,
           coreTypes,
           hierarchy,
-          libraries,
+          transitiveImportingDartFfi,
           diagnosticReporter,
           referenceFromIndex,
           changedStructureNotifier);
       transformFfiUseSites.transformLibraries(component, coreTypes, hierarchy,
-          libraries, diagnosticReporter, referenceFromIndex);
+          transitiveImportingDartFfi, diagnosticReporter, referenceFromIndex);
       logger?.call("Transformed ffi annotations");
     }
 
@@ -500,18 +501,11 @@
     // TODO(alexmarkov): Call this from the front-end in order to have
     //  the same defines when compiling platform.
     map['dart.isVM'] = 'true';
-    // TODO(dartbug.com/36460): Derive dart.library.* definitions from platform.
-    for (String library in extraRequiredLibraries) {
-      Uri libraryUri = Uri.parse(library);
-      if (libraryUri.scheme == 'dart') {
-        final path = libraryUri.path;
-        if (!path.startsWith('_')) {
-          map['dart.library.${path}'] = 'true';
-        }
-      }
-    }
-    // dart:core is not mentioned in Target.extraRequiredLibraries.
-    map['dart.library.core'] = 'true';
     return map;
   }
+
+  @override
+  DartLibrarySupport get dartLibrarySupport => flags.supportMirrors
+      ? const DefaultDartLibrarySupport()
+      : const CustomizedDartLibrarySupport(unsupported: {'mirrors'});
 }
diff --git a/pkg/vm/lib/transformations/ffi/abi.dart b/pkg/vm/lib/transformations/ffi/abi.dart
index 04bc8e2..cc2d86b 100644
--- a/pkg/vm/lib/transformations/ffi/abi.dart
+++ b/pkg/vm/lib/transformations/ffi/abi.dart
@@ -12,6 +12,8 @@
   arm64,
   ia32,
   x64,
+  riscv32,
+  riscv64,
 }
 
 extension on _Architecture {
@@ -20,9 +22,11 @@
     switch (this) {
       case _Architecture.arm:
       case _Architecture.ia32:
+      case _Architecture.riscv32:
         return 4;
       case _Architecture.arm64:
       case _Architecture.x64:
+      case _Architecture.riscv64:
         return 8;
     }
   }
@@ -91,6 +95,12 @@
   /// The application binary interface for linux on the X64 architecture.
   static const linuxX64 = _linuxX64;
 
+  /// The application binary interface for linux on 32-bit RISC-V.
+  static const linuxRiscv32 = _linuxRiscv32;
+
+  /// The application binary interface for linux on 64-bit RISC-V.
+  static const linuxRiscv64 = _linuxRiscv64;
+
   /// The application binary interface for MacOS on the Arm64 architecture.
   static const macosArm64 = _macosArm64;
 
@@ -128,6 +138,8 @@
     linuxArm64,
     linuxIA32,
     linuxX64,
+    linuxRiscv32,
+    linuxRiscv64,
     macosArm64,
     macosX64,
     windowsArm64,
@@ -171,6 +183,8 @@
   static const _linuxArm64 = Abi._(_Architecture.arm64, _OS.linux);
   static const _linuxIA32 = Abi._(_Architecture.ia32, _OS.linux);
   static const _linuxX64 = Abi._(_Architecture.x64, _OS.linux);
+  static const _linuxRiscv32 = Abi._(_Architecture.riscv32, _OS.linux);
+  static const _linuxRiscv64 = Abi._(_Architecture.riscv64, _OS.linux);
   static const _macosArm64 = Abi._(_Architecture.arm64, _OS.macos);
   static const _macosX64 = Abi._(_Architecture.x64, _OS.macos);
   static const _windowsArm64 = Abi._(_Architecture.arm64, _OS.windows);
@@ -193,6 +207,8 @@
   Abi.linuxArm64: 'linuxArm64',
   Abi.linuxIA32: 'linuxIA32',
   Abi.linuxX64: 'linuxX64',
+  Abi.linuxRiscv32: 'linuxRiscv32',
+  Abi.linuxRiscv64: 'linuxRiscv64',
   Abi.macosArm64: 'macosArm64',
   Abi.macosX64: 'macosX64',
   Abi.windowsArm64: 'windowsArm64',
@@ -229,6 +245,7 @@
   Abi.iosX64: _wordSize64,
   Abi.linuxArm64: _wordSize64,
   Abi.linuxX64: _wordSize64,
+  Abi.linuxRiscv64: _wordSize64,
   Abi.macosArm64: _wordSize64,
   Abi.macosX64: _wordSize64,
   Abi.windowsArm64: _wordSize64,
@@ -240,6 +257,7 @@
   // _wordSize32Align64
   Abi.androidArm: _wordSize32Align64,
   Abi.linuxArm: _wordSize32Align64,
+  Abi.linuxRiscv32: _wordSize32Align64,
   Abi.windowsIA32: _wordSize32Align64,
 };
 
diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart
index b50d0a2..c23bddb 100644
--- a/pkg/vm/lib/transformations/ffi/common.dart
+++ b/pkg/vm/lib/transformations/ffi/common.dart
@@ -16,6 +16,7 @@
 import 'package:kernel/type_algebra.dart' show Substitution;
 import 'package:kernel/type_environment.dart'
     show TypeEnvironment, SubtypeCheckMode;
+import 'package:kernel/util/graph.dart' as kernelGraph;
 
 import 'abi.dart';
 import 'native_type_cfe.dart';
@@ -35,7 +36,6 @@
   kUint16,
   kUint32,
   kUint64,
-  kIntptr,
   kFloat,
   kDouble,
   kVoid,
@@ -56,11 +56,6 @@
   NativeType.kUint64,
 };
 
-const Set<NativeType> nativeIntTypes = <NativeType>{
-  ...nativeIntTypesFixedSize,
-  NativeType.kIntptr,
-};
-
 /// The [NativeType] class names.
 const Map<NativeType, String> nativeTypeClassNames = <NativeType, String>{
   NativeType.kNativeType: 'NativeType',
@@ -76,7 +71,6 @@
   NativeType.kUint16: 'Uint16',
   NativeType.kUint32: 'Uint32',
   NativeType.kUint64: 'Uint64',
-  NativeType.kIntptr: 'IntPtr',
   NativeType.kFloat: 'Float',
   NativeType.kDouble: 'Double',
   NativeType.kVoid: 'Void',
@@ -104,7 +98,6 @@
   NativeType.kUint16: 2,
   NativeType.kUint32: 4,
   NativeType.kUint64: 8,
-  NativeType.kIntptr: WORD_SIZE,
   NativeType.kFloat: 4,
   NativeType.kDouble: 8,
   NativeType.kVoid: UNKNOWN,
@@ -125,7 +118,6 @@
   NativeType.kUint16,
   NativeType.kUint32,
   NativeType.kUint64,
-  NativeType.kIntptr,
   NativeType.kFloat,
   NativeType.kDouble,
   NativeType.kPointer,
@@ -203,10 +195,14 @@
   final Procedure offsetByMethod;
   final Procedure elementAtMethod;
   final Procedure addressGetter;
-  final Procedure structPointerRef;
-  final Procedure structPointerElemAt;
-  final Procedure unionPointerRef;
-  final Procedure unionPointerElemAt;
+  final Procedure structPointerGetRef;
+  final Procedure structPointerSetRef;
+  final Procedure structPointerGetElemAt;
+  final Procedure structPointerSetElemAt;
+  final Procedure unionPointerGetRef;
+  final Procedure unionPointerSetRef;
+  final Procedure unionPointerGetElemAt;
+  final Procedure unionPointerSetElemAt;
   final Procedure structArrayElemAt;
   final Procedure unionArrayElemAt;
   final Procedure arrayArrayElemAt;
@@ -249,6 +245,8 @@
   final Procedure storeAbiSpecificIntAtIndexMethod;
   final Procedure abiCurrentMethod;
   final Map<Constant, Abi> constantAbis;
+  final Class intptrClass;
+  late AbiSpecificNativeTypeCfe intptrNativeTypeCfe;
   final Procedure memCopy;
   final Procedure allocationTearoff;
   final Procedure asFunctionTearoff;
@@ -378,14 +376,22 @@
         arrayConstructor = index.getConstructor('dart:ffi', 'Array', '_'),
         fromAddressInternal =
             index.getTopLevelProcedure('dart:ffi', '_fromAddress'),
-        structPointerRef =
+        structPointerGetRef =
             index.getProcedure('dart:ffi', 'StructPointer', 'get:ref'),
-        structPointerElemAt =
+        structPointerSetRef =
+            index.getProcedure('dart:ffi', 'StructPointer', 'set:ref'),
+        structPointerGetElemAt =
             index.getProcedure('dart:ffi', 'StructPointer', '[]'),
-        unionPointerRef =
+        structPointerSetElemAt =
+            index.getProcedure('dart:ffi', 'StructPointer', '[]='),
+        unionPointerGetRef =
             index.getProcedure('dart:ffi', 'UnionPointer', 'get:ref'),
-        unionPointerElemAt =
+        unionPointerSetRef =
+            index.getProcedure('dart:ffi', 'UnionPointer', 'set:ref'),
+        unionPointerGetElemAt =
             index.getProcedure('dart:ffi', 'UnionPointer', '[]'),
+        unionPointerSetElemAt =
+            index.getProcedure('dart:ffi', 'UnionPointer', '[]='),
         structArrayElemAt = index.getProcedure('dart:ffi', 'StructArray', '[]'),
         unionArrayElemAt = index.getProcedure('dart:ffi', 'UnionArray', '[]'),
         arrayArrayElemAt = index.getProcedure('dart:ffi', 'ArrayArray', '[]'),
@@ -461,6 +467,7 @@
                     as ConstantExpression)
                 .constant,
             abi)),
+        intptrClass = index.getClass('dart:ffi', 'IntPtr'),
         memCopy = index.getTopLevelProcedure('dart:ffi', '_memCopy'),
         allocationTearoff = index.getProcedure(
             'dart:ffi', 'AllocatorAlloc', LibraryIndex.tearoffPrefix + 'call'),
@@ -482,6 +489,9 @@
         .getThisType(coreTypes, Nullability.nonNullable);
     pointerVoidType =
         InterfaceType(pointerClass, Nullability.nonNullable, [voidType]);
+    intptrNativeTypeCfe =
+        NativeTypeCfe(this, InterfaceType(intptrClass, Nullability.nonNullable))
+            as AbiSpecificNativeTypeCfe;
   }
 
   @override
@@ -548,7 +558,7 @@
     if (nativeType_ == NativeType.kPointer) {
       return nativeType;
     }
-    if (nativeIntTypes.contains(nativeType_)) {
+    if (nativeIntTypesFixedSize.contains(nativeType_)) {
       return InterfaceType(intClass, Nullability.legacy);
     }
     if (nativeType_ == NativeType.kFloat || nativeType_ == NativeType.kDouble) {
@@ -971,18 +981,61 @@
   }
 }
 
+/// Returns all libraries including the ones from component except for platform
+/// libraries that are only in component.
+Set<Library> _getAllRelevantLibraries(
+    Component component, List<Library> libraries) {
+  Set<Library> allLibs = {};
+  allLibs.addAll(libraries);
+  for (Library lib in component.libraries) {
+    // Skip real dart: libraries. dart:core imports dart:ffi, but that doesn't
+    // mean we have to transform anything.
+    if (lib.importUri.scheme == "dart" && !lib.isSynthetic) continue;
+    allLibs.add(lib);
+  }
+  return allLibs;
+}
+
 /// Checks if any library depends on dart:ffi.
-bool importsFfi(Component component, List<Library> libraries) {
-  Set<Library> allLibs = {...component.libraries, ...libraries};
+Library? importsFfi(Component component, List<Library> libraries) {
   final Uri dartFfiUri = Uri.parse("dart:ffi");
+  Set<Library> allLibs = _getAllRelevantLibraries(component, libraries);
   for (Library lib in allLibs) {
     for (LibraryDependency dependency in lib.dependencies) {
-      if (dependency.targetLibrary.importUri == dartFfiUri) {
-        return true;
+      Library targetLibrary = dependency.targetLibrary;
+      if (targetLibrary.importUri == dartFfiUri) {
+        return targetLibrary;
       }
     }
   }
-  return false;
+  return null;
+}
+
+/// Calculates the libraries in [libraries] that transitively imports dart:ffi.
+///
+/// Returns null if dart:ffi is not imported.
+List<Library>? calculateTransitiveImportsOfDartFfiIfUsed(
+    Component component, List<Library> libraries) {
+  Set<Library> allLibs = _getAllRelevantLibraries(component, libraries);
+
+  final Uri dartFfiUri = Uri.parse("dart:ffi");
+  Library? dartFfi;
+  canFind:
+  for (Library lib in allLibs) {
+    for (LibraryDependency dependency in lib.dependencies) {
+      Library targetLibrary = dependency.targetLibrary;
+      if (targetLibrary.importUri == dartFfiUri) {
+        dartFfi = targetLibrary;
+        break canFind;
+      }
+    }
+  }
+  if (dartFfi == null) return null;
+
+  kernelGraph.LibraryGraph graph = new kernelGraph.LibraryGraph(allLibs);
+  Set<Library> result =
+      kernelGraph.calculateTransitiveDependenciesOf(graph, {dartFfi});
+  return (result..retainAll(libraries)).toList();
 }
 
 extension on Map<Abi, Object?> {
diff --git a/pkg/vm/lib/transformations/ffi/native_type_cfe.dart b/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
index bb73a94..4a19480 100644
--- a/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
+++ b/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
@@ -81,11 +81,19 @@
   /// The size in bytes per [Abi].
   Map<Abi, int?> get size;
 
+  /// The size in bytes for [Abi].
+  int? getSizeFor(Abi abi);
+
   /// The alignment inside structs in bytes per [Abi].
   ///
   /// This is not the alignment on stack, this is only calculated in the VM.
   Map<Abi, int?> get alignment;
 
+  /// The alignment inside structs in bytes for [Abi].
+  ///
+  /// This is not the alignment on stack, this is only calculated in the VM.
+  int? getAlignmentFor(Abi abi);
+
   /// Generates a Constant representing the type which is consumed by the VM.
   ///
   /// Takes [transformer] to be able to lookup classes and methods.
@@ -120,6 +128,9 @@
   Map<Abi, int?> get alignment => throw reason;
 
   @override
+  int? getAlignmentFor(Abi abi) => throw reason;
+
+  @override
   Constant generateConstant(FfiTransformer transformer) => throw reason;
 
   @override
@@ -143,6 +154,9 @@
 
   @override
   Map<Abi, int?> get size => throw reason;
+
+  @override
+  int? getSizeFor(Abi abi) => throw reason;
 }
 
 class PrimitiveNativeTypeCfe implements NativeTypeCfe {
@@ -162,12 +176,25 @@
   }
 
   @override
+  int? getSizeFor(Abi abi) {
+    final int size = nativeTypeSizes[nativeType]!;
+    if (size == WORD_SIZE) {
+      return wordSize[abi];
+    }
+    return size;
+  }
+
+  @override
   Map<Abi, int> get alignment => {
         for (var abi in Abi.values)
-          abi: nonSizeAlignment[abi]![nativeType] ?? size[abi]!
+          abi: nonSizeAlignment[abi]![nativeType] ?? getSizeFor(abi)!
       };
 
   @override
+  int? getAlignmentFor(Abi abi) =>
+      nonSizeAlignment[abi]![nativeType] ?? getSizeFor(abi)!;
+
+  @override
   Constant generateConstant(FfiTransformer transformer) =>
       TypeLiteralConstant(InterfaceType(clazz, Nullability.nonNullable));
 
@@ -240,9 +267,15 @@
   Map<Abi, int?> get size => wordSize;
 
   @override
+  int? getSizeFor(Abi abi) => wordSize[abi];
+
+  @override
   Map<Abi, int?> get alignment => wordSize;
 
   @override
+  int? getAlignmentFor(Abi abi) => wordSize[abi];
+
+  @override
   Constant generateConstant(FfiTransformer transformer) => TypeLiteralConstant(
           InterfaceType(transformer.pointerClass, Nullability.nonNullable, [
         InterfaceType(
@@ -252,7 +285,7 @@
   /// Sample output for `Pointer<Int8> get x =>`:
   ///
   /// ```
-  /// _fromAddress<Int8>(_loadIntPtr(_typedDataBase, offset));
+  /// _fromAddress<Int8>(_loadAbiSpecificInt<IntPtr>(_typedDataBase, offset));
   /// ```
   @override
   ReturnStatement generateGetterStatement(
@@ -264,14 +297,13 @@
       ReturnStatement(StaticInvocation(
           transformer.fromAddressInternal,
           Arguments([
-            StaticInvocation(
-                transformer.loadMethods[NativeType.kIntptr]!,
-                Arguments([
-                  transformer.getCompoundTypedDataBaseField(
-                      ThisExpression(), fileOffset),
-                  transformer.runtimeBranchOnLayout(offsets)
-                ]))
-              ..fileOffset = fileOffset
+            transformer.abiSpecificLoadOrStoreExpression(
+              transformer.intptrNativeTypeCfe,
+              typedDataBase: transformer.getCompoundTypedDataBaseField(
+                  ThisExpression(), fileOffset),
+              offsetInBytes: transformer.runtimeBranchOnLayout(offsets),
+              fileOffset: fileOffset,
+            ),
           ], types: [
             (dartType as InterfaceType).typeArguments.single
           ]))
@@ -280,7 +312,11 @@
   /// Sample output for `set x(Pointer<Int8> #v) =>`:
   ///
   /// ```
-  /// _storeIntPtr(_typedDataBase, offset, (#v as Pointer<Int8>).address);
+  /// _storeAbiSpecificInt<IntPtr>(
+  ///   _typedDataBase,
+  ///   offset,
+  ///   (#v as Pointer<Int8>).address,
+  /// );
   /// ```
   @override
   ReturnStatement generateSetterStatement(
@@ -290,19 +326,22 @@
           bool unalignedAccess,
           VariableDeclaration argument,
           FfiTransformer transformer) =>
-      ReturnStatement(StaticInvocation(
-          transformer.storeMethods[NativeType.kIntptr]!,
-          Arguments([
-            transformer.getCompoundTypedDataBaseField(
-                ThisExpression(), fileOffset),
-            transformer.runtimeBranchOnLayout(offsets),
-            InstanceGet(InstanceAccessKind.Instance, VariableGet(argument),
-                transformer.addressGetter.name,
-                interfaceTarget: transformer.addressGetter,
-                resultType: transformer.addressGetter.getterType)
-              ..fileOffset = fileOffset
-          ]))
-        ..fileOffset = fileOffset);
+      ReturnStatement(
+        transformer.abiSpecificLoadOrStoreExpression(
+          transformer.intptrNativeTypeCfe,
+          typedDataBase: transformer.getCompoundTypedDataBaseField(
+              ThisExpression(), fileOffset),
+          offsetInBytes: transformer.runtimeBranchOnLayout(offsets),
+          value: InstanceGet(
+            InstanceAccessKind.Instance,
+            VariableGet(argument),
+            transformer.addressGetter.name,
+            interfaceTarget: transformer.addressGetter,
+            resultType: transformer.addressGetter.getterType,
+          )..fileOffset = fileOffset,
+          fileOffset: fileOffset,
+        ),
+      );
 }
 
 /// The layout of a `Struct` or `Union` in one [Abi].
@@ -335,10 +374,16 @@
       layout.map((abi, layout) => MapEntry(abi, layout.size));
 
   @override
+  int? getSizeFor(Abi abi) => layout[abi]?.size;
+
+  @override
   Map<Abi, int?> get alignment =>
       layout.map((abi, layout) => MapEntry(abi, layout.alignment));
 
   @override
+  int? getAlignmentFor(Abi abi) => layout[abi]?.alignment;
+
+  @override
   Constant generateConstant(FfiTransformer transformer) =>
       TypeLiteralConstant(InterfaceType(clazz, Nullability.nonNullable));
 
@@ -424,8 +469,8 @@
     final offsets = <int?>[];
     int? structAlignment = 1;
     for (int i = 0; i < types.length; i++) {
-      final int? size = types[i].size[abi];
-      int? alignment = types[i].alignment[abi];
+      final int? size = types[i].getSizeFor(abi);
+      int? alignment = types[i].getAlignmentFor(abi);
       if (packing != null) {
         alignment = min(packing, alignment);
       }
@@ -459,8 +504,8 @@
     int? unionSize = 1;
     int? unionAlignment = 1;
     for (int i = 0; i < types.length; i++) {
-      final int? size = types[i].size[abi];
-      int? alignment = types[i].alignment[abi];
+      final int? size = types[i].getSizeFor(abi);
+      int? alignment = types[i].getAlignmentFor(abi);
       unionSize = max(unionSize, size);
       unionAlignment = max(unionAlignment, alignment);
     }
@@ -511,8 +556,14 @@
       elementType.size.map((abi, size) => MapEntry(abi, size * length));
 
   @override
+  int? getSizeFor(Abi abi) => elementType.getSizeFor(abi) * length;
+
+  @override
   Map<Abi, int?> get alignment => elementType.alignment;
 
+  @override
+  int? getAlignmentFor(Abi abi) => elementType.getAlignmentFor(abi);
+
   // Note that we flatten multi dimensional arrays.
   @override
   Constant generateConstant(FfiTransformer transformer) =>
@@ -592,14 +643,20 @@
   AbiSpecificNativeTypeCfe(this.abiSpecificTypes, this.clazz);
 
   @override
-  Map<Abi, int?> get size => abiSpecificTypes
-      .map((abi, nativeTypeCfe) => MapEntry(abi, nativeTypeCfe.size[abi]));
+  Map<Abi, int?> get size => abiSpecificTypes.map(
+      (abi, nativeTypeCfe) => MapEntry(abi, nativeTypeCfe.getSizeFor(abi)));
+
+  @override
+  int? getSizeFor(Abi abi) => abiSpecificTypes[abi]?.getSizeFor(abi);
 
   @override
   Map<Abi, int?> get alignment => abiSpecificTypes
       .map((abi, nativeTypeCfe) => MapEntry(abi, nativeTypeCfe.alignment[abi]));
 
   @override
+  int? getAlignmentFor(Abi abi) => abiSpecificTypes[abi]?.getAlignmentFor(abi);
+
+  @override
   Constant generateConstant(FfiTransformer transformer) =>
       TypeLiteralConstant(InterfaceType(clazz, Nullability.nonNullable));
 
diff --git a/pkg/vm/lib/transformations/ffi/use_sites.dart b/pkg/vm/lib/transformations/ffi/use_sites.dart
index d0e44333..ba1a0b1 100644
--- a/pkg/vm/lib/transformations/ffi/use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi/use_sites.dart
@@ -169,15 +169,24 @@
           fileOffset: node.fileOffset,
         );
       }
-      if (target == structPointerRef ||
-          target == structPointerElemAt ||
-          target == unionPointerRef ||
-          target == unionPointerElemAt) {
+      if (target == structPointerGetRef ||
+          target == structPointerGetElemAt ||
+          target == unionPointerGetRef ||
+          target == unionPointerGetElemAt) {
         final DartType nativeType = node.arguments.types[0];
 
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
 
-        return _replaceRef(node);
+        return _replaceGetRef(node);
+      } else if (target == structPointerSetRef ||
+          target == structPointerSetElemAt ||
+          target == unionPointerSetRef ||
+          target == unionPointerSetElemAt) {
+        final DartType nativeType = node.arguments.types[0];
+
+        _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
+
+        return _replaceSetRef(node);
       } else if (target == structArrayElemAt || target == unionArrayElemAt) {
         final DartType nativeType = node.arguments.types[0];
 
@@ -533,7 +542,7 @@
     return StaticGet(field);
   }
 
-  Expression _replaceRef(StaticInvocation node) {
+  Expression _replaceGetRef(StaticInvocation node) {
     final dartType = node.arguments.types[0];
     final clazz = (dartType as InterfaceType).classNode;
     final constructor = clazz.constructors
@@ -555,6 +564,38 @@
     return ConstructorInvocation(constructor, Arguments([pointer]));
   }
 
+  /// Replaces a `.ref=` or `[]=` on a compound pointer extension with a memcopy
+  /// call.
+  Expression _replaceSetRef(StaticInvocation node) {
+    final target = node.arguments.positional[0]; // Receiver of extension
+
+    final Expression source, targetOffset;
+
+    if (node.arguments.positional.length == 3) {
+      // []= call, args are (receiver, index, source)
+      source = getCompoundTypedDataBaseField(
+          node.arguments.positional[2], node.fileOffset);
+      targetOffset = multiply(node.arguments.positional[1],
+          _inlineSizeOf(node.arguments.types[0] as InterfaceType)!);
+    } else {
+      // .ref= call, args are (receiver, source)
+      source = getCompoundTypedDataBaseField(
+          node.arguments.positional[1], node.fileOffset);
+      targetOffset = ConstantExpression(IntConstant(0));
+    }
+
+    return StaticInvocation(
+      memCopy,
+      Arguments([
+        target,
+        targetOffset,
+        source,
+        ConstantExpression(IntConstant(0)),
+        _inlineSizeOf(node.arguments.types[0] as InterfaceType)!,
+      ]),
+    );
+  }
+
   Expression _replaceRefArray(StaticInvocation node) {
     final dartType = node.arguments.types[0];
     final clazz = (dartType as InterfaceType).classNode;
diff --git a/pkg/vm/lib/transformations/to_string_transformer.dart b/pkg/vm/lib/transformations/to_string_transformer.dart
index 0cd1b5f..824282d 100644
--- a/pkg/vm/lib/transformations/to_string_transformer.dart
+++ b/pkg/vm/lib/transformations/to_string_transformer.dart
@@ -19,6 +19,8 @@
   /// 'package:flutter/foundation.dart'.
   final Set<String> _packageUris;
 
+  final Map<Class, bool> _inheritedKeepAnnotations = {};
+
   /// Turn 'dart:ui' into 'dart:ui', or
   /// 'package:flutter/src/semantics_event.dart' into 'package:flutter'.
   String _importUriToPackage(Uri importUri) =>
@@ -29,7 +31,18 @@
         .contains(_importUriToPackage(node.enclosingLibrary.importUri));
   }
 
-  bool _hasKeepAnnotation(Procedure node) {
+  bool _hasKeepAnnotation(Procedure node) =>
+      _hasPragma(node, 'flutter:keep-to-string');
+
+  bool _hasKeepAnnotationOnClass(Class node) =>
+      _hasPragma(node, 'flutter:keep-to-string-in-subtypes');
+
+  bool _hasInheritedKeepAnnotation(Class node) =>
+      _inheritedKeepAnnotations[node] ??= (_hasKeepAnnotationOnClass(node) ||
+          node.supers
+              .any((Supertype t) => _hasInheritedKeepAnnotation(t.classNode)));
+
+  bool _hasPragma(Annotatable node, String pragma) {
     for (ConstantExpression expression
         in node.annotations.whereType<ConstantExpression>()) {
       if (expression.constant is! InstanceConstant) {
@@ -43,8 +56,7 @@
         for (var fieldRef in constant.fieldValues.keys) {
           if (fieldRef.asField.name.text == 'name') {
             Constant? name = constant.fieldValues[fieldRef];
-            return name is StringConstant &&
-                name.value == 'flutter:keep-to-string';
+            return name is StringConstant && name.value == pragma;
           }
         }
         return false;
@@ -61,7 +73,8 @@
         !node.isAbstract &&
         !node.enclosingClass!.isEnum &&
         _isInTargetPackage(node) &&
-        !_hasKeepAnnotation(node)) {
+        !_hasKeepAnnotation(node) &&
+        !_hasInheritedKeepAnnotation(node.enclosingClass!)) {
       node.function.body!.replaceWith(
         ReturnStatement(
           SuperMethodInvocation(
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index d82925a..6533e54 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1583,12 +1583,22 @@
     if (_isExtendedBoolLiteral(condition)) {
       final bool value = _getExtendedBoolLiteralValue(condition);
       final Expression expr = transform(value ? node.then : node.otherwise);
+      Expression result;
       if (condition is BlockExpression) {
         condition.value = expr;
         expr.parent = condition;
-        return condition;
+        result = condition;
       } else {
-        return expr;
+        result = expr;
+      }
+      if (node.staticType != result.getStaticType(staticTypeContext)) {
+        return StaticInvocation(
+            unsafeCast,
+            Arguments([result],
+                types: [visitDartType(node.staticType, cannotRemoveSentinel)]))
+          ..fileOffset = node.fileOffset;
+      } else {
+        return result;
       }
     }
     node.condition = condition..parent = node;
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 62a66f4..056d540 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -1688,6 +1688,15 @@
 
   /// Retrieves the ID of the main isolate using the service protocol.
   Future<String> _computeMainId() async {
+    var completer = new Completer<String>();
+    rpc.registerMethod('streamNotify', (response) {
+      if (response['streamId'] == 'Isolate') return;
+      var event = response['event'];
+      if (event['kind'] != 'IsolateStart') return;
+      var isolate = event['isolate'];
+      completer.complete(isolate['id']);
+    });
+    await rpc.sendRequest('streamListen', {'streamId': 'Isolate'});
     var vm = await rpc.sendRequest('getVM', {});
     var isolates = vm['isolates'];
     for (var isolate in isolates) {
@@ -1695,7 +1704,10 @@
         return isolate['id'];
       }
     }
-    return isolates.first['id'];
+    for (var isolate in isolates) {
+      return isolate['id'];
+    }
+    return completer.future;
   }
 
   /// Send a request to the VM to reload sources from [entryUri].
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 090a08d..8e05c6c 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -28,7 +28,7 @@
   final Uri packagesFile = sdkRootFile('.packages');
   final Uri librariesFile = sdkRootFile('sdk/lib/libraries.json');
 
-  final vmTarget = VmTarget(TargetFlags());
+  final vmTarget = VmTarget(TargetFlags(supportMirrors: false));
 
   await withTempDirectory((Uri uri) async {
     final mixinFilename = uri.resolve('mixin.dart');
diff --git a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
index 4febdf9..cf616ed 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -71,7 +71,7 @@
 }
 
 Future<void> compileAOT(Uri source) async {
-  final target = TestingVmTarget(TargetFlags());
+  final target = TestingVmTarget(TargetFlags(supportMirrors: false));
   Component component =
       await compileTestCaseToKernelProgram(source, target: target);
 
diff --git a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
index 50266bd..c3ff180 100644
--- a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
+++ b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
@@ -18,6 +18,8 @@
   Abi.linuxArm64: Uint32(),
   Abi.linuxIA32: Uint32(),
   Abi.linuxX64: Uint32(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint32(),
   Abi.macosArm64: Uint32(),
   Abi.macosX64: Uint32(),
   Abi.windowsArm64: Uint16(),
diff --git a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
index d8ba7e5..63b991b 100644
--- a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
@@ -7,17 +7,17 @@
 
 import "dart:ffi";
 
-@#C49
-@#C56
+@#C55
+@#C62
 class WChar extends ffi::AbiSpecificInteger /*hasConstConstructor*/  {
   const constructor •() → self::WChar
     : super ffi::AbiSpecificInteger::•()
     ;
-  @#C59
+  @#C65
   static get #sizeOf() → core::int*
-    return #C61.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
-@#C66
+@#C72
 class WCharStruct extends ffi::Struct {
   synthetic constructor •() → self::WCharStruct
     : super ffi::Struct::•()
@@ -25,23 +25,23 @@
   constructor #fromTypedDataBase(core::Object #typedDataBase) → self::WCharStruct
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-  @#C67
+  @#C73
   get a0() → core::int
-    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C68.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C67
+    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C73
   set a0(core::int #externalFieldValue) → void
-    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C68.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
-  @#C67
+    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  @#C73
   get a1() → core::int
-    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C61.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C67
+    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C73
   set a1(core::int #externalFieldValue) → void
-    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C61.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
-  @#C59
+    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  @#C65
   static get #sizeOf() → core::int*
-    return #C70.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
-@#C75
+@#C81
 class WCharArrayStruct extends ffi::Struct {
   synthetic constructor •() → self::WCharArrayStruct
     : super ffi::Struct::•()
@@ -49,31 +49,31 @@
   constructor #fromTypedDataBase(core::Object #typedDataBase) → self::WCharArrayStruct
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-  @#C76
+  @#C82
   get a0() → ffi::Array<self::WChar>
     return new ffi::Array::_<self::WChar>( block {
       core::Object #typedDataBase = this.{ffi::_Compound::_typedDataBase}{core::Object};
-      core::int #offset = #C68.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
-    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} ffi::_fromAddress<self::WChar>(#typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}(#typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, #C80.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List}, #C71, #C81);
-  @#C76
+      core::int #offset = #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} ffi::_fromAddress<self::WChar>(#typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}(#typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List}, #C77, #C87);
+  @#C82
   set a0(ffi::Array<self::WChar> #externalFieldValue) → void
-    return ffi::_memCopy(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C68.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Array::_typedDataBase}{core::Object}, #C1, #C80.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C59
+    return ffi::_memCopy(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Array::_typedDataBase}{core::Object}, #C1, #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C65
   static get #sizeOf() → core::int*
-    return #C80.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
 class _DummyAllocator extends core::Object implements ffi::Allocator /*hasConstConstructor*/  {
   const constructor •() → self::_DummyAllocator
     : super core::Object::•()
     ;
-  @#C82
-  method allocate<T extends ffi::NativeType>(core::int byteCount, {core::int? alignment = #C58}) → ffi::Pointer<self::_DummyAllocator::allocate::T> {
+  @#C88
+  method allocate<T extends ffi::NativeType>(core::int byteCount, {core::int? alignment = #C64}) → ffi::Pointer<self::_DummyAllocator::allocate::T> {
     return ffi::Pointer::fromAddress<self::_DummyAllocator::allocate::T>(0);
   }
-  @#C82
+  @#C88
   method free(ffi::Pointer<ffi::NativeType> pointer) → void {}
 }
-static const field self::_DummyAllocator noAlloc = #C83;
+static const field self::_DummyAllocator noAlloc = #C89;
 static method main() → void {
   self::testSizeOf();
   self::testStoreLoad();
@@ -86,29 +86,29 @@
   core::print(size);
 }
 static method testStoreLoad() → void {
-  final ffi::Pointer<self::WChar> p = #C83.{ffi::Allocator::allocate}<self::WChar>(self::WChar::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
+  final ffi::Pointer<self::WChar> p = #C89.{ffi::Allocator::allocate}<self::WChar>(self::WChar::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
   ffi::_storeAbiSpecificInt<self::WChar>(p, #C1, 10);
   core::print(ffi::_loadAbiSpecificInt<self::WChar>(p, #C1));
-  #C83.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testStoreLoadIndexed() → void {
-  final ffi::Pointer<self::WChar> p = #C83.{ffi::Allocator::allocate}<self::WChar>(2.{core::num::*}(self::WChar::#sizeOf){(core::num) → core::num}){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
+  final ffi::Pointer<self::WChar> p = #C89.{ffi::Allocator::allocate}<self::WChar>(2.{core::num::*}(self::WChar::#sizeOf){(core::num) → core::num}){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
   ffi::_storeAbiSpecificIntAtIndex<self::WChar>(p, 0, 10);
   ffi::_storeAbiSpecificIntAtIndex<self::WChar>(p, 1, 3);
   core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(p, 0));
   core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(p, 1));
-  #C83.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testStruct() → void {
-  final ffi::Pointer<self::WCharStruct> p = #C83.{ffi::Allocator::allocate}<self::WCharStruct>(self::WCharStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharStruct>};
+  final ffi::Pointer<self::WCharStruct> p = #C89.{ffi::Allocator::allocate}<self::WCharStruct>(self::WCharStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharStruct>};
   new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0} = 1;
   core::print(new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0}{core::int});
   new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0} = 2;
   core::print(new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0}{core::int});
-  #C83.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testInlineArray() → void {
-  final ffi::Pointer<self::WCharArrayStruct> p = #C83.{ffi::Allocator::allocate}<self::WCharArrayStruct>(self::WCharArrayStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharArrayStruct>};
+  final ffi::Pointer<self::WCharArrayStruct> p = #C89.{ffi::Allocator::allocate}<self::WCharArrayStruct>(self::WCharArrayStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharArrayStruct>};
   final ffi::Array<self::WChar> array = new self::WCharArrayStruct::#fromTypedDataBase(p!).{self::WCharArrayStruct::a0}{ffi::Array<self::WChar>};
   for (core::int i = 0; i.{core::num::<}(100){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
     ffi::_storeAbiSpecificIntAtIndex<self::WChar>(array.{ffi::Array::_typedDataBase}{core::Object}, i, i);
@@ -116,7 +116,7 @@
   for (core::int i = 0; i.{core::num::<}(100){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
     core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(array.{ffi::Array::_typedDataBase}{core::Object}, i));
   }
-  #C83.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 constants  {
   #C1 = 0
@@ -155,51 +155,57 @@
   #C34 = ffi::Abi {_os:#C31, _architecture:#C14}
   #C35 = ffi::Abi {_os:#C31, _architecture:#C18}
   #C36 = 4
-  #C37 = "macos"
-  #C38 = ffi::_OS {index:#C36, _name:#C37}
-  #C39 = ffi::Abi {_os:#C38, _architecture:#C10}
-  #C40 = ffi::Abi {_os:#C38, _architecture:#C18}
-  #C41 = 5
-  #C42 = "windows"
-  #C43 = ffi::_OS {index:#C41, _name:#C42}
-  #C44 = ffi::Abi {_os:#C43, _architecture:#C10}
-  #C45 = ffi::Uint16 {}
-  #C46 = ffi::Abi {_os:#C43, _architecture:#C14}
-  #C47 = ffi::Abi {_os:#C43, _architecture:#C18}
-  #C48 = <ffi::Abi*, ffi::NativeType*>{#C6:#C7, #C11:#C7, #C15:#C7, #C19:#C7, #C22:#C23, #C24:#C7, #C27:#C7, #C28:#C7, #C29:#C7, #C32:#C7, #C33:#C7, #C34:#C7, #C35:#C7, #C39:#C7, #C40:#C7, #C44:#C45, #C46:#C45, #C47:#C45)
-  #C49 = ffi::AbiSpecificIntegerMapping {mapping:#C48}
-  #C50 = "vm:ffi:abi-specific-mapping"
-  #C51 = TypeLiteralConstant(ffi::Uint32)
-  #C52 = TypeLiteralConstant(ffi::Uint64)
-  #C53 = TypeLiteralConstant(ffi::Uint16)
-  #C54 = <core::Type?>[#C51, #C51, #C51, #C51, #C52, #C51, #C51, #C51, #C51, #C51, #C51, #C51, #C51, #C51, #C51, #C53, #C53, #C53]
-  #C55 = ffi::_FfiAbiSpecificMapping {nativeTypes:#C54}
-  #C56 = core::pragma {name:#C50, options:#C55}
-  #C57 = "vm:prefer-inline"
-  #C58 = null
-  #C59 = core::pragma {name:#C57, options:#C58}
-  #C60 = 8
-  #C61 = <core::int*>[#C36, #C36, #C36, #C36, #C60, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C12, #C12, #C12]
-  #C62 = "vm:ffi:struct-fields"
-  #C63 = TypeLiteralConstant(self::WChar)
-  #C64 = <core::Type>[#C63, #C63]
-  #C65 = ffi::_FfiStructLayout {fieldTypes:#C64, packing:#C58}
-  #C66 = core::pragma {name:#C62, options:#C65}
-  #C67 = self::WChar {}
-  #C68 = <core::int*>[#C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1]
-  #C69 = 16
-  #C70 = <core::int*>[#C60, #C60, #C60, #C60, #C69, #C60, #C60, #C60, #C60, #C60, #C60, #C60, #C60, #C60, #C60, #C36, #C36, #C36]
-  #C71 = 100
-  #C72 = ffi::_FfiInlineArray {elementType:#C63, length:#C71}
-  #C73 = <core::Type>[#C72]
-  #C74 = ffi::_FfiStructLayout {fieldTypes:#C73, packing:#C58}
-  #C75 = core::pragma {name:#C62, options:#C74}
-  #C76 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C71, dimension2:#C58, dimension3:#C58, dimension4:#C58, dimension5:#C58, dimensions:#C58}
-  #C77 = 400
-  #C78 = 800
-  #C79 = 200
-  #C80 = <core::int*>[#C77, #C77, #C77, #C77, #C78, #C77, #C77, #C77, #C77, #C77, #C77, #C77, #C77, #C77, #C77, #C79, #C79, #C79]
-  #C81 = <core::int*>[]
-  #C82 = core::_Override {}
-  #C83 = self::_DummyAllocator {}
+  #C37 = "riscv32"
+  #C38 = ffi::_Architecture {index:#C36, _name:#C37}
+  #C39 = ffi::Abi {_os:#C31, _architecture:#C38}
+  #C40 = 5
+  #C41 = "riscv64"
+  #C42 = ffi::_Architecture {index:#C40, _name:#C41}
+  #C43 = ffi::Abi {_os:#C31, _architecture:#C42}
+  #C44 = "macos"
+  #C45 = ffi::_OS {index:#C36, _name:#C44}
+  #C46 = ffi::Abi {_os:#C45, _architecture:#C10}
+  #C47 = ffi::Abi {_os:#C45, _architecture:#C18}
+  #C48 = "windows"
+  #C49 = ffi::_OS {index:#C40, _name:#C48}
+  #C50 = ffi::Abi {_os:#C49, _architecture:#C10}
+  #C51 = ffi::Uint16 {}
+  #C52 = ffi::Abi {_os:#C49, _architecture:#C14}
+  #C53 = ffi::Abi {_os:#C49, _architecture:#C18}
+  #C54 = <ffi::Abi*, ffi::NativeType*>{#C6:#C7, #C11:#C7, #C15:#C7, #C19:#C7, #C22:#C23, #C24:#C7, #C27:#C7, #C28:#C7, #C29:#C7, #C32:#C7, #C33:#C7, #C34:#C7, #C35:#C7, #C39:#C7, #C43:#C7, #C46:#C7, #C47:#C7, #C50:#C51, #C52:#C51, #C53:#C51)
+  #C55 = ffi::AbiSpecificIntegerMapping {mapping:#C54}
+  #C56 = "vm:ffi:abi-specific-mapping"
+  #C57 = TypeLiteralConstant(ffi::Uint32)
+  #C58 = TypeLiteralConstant(ffi::Uint64)
+  #C59 = TypeLiteralConstant(ffi::Uint16)
+  #C60 = <core::Type?>[#C57, #C57, #C57, #C57, #C58, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C59, #C59, #C59]
+  #C61 = ffi::_FfiAbiSpecificMapping {nativeTypes:#C60}
+  #C62 = core::pragma {name:#C56, options:#C61}
+  #C63 = "vm:prefer-inline"
+  #C64 = null
+  #C65 = core::pragma {name:#C63, options:#C64}
+  #C66 = 8
+  #C67 = <core::int*>[#C36, #C36, #C36, #C36, #C66, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C12, #C12, #C12]
+  #C68 = "vm:ffi:struct-fields"
+  #C69 = TypeLiteralConstant(self::WChar)
+  #C70 = <core::Type>[#C69, #C69]
+  #C71 = ffi::_FfiStructLayout {fieldTypes:#C70, packing:#C64}
+  #C72 = core::pragma {name:#C68, options:#C71}
+  #C73 = self::WChar {}
+  #C74 = <core::int*>[#C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1]
+  #C75 = 16
+  #C76 = <core::int*>[#C66, #C66, #C66, #C66, #C75, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C36, #C36, #C36]
+  #C77 = 100
+  #C78 = ffi::_FfiInlineArray {elementType:#C69, length:#C77}
+  #C79 = <core::Type>[#C78]
+  #C80 = ffi::_FfiStructLayout {fieldTypes:#C79, packing:#C64}
+  #C81 = core::pragma {name:#C68, options:#C80}
+  #C82 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C77, dimension2:#C64, dimension3:#C64, dimension4:#C64, dimension5:#C64, dimensions:#C64}
+  #C83 = 400
+  #C84 = 800
+  #C85 = 200
+  #C86 = <core::int*>[#C83, #C83, #C83, #C83, #C84, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C85, #C85, #C85]
+  #C87 = <core::int*>[]
+  #C88 = core::_Override {}
+  #C89 = self::_DummyAllocator {}
 }
diff --git a/pkg/vm/testcases/transformations/ffi/abi_specific_int_incomplete.dart.expect b/pkg/vm/testcases/transformations/ffi/abi_specific_int_incomplete.dart.expect
index 2acfbf6..306f413 100644
--- a/pkg/vm/testcases/transformations/ffi/abi_specific_int_incomplete.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/abi_specific_int_incomplete.dart.expect
@@ -143,22 +143,22 @@
   #C22 = "vm:ffi:abi-specific-mapping"
   #C23 = null
   #C24 = TypeLiteralConstant(ffi::Uint32)
-  #C25 = <core::Type?>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C24, #C24, #C24, #C24, #C23, #C23, #C23, #C23, #C23]
+  #C25 = <core::Type?>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C24, #C24, #C24, #C24, #C23, #C23, #C23, #C23, #C23, #C23, #C23]
   #C26 = ffi::_FfiAbiSpecificMapping {nativeTypes:#C25}
   #C27 = core::pragma {name:#C22, options:#C26}
   #C28 = "vm:prefer-inline"
   #C29 = core::pragma {name:#C28, options:#C23}
   #C30 = 4
-  #C31 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C30, #C30, #C30, #C30, #C23, #C23, #C23, #C23, #C23]
+  #C31 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C30, #C30, #C30, #C30, #C23, #C23, #C23, #C23, #C23, #C23, #C23]
   #C32 = "vm:ffi:struct-fields"
   #C33 = TypeLiteralConstant(self::Incomplete)
   #C34 = <core::Type>[#C33, #C33]
   #C35 = ffi::_FfiStructLayout {fieldTypes:#C34, packing:#C23}
   #C36 = core::pragma {name:#C32, options:#C35}
   #C37 = self::Incomplete {}
-  #C38 = <core::int*>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+  #C38 = <core::int*>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
   #C39 = 8
-  #C40 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C39, #C39, #C39, #C39, #C23, #C23, #C23, #C23, #C23]
+  #C40 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C39, #C39, #C39, #C39, #C23, #C23, #C23, #C23, #C23, #C23, #C23]
   #C41 = 100
   #C42 = ffi::_FfiInlineArray {elementType:#C33, length:#C41}
   #C43 = <core::Type>[#C42]
@@ -166,7 +166,7 @@
   #C45 = core::pragma {name:#C32, options:#C44}
   #C46 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C41, dimension2:#C23, dimension3:#C23, dimension4:#C23, dimension5:#C23, dimensions:#C23}
   #C47 = 400
-  #C48 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C47, #C47, #C47, #C47, #C23, #C23, #C23, #C23, #C23]
+  #C48 = <core::int*>[#C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C23, #C47, #C47, #C47, #C47, #C23, #C23, #C23, #C23, #C23, #C23, #C23]
   #C49 = <core::int*>[]
   #C50 = core::_Override {}
   #C51 = self::_DummyAllocator {}
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
new file mode 100644
index 0000000..4717b9b
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
@@ -0,0 +1,27 @@
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+
+class Coordinate extends Struct {
+  @Int64()
+  external int x;
+
+  @Int64()
+  external int y;
+
+  void copyInto(Pointer<Coordinate> ptr) {
+    ptr.ref = this;
+  }
+}
+
+class SomeUnion extends Union {
+  external Coordinate coordinate;
+  @Int64()
+  external int id;
+
+  void copyIntoAtIndex(Pointer<SomeUnion> ptr, int index) {
+    ptr[index] = this;
+  }
+}
+
+void main() {}
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
new file mode 100644
index 0000000..b1fe1cf
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
@@ -0,0 +1,87 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:typed_data" as typ;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+@#C6
+class Coordinate extends ffi::Struct {
+  synthetic constructor •() → self::Coordinate
+    : super ffi::Struct::•()
+    ;
+  constructor #fromTypedDataBase(core::Object #typedDataBase) → self::Coordinate
+    : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
+    ;
+  @#C7
+  get x() → core::int
+    return ffi::_loadInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C7
+  set x(core::int #externalFieldValue) → void
+    return ffi::_storeInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  @#C7
+  get y() → core::int
+    return ffi::_loadInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C11.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C7
+  set y(core::int #externalFieldValue) → void
+    return ffi::_storeInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C11.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  method copyInto(ffi::Pointer<self::Coordinate> ptr) → void {
+    ffi::_memCopy(ptr, #C8, this.{ffi::_Compound::_typedDataBase}{core::Object}, #C8, self::Coordinate::#sizeOf);
+  }
+  @#C13
+  static get #sizeOf() → core::int*
+    return #C15.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+}
+@#C19
+class SomeUnion extends ffi::Union {
+  synthetic constructor •() → self::SomeUnion
+    : super ffi::Union::•()
+    ;
+  constructor #fromTypedDataBase(core::Object #typedDataBase) → self::SomeUnion
+    : super ffi::Union::_fromTypedDataBase(#typedDataBase)
+    ;
+  get coordinate() → self::Coordinate
+    return new self::Coordinate::#fromTypedDataBase( block {
+      core::Object #typedDataBase = this.{ffi::_Compound::_typedDataBase}{core::Object};
+      core::int #offset = #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} ffi::_fromAddress<self::Coordinate>(#typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}(#typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, #C15.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List});
+  set coordinate(self::Coordinate #externalFieldValue) → void
+    return ffi::_memCopy(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::_Compound::_typedDataBase}{core::Object}, #C8, #C15.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C7
+  get id() → core::int
+    return ffi::_loadInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C7
+  set id(core::int #externalFieldValue) → void
+    return ffi::_storeInt64(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C9.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  method copyIntoAtIndex(ffi::Pointer<self::SomeUnion> ptr, core::int index) → void {
+    ffi::_memCopy(ptr, index.{core::num::*}(self::SomeUnion::#sizeOf){(core::num) → core::num}, this.{ffi::_Compound::_typedDataBase}{core::Object}, #C8, self::SomeUnion::#sizeOf);
+  }
+  @#C13
+  static get #sizeOf() → core::int*
+    return #C15.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+}
+static method main() → void {}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(ffi::Int64)
+  #C3 = <core::Type>[#C2, #C2]
+  #C4 = null
+  #C5 = ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
+  #C6 = core::pragma {name:#C1, options:#C5}
+  #C7 = ffi::Int64 {}
+  #C8 = 0
+  #C9 = <core::int*>[#C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8, #C8]
+  #C10 = 8
+  #C11 = <core::int*>[#C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10, #C10]
+  #C12 = "vm:prefer-inline"
+  #C13 = core::pragma {name:#C12, options:#C4}
+  #C14 = 16
+  #C15 = <core::int*>[#C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14, #C14]
+  #C16 = TypeLiteralConstant(self::Coordinate)
+  #C17 = <core::Type>[#C16, #C2]
+  #C18 = ffi::_FfiStructLayout {fieldTypes:#C17, packing:#C4}
+  #C19 = core::pragma {name:#C1, options:#C18}
+}
diff --git a/pkg/vm/testcases/transformations/to_string_transformer/lib/main.dart b/pkg/vm/testcases/transformations/to_string_transformer/lib/main.dart
index 96544f2..aa53235 100644
--- a/pkg/vm/testcases/transformations/to_string_transformer/lib/main.dart
+++ b/pkg/vm/testcases/transformations/to_string_transformer/lib/main.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 
 const keepToString = pragma('flutter:keep-to-string');
+const keepToStringInSubtypes = pragma('flutter:keep-to-string-in-subtypes');
 
 String toString() => 'I am static';
 
@@ -26,9 +27,28 @@
   String toString() => 'I am a Keep';
 }
 
+@keepToStringInSubtypes
+class Base1 {}
+
+class Base2 extends Base1 {}
+
+class Base3 extends Object with Base2 {}
+
+class KeepInherited implements Base3 {
+  @override
+  String toString() => 'Heir';
+}
+
+class MyException implements Exception {
+  @override
+  String toString() => 'A very detailed message';
+}
+
 void main() {
   final IFoo foo = Foo();
   print(foo.toString());
   print(Keep().toString());
   print(FooEnum.B.toString());
+  print(KeepInherited().toString());
+  print(MyException().toString());
 }
diff --git a/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect b/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
index 29c959a..6d48b41 100644
--- a/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
+++ b/pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect
@@ -39,7 +39,45 @@
   method toString() → core::String
     return "I am a Keep";
 }
+@#C16
+class Base1 extends core::Object {
+  synthetic constructor •() → self::Base1
+    : super core::Object::•()
+    ;
+}
+class Base2 extends self::Base1 {
+  synthetic constructor •() → self::Base2
+    : super self::Base1::•()
+    ;
+}
+abstract class _Base3&Object&Base2 extends core::Object implements self::Base2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_Base3&Object&Base2
+    : super core::Object::•()
+    ;
+}
+class Base3 extends self::_Base3&Object&Base2 {
+  synthetic constructor •() → self::Base3
+    : super self::_Base3&Object&Base2::•()
+    ;
+}
+class KeepInherited extends core::Object implements self::Base3 {
+  synthetic constructor •() → self::KeepInherited
+    : super core::Object::•()
+    ;
+  @#C1
+  method toString() → core::String
+    return "Heir";
+}
+class MyException extends core::Object implements core::Exception {
+  synthetic constructor •() → self::MyException
+    : super core::Object::•()
+    ;
+  @#C1
+  method toString() → core::String
+    return "A very detailed message";
+}
 static const field core::pragma keepToString = #C14;
+static const field core::pragma keepToStringInSubtypes = #C16;
 static method toString() → core::String
   return "I am static";
 static method main() → void {
@@ -47,6 +85,8 @@
   core::print(foo.{self::IFoo::toString}(){() → core::String});
   core::print(new self::Keep::•().{self::Keep::toString}(){() → core::String});
   core::print(#C7.{self::FooEnum::toString}(){() → core::String});
+  core::print(new self::KeepInherited::•().{self::KeepInherited::toString}(){() → core::String});
+  core::print(new self::MyException::•().{self::MyException::toString}(){() → core::String});
 }
 constants  {
   #C1 = core::_Override {}
@@ -63,4 +103,6 @@
   #C12 = "flutter:keep-to-string"
   #C13 = null
   #C14 = core::pragma {name:#C12, options:#C13}
+  #C15 = "flutter:keep-to-string-in-subtypes"
+  #C16 = core::pragma {name:#C15, options:#C13}
 }
diff --git a/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect b/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
index dca5efb..75d87ae 100644
--- a/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
+++ b/pkg/vm/testcases/transformations/to_string_transformer/transformed.expect
@@ -39,7 +39,45 @@
   method toString() → core::String
     return "I am a Keep";
 }
+@#C16
+class Base1 extends core::Object {
+  synthetic constructor •() → self::Base1
+    : super core::Object::•()
+    ;
+}
+class Base2 extends self::Base1 {
+  synthetic constructor •() → self::Base2
+    : super self::Base1::•()
+    ;
+}
+abstract class _Base3&Object&Base2 extends core::Object implements self::Base2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_Base3&Object&Base2
+    : super core::Object::•()
+    ;
+}
+class Base3 extends self::_Base3&Object&Base2 {
+  synthetic constructor •() → self::Base3
+    : super self::_Base3&Object&Base2::•()
+    ;
+}
+class KeepInherited extends core::Object implements self::Base3 {
+  synthetic constructor •() → self::KeepInherited
+    : super core::Object::•()
+    ;
+  @#C1
+  method toString() → core::String
+    return "Heir";
+}
+class MyException extends core::Object implements core::Exception {
+  synthetic constructor •() → self::MyException
+    : super core::Object::•()
+    ;
+  @#C1
+  method toString() → core::String
+    return "A very detailed message";
+}
 static const field core::pragma keepToString = #C14;
+static const field core::pragma keepToStringInSubtypes = #C16;
 static method toString() → core::String
   return "I am static";
 static method main() → void {
@@ -47,6 +85,8 @@
   core::print(foo.{self::IFoo::toString}(){() → core::String});
   core::print(new self::Keep::•().{self::Keep::toString}(){() → core::String});
   core::print(#C7.{self::FooEnum::toString}(){() → core::String});
+  core::print(new self::KeepInherited::•().{self::KeepInherited::toString}(){() → core::String});
+  core::print(new self::MyException::•().{self::MyException::toString}(){() → core::String});
 }
 constants  {
   #C1 = core::_Override {}
@@ -63,4 +103,6 @@
   #C12 = "flutter:keep-to-string"
   #C13 = null
   #C14 = core::pragma {name:#C12, options:#C13}
+  #C15 = "flutter:keep-to-string-in-subtypes"
+  #C16 = core::pragma {name:#C15, options:#C13}
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index aca8022..1443d95 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3380,getterSelectorId:3381]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3384,getterSelectorId:3385]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
index c2c6faa..5927788 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
@@ -128,10 +128,10 @@
   #C9 = ffi::_FfiStructLayout {fieldTypes:#C8, packing:#C4}
   #C10 = core::pragma {name:#C1, options:#C9}
   #C11 = 0
-  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
+  #C12 = <core::int*>[#C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11, #C11]
   #C13 = 4
   #C14 = 8
-  #C15 = <core::int*>[#C13, #C14, #C13, #C14, #C14, #C14, #C13, #C14, #C14, #C13, #C14, #C13, #C14, #C14, #C14, #C14, #C13, #C14]
+  #C15 = <core::int*>[#C13, #C14, #C13, #C14, #C14, #C14, #C13, #C14, #C14, #C13, #C14, #C13, #C14, #C13, #C14, #C14, #C14, #C14, #C13, #C14]
   #C16 = static-tearoff self::useStruct3
   #C17 = static-tearoff self::returnStruct7
   #C18 = 1
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart
new file mode 100644
index 0000000..47a6a15
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests elimination of null test in a conditional expression of
+// a different static type.
+
+bool _defaultCheck([dynamic _]) => true;
+
+void testStaticTypeOfConditional<T>(bool Function(T error)? check, Object e) {
+  // Verify that null test elimination leaves unsafeCast here to
+  // keep static type of 'check ?? _defaultCheck' expression.
+  if (e is T && (check ?? _defaultCheck)(e)) {
+    print('ok');
+  }
+}
+
+void main() {
+  testStaticTypeOfConditional<String>((_) => true, 'hi');
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart.expect
new file mode 100644
index 0000000..de2490b
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination2_nnbd_strong.dart.expect
@@ -0,0 +1,19 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method _defaultCheck([dynamic _ = #C1]) → core::bool
+  return true;
+static method testStaticTypeOfConditional<T extends core::Object? = dynamic>([@vm.inferred-type.metadata=!] (self::testStaticTypeOfConditional::T%) →? core::bool check) → void {
+  if(#C2 is{ForNonNullableByDefault} self::testStaticTypeOfConditional::T% && (let final (self::testStaticTypeOfConditional::T%) →? core::bool #t1 = check in _in::unsafeCast<core::Function>(#t1{(self::testStaticTypeOfConditional::T%) → core::bool}))(#C2) as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool) {
+    core::print("ok");
+  }
+}
+static method main() → void {
+  self::testStaticTypeOfConditional<core::String>((core::String _) → core::bool => true);
+}
+constants  {
+  #C1 = null
+  #C2 = "hi"
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index 446a1e7..c16c8ac 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
   synthetic constructor •() → self::ConstClass
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3384,getterSelectorId:3385]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3388,getterSelectorId:3389]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index 4203e7a..ba91b27 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -56,7 +56,7 @@
   new self::A::•();
   new self::B::•();
   self::C<core::num> c = new self::D::•();
-  exp::Expect::throws<dynamic>(() → void {
+  exp::Expect::throws<core::Object>(() → void {
     [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num>] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
   });
   self::E e = new self::F::•();
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index e096691..1d09a57 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## 8.2.0-dev
+- Update to version `3.56` of the spec.
+- Added optional `line` and `column` properties to `SourceLocation`.
+- Added a new `SourceReportKind`, `BranchCoverage`, which reports branch level
+  coverage information.
+
 ## 8.1.0
 - Update to version `3.55` of the spec.
 - Added `streamCpuSamplesWithUserTag` RPC.
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index aa1b7c7..2955af8 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -230,6 +230,7 @@
 }
 
 String assertSourceReportKind(String obj) {
+  if (obj == "BranchCoverage") return obj;
   if (obj == "Coverage") return obj;
   if (obj == "PossibleBreakpoints") return obj;
   throw "invalid SourceReportKind: $obj";
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index e465dc5..1c8ad22 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.55
+version=3.56
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 968a41f..4905a0d 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
         HeapSnapshotObjectNoData,
         HeapSnapshotObjectNullData;
 
-const String vmServiceVersion = '3.55.0';
+const String vmServiceVersion = '3.56.0';
 
 /// @optional
 const String optional = 'optional';
@@ -2776,6 +2776,9 @@
 
   /// Used to request a list of token positions of possible breakpoints.
   static const String kPossibleBreakpoints = 'PossibleBreakpoints';
+
+  /// Used to request branch coverage information.
+  static const String kBranchCoverage = 'BranchCoverage';
 }
 
 /// An `ExceptionPauseMode` indicates how the isolate pauses when an exception
@@ -7417,10 +7420,22 @@
   @optional
   int? endTokenPos;
 
+  /// The line associated with this location. Only provided for non-synthetic
+  /// token positions.
+  @optional
+  int? line;
+
+  /// The column associated with this location. Only provided for non-synthetic
+  /// token positions.
+  @optional
+  int? column;
+
   SourceLocation({
     required this.script,
     required this.tokenPos,
     this.endTokenPos,
+    this.line,
+    this.column,
   });
 
   SourceLocation._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
@@ -7428,6 +7443,8 @@
         createServiceObject(json['script'], const ['ScriptRef']) as ScriptRef?;
     tokenPos = json['tokenPos'] ?? -1;
     endTokenPos = json['endTokenPos'];
+    line = json['line'];
+    column = json['column'];
   }
 
   @override
@@ -7442,6 +7459,8 @@
       'tokenPos': tokenPos,
     });
     _setIfNotNull(json, 'endTokenPos', endTokenPos);
+    _setIfNotNull(json, 'line', line);
+    _setIfNotNull(json, 'column', column);
     return json;
   }
 
@@ -7578,6 +7597,11 @@
   @optional
   List<int>? possibleBreakpoints;
 
+  /// Branch coverage information for this range.  Provided only when the
+  /// BranchCoverage report has been requested and the range has been compiled.
+  @optional
+  SourceReportCoverage? branchCoverage;
+
   SourceReportRange({
     required this.scriptIndex,
     required this.startPos,
@@ -7586,6 +7610,7 @@
     this.error,
     this.coverage,
     this.possibleBreakpoints,
+    this.branchCoverage,
   });
 
   SourceReportRange._fromJson(Map<String, dynamic> json) {
@@ -7599,6 +7624,9 @@
     possibleBreakpoints = json['possibleBreakpoints'] == null
         ? null
         : List<int>.from(json['possibleBreakpoints']);
+    branchCoverage = createServiceObject(
+            json['branchCoverage'], const ['SourceReportCoverage'])
+        as SourceReportCoverage?;
   }
 
   Map<String, dynamic> toJson() {
@@ -7613,6 +7641,7 @@
     _setIfNotNull(json, 'coverage', coverage?.toJson());
     _setIfNotNull(json, 'possibleBreakpoints',
         possibleBreakpoints?.map((f) => f).toList());
+    _setIfNotNull(json, 'branchCoverage', branchCoverage?.toJson());
     return json;
   }
 
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index a01b273..99c5e18 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
   A library to communicate with a service implementing the Dart VM
   service protocol.
 
-version: 8.1.0
+version: 8.2.0-dev
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/pkg/vm_service/test/add_breakpoint_rpc_kernel_test.dart b/pkg/vm_service/test/add_breakpoint_rpc_kernel_test.dart
index bead75c..0fa939b 100644
--- a/pkg/vm_service/test/add_breakpoint_rpc_kernel_test.dart
+++ b/pkg/vm_service/test/add_breakpoint_rpc_kernel_test.dart
@@ -71,13 +71,17 @@
     expect(futureBpt1.resolved, isTrue);
     expect(script.getLineNumberFromTokenPos(futureBpt1.location!.tokenPos!),
         LINE_A);
+    expect(futureBpt1.location!.line, LINE_A);
     expect(
         script.getColumnNumberFromTokenPos(futureBpt1.location!.tokenPos!), 12);
+    expect(futureBpt1.location!.column, 12);
     expect(futureBpt2.resolved, isTrue);
     expect(script.getLineNumberFromTokenPos(futureBpt2.location!.tokenPos!),
         LINE_A);
+    expect(futureBpt2.location!.line, LINE_A);
     expect(
         script.getColumnNumberFromTokenPos(futureBpt2.location!.tokenPos!), 3);
+    expect(futureBpt2.location!.column, 3);
 
     // The first breakpoint hits before value is modified.
     InstanceRef result =
@@ -121,13 +125,19 @@
       print('$LINE_A:${col} -> ${resolvedLine}:${resolvedCol}');
       if (col <= 12) {
         expect(resolvedLine, LINE_A);
+        expect(bpt.location!.line, LINE_A);
         expect(resolvedCol, 3);
+        expect(bpt.location!.column, 3);
       } else if (col <= 36) {
         expect(resolvedLine, LINE_A);
+        expect(bpt.location!.line, LINE_A);
         expect(resolvedCol, 12);
+        expect(bpt.location!.column, 12);
       } else {
         expect(resolvedLine, LINE_B);
+        expect(bpt.location!.line, LINE_B);
         expect(resolvedCol, 12);
+        expect(bpt.location!.column, 12);
       }
       expect(
           (await service.removeBreakpoint(isolateId, bpt.id!)).type, 'Success');
diff --git a/pkg/vm_service/test/branch_coverage_test.dart b/pkg/vm_service/test/branch_coverage_test.dart
new file mode 100644
index 0000000..03b790d
--- /dev/null
+++ b/pkg/vm_service/test/branch_coverage_test.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+int ifTest(x) {
+  if (x > 0) {
+    if (x > 10) {
+      return 10;
+    } else {
+      return 1;
+    }
+  } else {
+    return 0;
+  }
+}
+
+void testFunction() {
+  debugger();
+  ifTest(1);
+  debugger();
+}
+
+bool allRangesCompiled(coverage) {
+  for (int i = 0; i < coverage['ranges'].length; i++) {
+    if (!coverage['ranges'][i]['compiled']) {
+      return false;
+    }
+  }
+  return true;
+}
+
+IsolateTest coverageTest(
+  Map<String, dynamic> expectedRange, {
+  required bool reportLines,
+}) {
+  return (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
+
+    // Make sure we are in the right place.
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+    expect(stack.frames![0].function!.name, 'testFunction');
+
+    final root =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final funcRef = root.functions!.singleWhere((f) => f.name == 'ifTest');
+    final func = await service.getObject(isolateId, funcRef.id!) as Func;
+    final location = func.location!;
+
+    final report = await service.getSourceReport(
+      isolateId,
+      [SourceReportKind.kBranchCoverage],
+      scriptId: location.script!.id,
+      tokenPos: location.tokenPos,
+      endTokenPos: location.endTokenPos,
+      forceCompile: true,
+      reportLines: reportLines,
+    );
+    expect(report.ranges!.length, 1);
+    expect(report.ranges![0].toJson(), expectedRange);
+    expect(report.scripts!.length, 1);
+    expect(
+      report.scripts![0].uri,
+      endsWith('branch_coverage_test.dart'),
+    );
+  };
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  coverageTest(
+    {
+      'scriptIndex': 0,
+      'startPos': 397,
+      'endPos': 527,
+      'compiled': true,
+      'branchCoverage': {
+        'hits': [],
+        'misses': [397, 426, 444, 474, 507]
+      }
+    },
+    reportLines: false,
+  ),
+  coverageTest(
+    {
+      'scriptIndex': 0,
+      'startPos': 397,
+      'endPos': 527,
+      'compiled': true,
+      'branchCoverage': {
+        'hits': [],
+        'misses': [11, 12, 13, 15, 18]
+      }
+    },
+    reportLines: true,
+  ),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  coverageTest(
+    {
+      'scriptIndex': 0,
+      'startPos': 397,
+      'endPos': 527,
+      'compiled': true,
+      'branchCoverage': {
+        'hits': [397, 426, 474],
+        'misses': [444, 507]
+      }
+    },
+    reportLines: false,
+  ),
+  coverageTest(
+    {
+      'scriptIndex': 0,
+      'startPos': 397,
+      'endPos': 527,
+      'compiled': true,
+      'branchCoverage': {
+        'hits': [11, 12, 15],
+        'misses': [13, 18]
+      }
+    },
+    reportLines: true,
+  ),
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'branch_coverage_test.dart',
+      testeeConcurrent: testFunction,
+      extraArgs: ['--branch-coverage'],
+    );
diff --git a/pkg/vm_service/test/breakpoint_async_break_test.dart b/pkg/vm_service/test/breakpoint_async_break_test.dart
index d0c2443..b83e6ad 100644
--- a/pkg/vm_service/test/breakpoint_async_break_test.dart
+++ b/pkg/vm_service/test/breakpoint_async_break_test.dart
@@ -9,7 +9,8 @@
 import 'common/service_test_common.dart';
 import 'common/test_helper.dart';
 
-const int LINE = 18;
+const int LINE = 19;
+const int COL = 7;
 
 // Issue: https://github.com/dart-lang/sdk/issues/36622
 Future<void> testMain() async {
@@ -62,7 +63,10 @@
     expect(futureBpt.resolved, isTrue);
     expect(
         script.getLineNumberFromTokenPos(futureBpt.location!.tokenPos), LINE);
-    expect(script.getColumnNumberFromTokenPos(futureBpt.location!.tokenPos), 7);
+    expect(futureBpt.location!.line, LINE);
+    expect(
+        script.getColumnNumberFromTokenPos(futureBpt.location!.tokenPos), COL);
+    expect(futureBpt.location!.column, COL);
 
     // Remove the breakpoints.
     expect((await service.removeBreakpoint(isolateId, futureBpt.id!)).type,
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index e16e307d..62ced95 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -107,6 +107,7 @@
     bool pause_on_unhandled_exceptions,
     bool testeeControlsServer,
     bool useAuthToken,
+    List<String>? experiments,
     List<String>? extraArgs,
   ) {
     return _spawnDartProcess(
@@ -115,6 +116,7 @@
         pause_on_unhandled_exceptions,
         testeeControlsServer,
         useAuthToken,
+        experiments,
         extraArgs);
   }
 
@@ -124,6 +126,7 @@
       bool pause_on_unhandled_exceptions,
       bool testeeControlsServer,
       bool useAuthToken,
+      List<String>? experiments,
       List<String>? extraArgs) {
     String dartExecutable = io.Platform.executable;
 
@@ -143,6 +146,9 @@
       fullArgs.add('--pause-isolates-on-unhandled-exceptions');
     }
     fullArgs.add('--profiler');
+    if (experiments != null) {
+      fullArgs.addAll(experiments.map((e) => '--enable-experiment=$e'));
+    }
     if (extraArgs != null) {
       fullArgs.addAll(extraArgs);
     }
@@ -152,7 +158,6 @@
       fullArgs.add('--enable-vm-service:0');
     }
     fullArgs.addAll(args);
-
     return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
   }
 
@@ -180,6 +185,7 @@
       bool pause_on_unhandled_exceptions,
       bool testeeControlsServer,
       bool useAuthToken,
+      List<String>? experiments,
       List<String>? extraArgs) {
     return _spawnProcess(
             pause_on_start,
@@ -187,6 +193,7 @@
             pause_on_unhandled_exceptions,
             testeeControlsServer,
             useAuthToken,
+            experiments,
             extraArgs)
         .then((p) {
       Completer<Uri> completer = Completer<Uri>();
@@ -247,25 +254,27 @@
 }
 
 class _ServiceTesterRunner {
-  Future run(
-      {List<String>? mainArgs,
-      List<String>? extraArgs,
-      List<VMTest>? vmTests,
-      List<IsolateTest>? isolateTests,
-      required String scriptName,
-      bool pause_on_start = false,
-      bool pause_on_exit = false,
-      bool verbose_vm = false,
-      bool pause_on_unhandled_exceptions = false,
-      bool testeeControlsServer = false,
-      bool useAuthToken = false}) async {
+  Future run({
+    List<String>? mainArgs,
+    List<String>? extraArgs,
+    List<String>? experiments,
+    List<VMTest>? vmTests,
+    List<IsolateTest>? isolateTests,
+    required String scriptName,
+    bool pause_on_start = false,
+    bool pause_on_exit = false,
+    bool verbose_vm = false,
+    bool pause_on_unhandled_exceptions = false,
+    bool testeeControlsServer = false,
+    bool useAuthToken = false,
+  }) async {
     var process = _ServiceTesteeLauncher(scriptName);
     late VmService vm;
     late IsolateRef isolate;
     setUp(() async {
       await process
           .launch(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions,
-              testeeControlsServer, useAuthToken, extraArgs)
+              testeeControlsServer, useAuthToken, experiments, extraArgs)
           .then((Uri serverAddress) async {
         if (mainArgs!.contains("--gdb")) {
           var pid = process.process!.pid;
@@ -277,7 +286,6 @@
         vm = await vmServiceConnectUri(serviceWebsocketAddress);
         print('Done loading VM');
         isolate = await getFirstIsolate(vm);
-        print('Got first isolate');
       });
     });
 
@@ -327,13 +335,11 @@
     Completer<dynamic>? completer = Completer();
     late StreamSubscription subscription;
     subscription = service.onIsolateEvent.listen((Event event) async {
-      print('Isolate event: $event');
       if (completer == null) {
         await subscription.cancel();
         return;
       }
       if (event.kind == EventKind.kIsolateRunnable) {
-        print(event.isolate!.name);
         vm = await service.getVM();
         await subscription.cancel();
         await service.streamCancel(EventStreams.kIsolate);
@@ -372,6 +378,7 @@
   bool pause_on_unhandled_exceptions = false,
   bool testeeControlsServer = false,
   bool useAuthToken = false,
+  List<String>? experiments,
   List<String>? extraArgs,
 }) async {
   assert(!pause_on_start || testeeBefore == null);
@@ -390,6 +397,7 @@
         pause_on_start: pause_on_start,
         pause_on_exit: pause_on_exit,
         verbose_vm: verbose_vm,
+        experiments: experiments,
         pause_on_unhandled_exceptions: pause_on_unhandled_exceptions,
         testeeControlsServer: testeeControlsServer,
         useAuthToken: useAuthToken);
diff --git a/pkg/vm_service/test/debugging_test.dart b/pkg/vm_service/test/debugging_test.dart
index 1ddee02..cf56e3e 100644
--- a/pkg/vm_service/test/debugging_test.dart
+++ b/pkg/vm_service/test/debugging_test.dart
@@ -91,6 +91,7 @@
     final SourceLocation location = bpt.location;
     expect(location.script!.id, script.id);
     expect(script.getLineNumberFromTokenPos(location.tokenPos!), 16);
+    expect(location.line, 16);
 
     isolate = await service.getIsolate(isolateId);
     expect(isolate.breakpoints!.length, 1);
@@ -103,13 +104,12 @@
     final isolateId = isolateRef.id!;
     final stack = await service.getStack(isolateId);
     expect(stack.frames!.length, greaterThanOrEqualTo(1));
-
-    Script script = (await service.getObject(
-        isolateId, stack.frames![0].location!.script!.id!)) as Script;
+    final location = stack.frames![0].location!;
+    Script script =
+        (await service.getObject(isolateId, location.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(
-        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
-        16);
+    expect(script.getLineNumberFromTokenPos(location.tokenPos!), 16);
+    expect(location.line, 16);
   },
 
 // Stepping
@@ -136,13 +136,12 @@
     final isolateId = isolateRef.id!;
     final stack = await service.getStack(isolateId);
     expect(stack.frames!.length, greaterThanOrEqualTo(1));
-
-    final Script script = (await service.getObject(
-        isolateId, stack.frames![0].location!.script!.id!)) as Script;
+    final location = stack.frames![0].location!;
+    final Script script =
+        (await service.getObject(isolateId, location.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(
-        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
-        17);
+    expect(script.getLineNumberFromTokenPos(location.tokenPos!), 17);
+    expect(location.line, 17);
   },
 // Remove breakpoint
   (VmService service, IsolateRef isolateRef) async {
@@ -214,6 +213,7 @@
         (await service.getObject(isolateId, bpt.location.script.id)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
     expect(script.getLineNumberFromTokenPos(bpt.location.tokenPos), 14);
+    expect(bpt.location.line, 14);
 
     // Refresh isolate state.
     isolate = await service.getIsolate(isolateId);
@@ -226,13 +226,12 @@
     final isolateId = isolateRef.id!;
     final stack = await service.getStack(isolateId);
     expect(stack.frames!.length, greaterThanOrEqualTo(1));
-
-    final Script script = (await service.getObject(
-        isolateId, stack.frames![0].location!.script!.id!)) as Script;
+    final location = stack.frames![0].location!;
+    final Script script =
+        (await service.getObject(isolateId, location.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(
-        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
-        14);
+    expect(script.getLineNumberFromTokenPos(location.tokenPos!), 14);
+    expect(location.line, 14);
   },
 ];
 
diff --git a/pkg/vm_service/test/eval_named_args_anywhere_test.dart b/pkg/vm_service/test/eval_named_args_anywhere_test.dart
new file mode 100644
index 0000000..ad01d46
--- /dev/null
+++ b/pkg/vm_service/test/eval_named_args_anywhere_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for 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=2.17
+// ignore_for_file: unused_element
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+int foo(int a, {required int b}) {
+  return a - b;
+}
+
+class _MyClass {
+  int foo(int a, {required int b}) {
+    return a - b;
+  }
+
+  static int baz(int a, {required int b}) {
+    return a - b;
+  }
+}
+
+void testFunction() {
+  debugger();
+}
+
+final tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+
+    final rootLibId = isolate.rootLib!.id!;
+
+    // Evaluate top-level function
+    var result = await service.evaluate(
+      isolateId,
+      rootLibId,
+      'foo(b: 10, 50)',
+    ) as InstanceRef;
+    expect(result.valueAsString, '40');
+
+    // Evaluate class instance method
+    result = await service.evaluate(
+      isolateId,
+      rootLibId,
+      '_MyClass().foo(b: 10, 50)',
+    ) as InstanceRef;
+    expect(result.valueAsString, '40');
+
+    // Evaluate static method
+    result = await service.evaluate(
+      isolateId,
+      rootLibId,
+      '_MyClass.baz(b: 10, 50)',
+    ) as InstanceRef;
+    expect(result.valueAsString, '40');
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'eval_named_args_anywhere_test.dart',
+      testeeConcurrent: testFunction,
+      experiments: ['named-arguments-anywhere'],
+    );
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 8b3999a..a4c477a 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -112,6 +112,10 @@
     defines += [ "TARGET_ARCH_X64" ]
   } else if (dart_target_arch == "ia32" || dart_target_arch == "x86") {
     defines += [ "TARGET_ARCH_IA32" ]
+  } else if (dart_target_arch == "riscv32") {
+    defines += [ "TARGET_ARCH_RISCV32" ]
+  } else if (dart_target_arch == "riscv64") {
+    defines += [ "TARGET_ARCH_RISCV64" ]
   } else {
     print("Invalid dart_target_arch: $dart_target_arch")
     assert(false)
diff --git a/runtime/bin/address_sanitizer.cc b/runtime/bin/address_sanitizer.cc
index a780894..4b8776d 100644
--- a/runtime/bin/address_sanitizer.cc
+++ b/runtime/bin/address_sanitizer.cc
@@ -7,6 +7,7 @@
 #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOSX)
 #if defined(__has_feature)
 #if __has_feature(address_sanitizer)
+#if !defined(GOOGLE3)
 
 const char* kAsanDefaultOptions =
     "strict_memcmp=0 symbolize=0 check_printf=1 use_sigaltstack=1 "
@@ -21,6 +22,7 @@
   return kAsanDefaultOptions;
 }
 
+#endif  // !defined(GOOGLE3)
 #endif  // __has_feature(address_sanitizer)
 #endif  // defined(__has_feature)
 #endif  //  defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOSX)
diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc
index 4b9fe69..93259b0 100644
--- a/runtime/bin/dartdev_isolate.cc
+++ b/runtime/bin/dartdev_isolate.cc
@@ -206,7 +206,7 @@
   Dart_IsolateFlags flags;
   Dart_IsolateFlagsInitialize(&flags);
   flags.enable_asserts = false;
-  flags.null_safety = false;
+  flags.null_safety = true;
   flags.use_field_guards = true;
   flags.use_osr = true;
   flags.is_system_isolate = true;
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 701967b..b29c8c1 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -194,6 +194,21 @@
                               package_config, verbosity());
 }
 
+Dart_KernelCompilationResult DFE::CompileScriptWithGivenNullsafety(
+    const char* script_uri,
+    const char* package_config,
+    bool snapshot,
+    bool null_safety) {
+  // TODO(aam): When Frontend is ready, VM should be passing vm_outline.dill
+  // instead of vm_platform.dill to Frontend for compilation.
+  PathSanitizer path_sanitizer(script_uri);
+  const char* sanitized_uri = path_sanitizer.sanitized_uri();
+
+  return Dart_CompileToKernelWithGivenNullsafety(
+      sanitized_uri, platform_strong_dill, platform_strong_dill_size, snapshot,
+      package_config, null_safety, verbosity());
+}
+
 void DFE::CompileAndReadScript(const char* script_uri,
                                uint8_t** kernel_buffer,
                                intptr_t* kernel_buffer_size,
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index 038bca7..eb18df6 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -72,6 +72,19 @@
                                              const char* package_config,
                                              bool snapshot);
 
+  // Compiles specified script.
+  // Returns result from compiling the script.
+  //
+  // `snapshot` is used by the frontend to determine if compilation
+  // related information should be printed to console (e.g., null safety mode).
+  // `null_safety` specifies compilation mode, which is normally
+  // retrieved either from vm flags or from vm isolate group.
+  Dart_KernelCompilationResult CompileScriptWithGivenNullsafety(
+      const char* script_uri,
+      const char* package_config,
+      bool snapshot,
+      bool null_safety);
+
   // Compiles specified script and reads the resulting kernel file.
   // If the compilation is successful, returns a valid in memory kernel
   // representation of the script, NULL otherwise
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index a5ff8c0..fb0e3a0 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -313,6 +313,8 @@
 #elif defined(TARGET_ARCH_ARM64)
   CHECK_ERROR(header_.machine == dart::elf::EM_AARCH64,
               "Architecture mismatch.");
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+  CHECK_ERROR(header_.machine == dart::elf::EM_RISCV, "Architecture mismatch.");
 #else
 #error Unsupported architecture architecture.
 #endif
diff --git a/runtime/bin/ffi_test/clobber_riscv32.S b/runtime/bin/ffi_test/clobber_riscv32.S
new file mode 100644
index 0000000..374c1d5
--- /dev/null
+++ b/runtime/bin/ffi_test/clobber_riscv32.S
@@ -0,0 +1,27 @@
+.text
+
+#if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */
+.globl ClobberAndCall
+.type ClobberAndCall, @function
+ClobberAndCall:
+#else /* HOST_OS_MACOS */
+.globl _ClobberAndCall
+_ClobberAndCall:
+#endif
+
+li a0, 1
+li a1, 1
+li a2, 1
+li a3, 1
+li a4, 1
+li a5, 1
+li a6, 1
+li a7, 1
+li t0, 1
+li t1, 1
+li t2, 1
+li t3, 1
+li t4, 1
+li t5, 1
+li t6, 1
+ret
diff --git a/runtime/bin/ffi_test/clobber_riscv64.S b/runtime/bin/ffi_test/clobber_riscv64.S
new file mode 100644
index 0000000..374c1d5
--- /dev/null
+++ b/runtime/bin/ffi_test/clobber_riscv64.S
@@ -0,0 +1,27 @@
+.text
+
+#if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */
+.globl ClobberAndCall
+.type ClobberAndCall, @function
+ClobberAndCall:
+#else /* HOST_OS_MACOS */
+.globl _ClobberAndCall
+_ClobberAndCall:
+#endif
+
+li a0, 1
+li a1, 1
+li a2, 1
+li a3, 1
+li a4, 1
+li a5, 1
+li a6, 1
+li a7, 1
+li t0, 1
+li t1, 1
+li t2, 1
+li t3, 1
+li t4, 1
+li t5, 1
+li t6, 1
+ret
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index dd5e41f..1545f8e 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -1138,27 +1138,36 @@
 typedef intptr_t ssize_t;
 #endif
 
-#define DEFINE_SIZE_OF(type_modifier, type)                                    \
-  DART_EXPORT uint64_t FfiSizeOf_##type_modifier##_##type() {                  \
-    return sizeof(type_modifier type);                                         \
+#define DEFINE_SIZE_OF_AND_SIGN_OF(type_modifier, type, type2)                 \
+  DART_EXPORT uint64_t FfiSizeOf_##type_modifier##_##type##_##type2() {        \
+    return sizeof(type_modifier type type2);                                   \
+  }                                                                            \
+                                                                               \
+  DART_EXPORT uint64_t FfiSignOf_##type_modifier##_##type##_##type2() {        \
+    return std::numeric_limits<type_modifier type type2>::is_signed;           \
   }
 
-#define SIZES(F)                                                               \
-  F(, intptr_t)                                                                \
-  F(, uintptr_t)                                                               \
-  F(, int)                                                                     \
-  F(unsigned, int)                                                             \
-  F(, long)         /* NOLINT */                                               \
-  F(unsigned, long) /* NOLINT */                                               \
-  F(, wchar_t)                                                                 \
-  F(, size_t)                                                                  \
-  F(, ssize_t)                                                                 \
-  F(, off_t)
+#define TYPES(F)                                                               \
+  F(, char, )             /* NOLINT */                                         \
+  F(signed, char, )       /* NOLINT */                                         \
+  F(unsigned, char, )     /* NOLINT */                                         \
+  F(, short, )            /* NOLINT */                                         \
+  F(unsigned, short, )    /* NOLINT */                                         \
+  F(, int, )              /* NOLINT */                                         \
+  F(unsigned, int, )      /* NOLINT */                                         \
+  F(, long, )             /* NOLINT */                                         \
+  F(unsigned, long, )     /* NOLINT */                                         \
+  F(, long, long)         /* NOLINT */                                         \
+  F(unsigned, long, long) /* NOLINT */                                         \
+  F(, intptr_t, )         /* NOLINT */                                         \
+  F(, uintptr_t, )        /* NOLINT */                                         \
+  F(, size_t, )           /* NOLINT */                                         \
+  F(, wchar_t, )          /* NOLINT */
 
-SIZES(DEFINE_SIZE_OF)
+TYPES(DEFINE_SIZE_OF_AND_SIGN_OF)
 
-#undef DEFINE_SIZE_OF
-#undef SIZES
+#undef DEFINE_SIZE_OF_AND_SIGN_OF
+#undef TYPES
 
 DART_EXPORT int64_t WCharMinValue() {
   return WCHAR_MIN;
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index cf10a4e..6b546ad 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -906,6 +906,34 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// Helpers used for isolate exit tests.
+////////////////////////////////////////////////////////////////////////////////
+
+// This method consumes and ignores unwind error raised by `Isolate.exit` called
+// by dart `callIsolateExit` method.
+DART_EXPORT void IsolateExitTest_LookupAndCallIsolateExit(int i) {
+  Dart_Handle root_lib = Dart_RootLibrary();
+  fprintf(stderr, "IsolateExitTest_LookupAndCallIsolateExit i:%d\n", i);
+  if (i > 0) {
+    Dart_Handle method_name =
+        Dart_NewStringFromCString("recurseLookupAndCallWorker");
+    Dart_Handle dart_args[1];
+    dart_args[0] = Dart_NewInteger(i - 1);
+    Dart_Handle result = Dart_Invoke(root_lib, method_name, 1, dart_args);
+    ENSURE(Dart_IsError(result));
+  } else {
+    Dart_Handle method_name = Dart_NewStringFromCString("callIsolateExit");
+    Dart_Handle result = Dart_Invoke(root_lib, method_name, 0, NULL);
+    if (Dart_IsError(result)) {
+      fprintf(stderr,
+              "%d failed to invoke %s in child isolate: %s, carrying on..\n", i,
+              "callIsolateExit", Dart_GetError(result));
+    }
+    ENSURE(Dart_IsError(result));
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Functions for handle tests.
 //
 // vmspecific_handle_test.dart (statically linked).
diff --git a/runtime/bin/ffi_unit_test/BUILD.gn b/runtime/bin/ffi_unit_test/BUILD.gn
index 99396af..bad85d0 100644
--- a/runtime/bin/ffi_unit_test/BUILD.gn
+++ b/runtime/bin/ffi_unit_test/BUILD.gn
@@ -49,6 +49,14 @@
   defines = [ "TARGET_ARCH_X64" ]
 }
 
+config("define_target_arch_riscv32") {
+  defines = [ "TARGET_ARCH_RISCV32" ]
+}
+
+config("define_target_arch_riscv64") {
+  defines = [ "TARGET_ARCH_RISCV64" ]
+}
+
 config("define_target_os_android") {
   defines = [ "DART_TARGET_OS_ANDROID" ]
 }
@@ -167,6 +175,20 @@
   ]
 }
 
+build_run_ffi_unit_tests("run_ffi_unit_tests_riscv32_linux") {
+  extra_configs = [
+    ":define_target_arch_riscv32",
+    ":define_target_os_linux",
+  ]
+}
+
+build_run_ffi_unit_tests("run_ffi_unit_tests_riscv64_linux") {
+  extra_configs = [
+    ":define_target_arch_riscv64",
+    ":define_target_os_linux",
+  ]
+}
+
 group("run_ffi_unit_tests") {
   deps = [
     ":run_ffi_unit_tests_arm64_android",
@@ -179,6 +201,8 @@
     ":run_ffi_unit_tests_ia32_android",  # Emulator, no other test coverage.
     ":run_ffi_unit_tests_ia32_linux",
     ":run_ffi_unit_tests_ia32_win",
+    ":run_ffi_unit_tests_riscv32_linux",
+    ":run_ffi_unit_tests_riscv64_linux",
     ":run_ffi_unit_tests_x64_ios",  # Simulator, no other test coverage.
     ":run_ffi_unit_tests_x64_linux",
     ":run_ffi_unit_tests_x64_macos",
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 6a24139..b3c5cbb 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -957,3 +957,8 @@
 int main(int argc, char** argv) {
   return dart::bin::main(argc, argv);
 }
+
+// TODO(riscv): Why is this missing from libc?
+#if defined(__riscv)
+char __libc_single_threaded = 0;
+#endif
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d03555a..2e80b0a 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -96,7 +96,7 @@
     SAVE_ERROR_AND_EXIT(result);                                               \
   }
 
-static void WriteDepsFile(Dart_Isolate isolate) {
+static void WriteDepsFile() {
   if (Options::depfile() == NULL) {
     return;
   }
@@ -142,7 +142,7 @@
     if (Options::gen_snapshot_kind() == kAppJIT) {
       Snapshot::GenerateAppJIT(Options::snapshot_filename());
     }
-    WriteDepsFile(main_isolate);
+    WriteDepsFile();
   }
 }
 
@@ -937,6 +937,20 @@
     ErrorExit(exit_code, "%s\n", Dart_GetError(result));                       \
   }
 
+static void CompileAndSaveKernel(const char* script_name,
+                                 const char* package_config_override,
+                                 CommandLineOptions* dart_options) {
+  if (vm_run_app_snapshot) {
+    Syslog::PrintErr("Cannot create a script snapshot from an app snapshot.\n");
+    // The snapshot would contain references to the app snapshot instead of
+    // the core snapshot.
+    Platform::Exit(kErrorExitCode);
+  }
+  Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
+                           package_config_override);
+  WriteDepsFile();
+}
+
 void RunMainIsolate(const char* script_name,
                     const char* package_config_override,
                     CommandLineOptions* dart_options) {
@@ -1001,71 +1015,59 @@
 
   Dart_EnterScope();
 
-  auto isolate_group_data =
-      reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
-  if (Options::gen_snapshot_kind() == kKernel) {
-    if (vm_run_app_snapshot) {
-      Syslog::PrintErr(
-          "Cannot create a script snapshot from an app snapshot.\n");
-      // The snapshot would contain references to the app snapshot instead of
-      // the core snapshot.
-      Platform::Exit(kErrorExitCode);
-    }
-    Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
-                             isolate_group_data->resolved_packages_config());
-  } else {
-    // Lookup the library of the root script.
-    Dart_Handle root_lib = Dart_RootLibrary();
+  // Kernel snapshots should have been handled before reaching this point.
+  ASSERT(Options::gen_snapshot_kind() != kKernel);
+  // Lookup the library of the root script.
+  Dart_Handle root_lib = Dart_RootLibrary();
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    if (Options::compile_all()) {
-      result = Dart_CompileAll();
-      CHECK_RESULT(result);
-    }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
-    if (Dart_IsNull(root_lib)) {
-      ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
-                script_name);
-    }
-
-    // Create a closure for the main entry point which is in the exported
-    // namespace of the root library or invoke a getter of the same name
-    // in the exported namespace and return the resulting closure.
-    Dart_Handle main_closure =
-        Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
-    CHECK_RESULT(main_closure);
-    if (!Dart_IsClosure(main_closure)) {
-      ErrorExit(kErrorExitCode, "Unable to find 'main' in root library '%s'\n",
-                script_name);
-    }
-
-    // Call _startIsolate in the isolate library to enable dispatching the
-    // initial startup message.
-    const intptr_t kNumIsolateArgs = 2;
-    Dart_Handle isolate_args[kNumIsolateArgs];
-    isolate_args[0] = main_closure;                          // entryPoint
-    isolate_args[1] = dart_options->CreateRuntimeOptions();  // args
-
-    Dart_Handle isolate_lib =
-        Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
-    result =
-        Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startMainIsolate"),
-                    kNumIsolateArgs, isolate_args);
-    CHECK_RESULT(result);
-
-    // Keep handling messages until the last active receive port is closed.
-    result = Dart_RunLoop();
-    // Generate an app snapshot after execution if specified.
-    if (Options::gen_snapshot_kind() == kAppJIT) {
-      if (!Dart_IsCompilationError(result)) {
-        Snapshot::GenerateAppJIT(Options::snapshot_filename());
-      }
-    }
+  if (Options::compile_all()) {
+    result = Dart_CompileAll();
     CHECK_RESULT(result);
   }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-  WriteDepsFile(isolate);
+  if (Dart_IsNull(root_lib)) {
+    ErrorExit(kErrorExitCode, "Unable to find root library for '%s'\n",
+              script_name);
+  }
+
+  // Create a closure for the main entry point which is in the exported
+  // namespace of the root library or invoke a getter of the same name
+  // in the exported namespace and return the resulting closure.
+  Dart_Handle main_closure =
+      Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
+  CHECK_RESULT(main_closure);
+  if (!Dart_IsClosure(main_closure)) {
+    ErrorExit(kErrorExitCode, "Unable to find 'main' in root library '%s'\n",
+              script_name);
+  }
+
+  // Call _startIsolate in the isolate library to enable dispatching the
+  // initial startup message.
+  const intptr_t kNumIsolateArgs = 2;
+  Dart_Handle isolate_args[kNumIsolateArgs];
+  isolate_args[0] = main_closure;                          // entryPoint
+  isolate_args[1] = dart_options->CreateRuntimeOptions();  // args
+
+  Dart_Handle isolate_lib =
+      Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
+  result =
+      Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startMainIsolate"),
+                  kNumIsolateArgs, isolate_args);
+  CHECK_RESULT(result);
+
+  // Keep handling messages until the last active receive port is closed.
+  result = Dart_RunLoop();
+  // Generate an app snapshot after execution if specified.
+  if (Options::gen_snapshot_kind() == kAppJIT) {
+    if (!Dart_IsCompilationError(result)) {
+      Snapshot::GenerateAppJIT(Options::snapshot_filename());
+    }
+  }
+  CHECK_RESULT(result);
+
+  WriteDepsFile();
 
   Dart_ExitScope();
 
@@ -1350,8 +1352,14 @@
           script_name);
       Platform::Exit(kErrorExitCode);
     } else {
-      // Run the main isolate until we aren't told to restart.
-      RunMainIsolate(script_name, package_config_override, &dart_options);
+      if (Options::gen_snapshot_kind() == kKernel) {
+        CompileAndSaveKernel(script_name, package_config_override,
+                             &dart_options);
+
+      } else {
+        // Run the main isolate until we aren't told to restart.
+        RunMainIsolate(script_name, package_config_override, &dart_options);
+      }
     }
   }
 
@@ -1392,3 +1400,8 @@
   dart::bin::main(argc, argv);
   UNREACHABLE();
 }
+
+// TODO(riscv): Why is this missing from libc?
+#if defined(__riscv)
+char __libc_single_threaded = 0;
+#endif
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index e213e70..83c1408 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -141,8 +141,10 @@
   if (!Options::verbose_option()) {
     Syslog::Print(
 "Common VM flags:\n"
+#if !defined(PRODUCT)
 "--enable-asserts\n"
 "  Enable assert statements.\n"
+#endif  // !defined(PRODUCT)
 "--help or -h\n"
 "  Display this message (add -v or --verbose for information about\n"
 "  all VM options).\n"
@@ -151,6 +153,7 @@
 "--define=<key>=<value> or -D<key>=<value>\n"
 "  Define an environment declaration. To specify multiple declarations,\n"
 "  use multiple instances of this option.\n"
+#if !defined(PRODUCT)
 "--observe[=<port>[/<bind-address>]]\n"
 "  The observe flag is a convenience flag used to run a program with a\n"
 "  set of options which are often useful for debugging under Observatory.\n"
@@ -166,6 +169,7 @@
 "  Outputs information necessary to connect to the VM service to the\n"
 "  specified file in JSON format. Useful for clients which are unable to\n"
 "  listen to stdout for the Observatory listening message.\n"
+#endif  // !defined(PRODUCT)
 "--snapshot-kind=<snapshot_kind>\n"
 "--snapshot=<file_name>\n"
 "  These snapshot options are used to generate a snapshot of the loaded\n"
@@ -178,8 +182,10 @@
   } else {
     Syslog::Print(
 "Supported options:\n"
+#if !defined(PRODUCT)
 "--enable-asserts\n"
 "  Enable assert statements.\n"
+#endif  // !defined(PRODUCT)
 "--help or -h\n"
 "  Display this message (add -v or --verbose for information about\n"
 "  all VM options).\n"
@@ -188,6 +194,7 @@
 "--define=<key>=<value> or -D<key>=<value>\n"
 "  Define an environment declaration. To specify multiple declarations,\n"
 "  use multiple instances of this option.\n"
+#if !defined(PRODUCT)
 "--observe[=<port>[/<bind-address>]]\n"
 "  The observe flag is a convenience flag used to run a program with a\n"
 "  set of options which are often useful for debugging under Observatory.\n"
@@ -199,12 +206,14 @@
 "      --warn-on-pause-with-no-debugger\n"
 "  This set is subject to change.\n"
 "  Please see these options for further documentation.\n"
+#endif  // !defined(PRODUCT)
 "--version\n"
 "  Print the VM version.\n"
 "\n"
 "--trace-loading\n"
 "  enables tracing of library and script loading\n"
 "\n"
+#if !defined(PRODUCT)
 "--enable-vm-service[=<port>[/<bind-address>]]\n"
 "  Enables the VM service and listens on specified port for connections\n"
 "  (default port number is 8181, default bind address is localhost).\n"
@@ -219,6 +228,7 @@
 "  When the VM service is told to bind to a particular port, fallback to 0 if\n"
 "  it fails to bind instead of failing to start.\n"
 "\n"
+#endif  // !defined(PRODUCT)
 "--root-certs-file=<path>\n"
 "  The path to a file containing the trusted root certificates to use for\n"
 "  secure socket connections.\n"
@@ -321,6 +331,7 @@
 int Options::vm_service_server_port_ = INVALID_VM_SERVICE_SERVER_PORT;
 bool Options::ProcessEnableVmServiceOption(const char* arg,
                                            CommandLineOptions* vm_options) {
+#if !defined(PRODUCT)
   const char* value =
       OptionProcessor::ProcessOption(arg, "--enable-vm-service");
   if (value == NULL) {
@@ -339,10 +350,15 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   enable_vm_service_ = true;
   return true;
+#else
+  // VM service not available in product mode.
+  return false;
+#endif  // !defined(PRODUCT)
 }
 
 bool Options::ProcessObserveOption(const char* arg,
                                    CommandLineOptions* vm_options) {
+#if !defined(PRODUCT)
   const char* value = OptionProcessor::ProcessOption(arg, "--observe");
   if (value == NULL) {
     return false;
@@ -366,6 +382,10 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   enable_vm_service_ = true;
   return true;
+#else
+  // VM service not available in product mode.
+  return false;
+#endif  // !defined(PRODUCT)
 }
 
 // Explicitly handle VM flags that can be parsed by DartDev's run command.
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index 68723c2..4b5bb50 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -47,6 +47,10 @@
     return "ia32";
 #elif defined(HOST_ARCH_X64)
     return "x64";
+#elif defined(HOST_ARCH_RISCV32)
+    return "riscv32";
+#elif defined(HOST_ARCH_RISCV64)
+    return "riscv64";
 #else
 #error Architecture detection failed.
 #endif
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index d560dab..58d16b6 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -380,6 +380,7 @@
       /*shutdown_isolate=*/nullptr,
       /*cleanup_isolate=*/nullptr,
       /*cleanup_group=*/CleanupIsolateGroup,
+      /*thread_start=*/nullptr,
       /*thread_exit=*/nullptr, dart::bin::DartUtils::OpenFile,
       dart::bin::DartUtils::ReadFile, dart::bin::DartUtils::WriteFile,
       dart::bin::DartUtils::CloseFile, /*entropy_source=*/nullptr,
@@ -426,3 +427,8 @@
 int main(int argc, const char** argv) {
   dart::bin::Platform::Exit(dart::Main(argc, argv));
 }
+
+// TODO(riscv): Why is this missing from libc?
+#if defined(__riscv)
+char __libc_single_threaded = 0;
+#endif
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 754043a..4650da4 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -471,6 +471,8 @@
                               const char* script_name,
                               const char* package_config) {
 #if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) && !defined(TESTING)
+  ASSERT(Dart_CurrentIsolate() == nullptr);
+
   uint8_t* kernel_buffer = NULL;
   intptr_t kernel_buffer_size = 0;
   dfe.ReadScript(script_name, &kernel_buffer, &kernel_buffer_size);
@@ -478,10 +480,23 @@
     WriteSnapshotFile(snapshot_filename, kernel_buffer, kernel_buffer_size);
     free(kernel_buffer);
   } else {
-    Dart_KernelCompilationResult result =
-        dfe.CompileScript(script_name, false, package_config, true);
+    PathSanitizer script_uri_sanitizer(script_name);
+    PathSanitizer packages_config_sanitizer(package_config);
+
+    bool null_safety =
+        Dart_DetectNullSafety(script_uri_sanitizer.sanitized_uri(),
+                              packages_config_sanitizer.sanitized_uri(),
+                              DartUtils::original_working_directory,
+                              /*isolate_snapshot_data=*/nullptr,
+                              /*isolate_snapshot_instructions=*/nullptr,
+                              /*kernel_buffer=*/nullptr,
+                              /*kernel_buffer_size=*/0);
+
+    Dart_KernelCompilationResult result = dfe.CompileScriptWithGivenNullsafety(
+        script_name, package_config, /*snapshot=*/true, null_safety);
     if (result.status != Dart_KernelCompilationStatus_Ok) {
-      ErrorExit(kErrorExitCode, "%s\n", result.error);
+      Syslog::PrintErr("%s\n", result.error);
+      Platform::Exit(kCompilationErrorExitCode);
     }
     WriteSnapshotFile(snapshot_filename, result.kernel, result.kernel_size);
     free(result.kernel);
diff --git a/runtime/docs/infra/il_tests.md b/runtime/docs/infra/il_tests.md
index 94c4500..c8c2b40 100644
--- a/runtime/docs/infra/il_tests.md
+++ b/runtime/docs/infra/il_tests.md
@@ -36,6 +36,10 @@
 
 Actual matching is done by the `pkg/vm/tool/compare_il` script.
 
+In order to test IL of the inner (local) function, use
+`@pragma('vm:testing:match-inner-flow-graph', 'inner name')`.
+Specifying a particular phase is not supported for inner closures.
+
 ## Example
 
 ```dart
@@ -54,4 +58,15 @@
     ]),
   ]);
 }
-```
\ No newline at end of file
+
+@pragma('vm:testing:match-inner-flow-graph', 'bar')
+void foo() {
+  @pragma('vm:testing:print-flow-graph')
+  bar() {
+  }
+}
+
+void matchIL$foo_bar(FlowGraph graph) {
+  // Test IL of local bar() in foo().
+}
+```
diff --git a/runtime/docs/pragmas.md b/runtime/docs/pragmas.md
index 589699c..77d6d8e 100644
--- a/runtime/docs/pragmas.md
+++ b/runtime/docs/pragmas.md
@@ -41,3 +41,14 @@
 | Pragma | Meaning |
 | --- | --- |
 | `vm:testing.unsafe.trace-entrypoints-fn` | [Observing which flow-graph-level entry-point was used when a function was called](compiler/frontend/testing_trace_entrypoints_pragma.md) |
+
+## Flutter toString transformer pragmas
+
+These pragmas are useful to exclude certain toString methods from toString transformation,
+which is enabled with `--delete-tostring-package-uri` option in kernel compilers and
+used by Flutter to remove certain toString methods in release mode to reduce size.
+
+| Pragma | Meaning |
+| --- | --- |
+| `flutter:keep-to-string` | Avoid transforming the annotated toString method. |
+| `flutter:keep-to-string-in-subtypes` | Avoid transforming toString methods in all subtypes of the annotated class. |
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index f37de2b..360de52 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -706,13 +706,6 @@
                                                char** error);
 
 /**
- * An isolate unhandled exception callback function.
- *
- * This callback has been DEPRECATED.
- */
-typedef void (*Dart_IsolateUnhandledExceptionCallback)(Dart_Handle error);
-
-/**
  * An isolate shutdown callback function.
  *
  * This callback, provided by the embedder, is called before the vm
@@ -764,6 +757,15 @@
 typedef void (*Dart_IsolateGroupCleanupCallback)(void* isolate_group_data);
 
 /**
+ * A thread start callback function.
+ * This callback, provided by the embedder, is called after a thread in the
+ * vm thread pool starts.
+ * This function could be used to adjust thread priority or attach native
+ * resources to the thread.
+ */
+typedef void (*Dart_ThreadStartCallback)(void);
+
+/**
  * A thread death callback function.
  * This callback, provided by the embedder, is called before a thread in the
  * vm thread pool exits.
@@ -847,7 +849,7 @@
  * The current version of the Dart_InitializeFlags. Should be incremented every
  * time Dart_InitializeFlags changes in a binary incompatible way.
  */
-#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000005)
+#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000006)
 
 /** Forward declaration */
 struct Dart_CodeObserver;
@@ -973,6 +975,7 @@
    */
   Dart_IsolateGroupCleanupCallback cleanup_group;
 
+  Dart_ThreadStartCallback thread_start;
   Dart_ThreadExitCallback thread_exit;
   Dart_FileOpenCallback file_open;
   Dart_FileReadCallback file_read;
@@ -1259,18 +1262,6 @@
 DART_EXPORT void Dart_KillIsolate(Dart_Isolate isolate);
 
 /**
- * Notifies the VM that the embedder expects |size| bytes of memory have become
- * unreachable. The VM may use this hint to adjust the garbage collector's
- * growth policy.
- *
- * Multiple calls are interpreted as increasing, not replacing, the estimate of
- * unreachable memory.
- *
- * Requires there to be a current isolate.
- */
-DART_EXPORT void Dart_HintFreed(intptr_t size);
-
-/**
  * Notifies the VM that the embedder expects to be idle until |deadline|. The VM
  * may use this time to perform garbage collection or other tasks to avoid
  * delays during execution of Dart code in the future.
@@ -3685,6 +3676,43 @@
                      const char* package_config,
                      Dart_KernelCompilationVerbosityLevel verbosity);
 
+/**
+ * Compiles the given `script_uri` to a kernel file.
+ *
+ * \param platform_kernel A buffer containing the kernel of the platform (e.g.
+ * `vm_platform_strong.dill`). The VM does not take ownership of this memory.
+ *
+ * \param platform_kernel_size The length of the platform_kernel buffer.
+ *
+ * \param snapshot_compile Set to `true` when the compilation is for a snapshot.
+ * This is used by the frontend to determine if compilation related information
+ * should be printed to console (e.g., null safety mode).
+ *
+ * \param null_safety Provides null-safety mode setting for the compiler.
+ *
+ * \param verbosity Specifies the logging behavior of the kernel compilation
+ * service.
+ *
+ * \return Returns the result of the compilation.
+ *
+ * On a successful compilation the returned [Dart_KernelCompilationResult] has
+ * a status of [Dart_KernelCompilationStatus_Ok] and the `kernel`/`kernel_size`
+ * fields are set. The caller takes ownership of the malloc()ed buffer.
+ *
+ * On a failed compilation the `error` might be set describing the reason for
+ * the failed compilation. The caller takes ownership of the malloc()ed
+ * error.
+ */
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileToKernelWithGivenNullsafety(
+    const char* script_uri,
+    const uint8_t* platform_kernel,
+    const intptr_t platform_kernel_size,
+    bool snapshot_compile,
+    const char* package_config,
+    const bool null_safety,
+    Dart_KernelCompilationVerbosityLevel verbosity);
+
 typedef struct {
   const char* uri;
   const char* source;
diff --git a/runtime/lib/core_sources.gni b/runtime/lib/core_sources.gni
index 7e18428..c5b40f1 100644
--- a/runtime/lib/core_sources.gni
+++ b/runtime/lib/core_sources.gni
@@ -22,5 +22,4 @@
   "stopwatch.cc",
   "string.cc",
   "uri.cc",
-  "weak_property.cc",
 ]
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 2c54160..e1a6b24 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -44,7 +44,7 @@
 
 #define DEFINE_NATIVE_ENTRY_LOAD(type)                                         \
   DEFINE_NATIVE_ENTRY(Ffi_load##type, 0, 2) { UNREACHABLE(); }
-CLASS_LIST_FFI_NUMERIC(DEFINE_NATIVE_ENTRY_LOAD)
+CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(DEFINE_NATIVE_ENTRY_LOAD)
 #undef DEFINE_NATIVE_ENTRY_LOAD
 
 DEFINE_NATIVE_ENTRY(Ffi_loadPointer, 1, 2) {
@@ -57,7 +57,7 @@
 
 #define DEFINE_NATIVE_ENTRY_STORE(type)                                        \
   DEFINE_NATIVE_ENTRY(Ffi_store##type, 0, 3) { UNREACHABLE(); }
-CLASS_LIST_FFI_NUMERIC(DEFINE_NATIVE_ENTRY_STORE)
+CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(DEFINE_NATIVE_ENTRY_STORE)
 #undef DEFINE_NATIVE_ENTRY_STORE
 
 DEFINE_NATIVE_ENTRY(Ffi_storePointer, 0, 3) {
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index 9346d1e..59e2305 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -13,57 +13,6 @@
 
 namespace dart {
 
-DEFINE_NATIVE_ENTRY(Math_sqrt, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(sqrt(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_sin, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(sin(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_cos, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(cos(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_tan, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(tan(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_asin, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(asin(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_acos, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(acos(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_atan, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(atan(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_atan2, 0, 2) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand1, arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand2, arguments->NativeArgAt(1));
-  return Double::New(atan2_ieee(operand1.value(), operand2.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_exp, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(exp(operand.value()));
-}
-
-DEFINE_NATIVE_ENTRY(Math_log, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
-  return Double::New(log(operand.value()));
-}
-
 DEFINE_NATIVE_ENTRY(Math_doublePow, 0, 2) {
   const double operand =
       Double::CheckedHandle(zone, arguments->NativeArgAt(0)).value();
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 2b7a470..f3efce1 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -299,14 +299,6 @@
   return unit.IssueLoad();
 }
 
-DEFINE_NATIVE_ENTRY(Internal_has63BitSmis, 0, 0) {
-#if defined(ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
-  return Bool::True().ptr();
-#else
-  return Bool::False().ptr();
-#endif  // defined(ARCH_IS_64_BIT)
-}
-
 DEFINE_NATIVE_ENTRY(Internal_unsafeCast, 0, 1) {
   UNREACHABLE();  // Should be erased at Kernel translation time.
   return arguments->NativeArgAt(0);
@@ -316,10 +308,6 @@
   UNREACHABLE();
 }
 
-DEFINE_NATIVE_ENTRY(Internal_reachabilityFence, 0, 1) {
-  UNREACHABLE();
-}
-
 DEFINE_NATIVE_ENTRY(Internal_collectAllGarbage, 0, 0) {
   isolate->group()->heap()->CollectAllGarbage();
   return Object::null();
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 9fb91ee..e411e07 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -343,8 +343,8 @@
   ASSERT(receiver.IsOneByteString());
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, code_point_obj, arguments->NativeArgAt(2));
-  ASSERT((0 <= code_point_obj.Value()) && (code_point_obj.Value() <= 0xFF));
-  OneByteString::SetCharAt(receiver, index_obj.Value(), code_point_obj.Value());
+  OneByteString::SetCharAt(receiver, index_obj.Value(),
+                           code_point_obj.Value() & 0xFF);
   return Object::null();
 }
 
@@ -353,8 +353,8 @@
   ASSERT(receiver.IsTwoByteString());
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, index_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, code_point_obj, arguments->NativeArgAt(2));
-  ASSERT((0 <= code_point_obj.Value()) && (code_point_obj.Value() <= 0xFFFF));
-  TwoByteString::SetCharAt(receiver, index_obj.Value(), code_point_obj.Value());
+  TwoByteString::SetCharAt(receiver, index_obj.Value(),
+                           code_point_obj.Value() & 0xFFFF);
   return Object::null();
 }
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 1f0744a..16725ec 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -35,6 +35,7 @@
   virtual void VisitIsolate(Isolate* isolate) {
     isolate_ports_.Add(isolate->main_port());
     isolate_names_.Add(&String::Handle(zone_, String::New(isolate->name())));
+    isolate->set_is_service_registered(true);
   }
 
   void RegisterIsolates() {
@@ -128,10 +129,13 @@
   return Object::null();
 }
 
-DEFINE_NATIVE_ENTRY(VMService_ListenStream, 0, 1) {
+DEFINE_NATIVE_ENTRY(VMService_ListenStream, 0, 2) {
 #ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
-  bool result = Service::ListenStream(stream_id.ToCString());
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, include_privates,
+                               arguments->NativeArgAt(1));
+  bool result =
+      Service::ListenStream(stream_id.ToCString(), include_privates.value());
   return Bool::Get(result).ptr();
 #else
   return Object::null();
diff --git a/runtime/lib/weak_property.cc b/runtime/lib/weak_property.cc
deleted file mode 100644
index 16eb41c..0000000
--- a/runtime/lib/weak_property.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "vm/bootstrap_natives.h"
-
-#include "vm/exceptions.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-
-namespace dart {
-
-DEFINE_NATIVE_ENTRY(WeakProperty_getKey, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(WeakProperty, weak_property,
-                               arguments->NativeArgAt(0));
-  return weak_property.key();
-}
-
-DEFINE_NATIVE_ENTRY(WeakProperty_setKey, 0, 2) {
-  GET_NON_NULL_NATIVE_ARGUMENT(WeakProperty, weak_property,
-                               arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, key, arguments->NativeArgAt(1));
-  weak_property.set_key(key);
-  return Object::null();
-}
-
-DEFINE_NATIVE_ENTRY(WeakProperty_getValue, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(WeakProperty, weak_property,
-                               arguments->NativeArgAt(0));
-  return weak_property.value();
-}
-
-DEFINE_NATIVE_ENTRY(WeakProperty_setValue, 0, 2) {
-  GET_NON_NULL_NATIVE_ARGUMENT(WeakProperty, weak_property,
-                               arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(1));
-  weak_property.set_value(value);
-  return Object::null();
-}
-
-}  // namespace dart
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 236343c..5c62c48 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -149,7 +149,11 @@
       return new Future.error(exception);
     }
     String serial = (_requestSerial++).toString();
-    var request = new _WebSocketRequest(method, params);
+    var request = new _WebSocketRequest(method, <String, dynamic>{
+      ...params,
+      // Include internal response data.
+      '_includePrivateMembers': true,
+    });
     if ((_webSocket != null) && _webSocket!.isOpen) {
       // Already connected, send request immediately.
       _sendRequest(serial, request);
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index c7c4dc5..7f63140 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -2545,7 +2545,7 @@
     if (_expanded) {
       final homeMethod = _frame.function!.homeMethod;
       String? homeMethodName;
-      if ((homeMethod.dartOwner is S.Class) && homeMethod.isStatic!) {
+      if ((homeMethod.dartOwner is S.Class) && homeMethod.isStatic == true) {
         homeMethodName = '<class>';
       } else if (homeMethod.dartOwner is S.Library) {
         homeMethodName = '<library>';
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index f449b78..a3e51a4 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -3098,7 +3098,11 @@
     } else {
       var localVariables = <ContextElement>[];
       for (var element in map['variables']) {
-        localVariables.add(new ContextElement(element));
+        try {
+          localVariables.add(new ContextElement(element));
+        } catch (e) {
+          // Swallowing '$e' to still show stuff...
+        }
       }
       variables = localVariables;
     }
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 048b1e4..d9e8b70 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], 'Version');
     expect(result['major'], 3);
-    expect(result['minor'], 55);
+    expect(result['minor'], 56);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 487c098..bf6ce73 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -18,6 +18,10 @@
 /// Determines whether DDS is enabled for this test run.
 const bool useDds = const bool.fromEnvironment('USE_DDS');
 
+/// The directory to output VM service response size data files to.
+const String serviceResponseSizesDir =
+    const String.fromEnvironment('SERVICE_RESPONSE_SIZES_DIR');
+
 /// The extra arguments to use
 const List<String> extraDebuggingArgs = ['--lazy-async-stacks'];
 
@@ -178,6 +182,15 @@
     if (!testeeControlsServer) {
       fullArgs.add('--enable-vm-service:$port');
     }
+    if (serviceResponseSizesDir.isNotEmpty) {
+      // Dump service response size details to a CSV. This feature is not used
+      // on the build bots and the generated output will persist after the test
+      // has completed.
+      final dir = path.prettyUri(serviceResponseSizesDir);
+      final testName = path.withoutExtension(path.basename(args.last));
+      final logName = '${testName}_${useDds ? "" : "no_"}dds_sizes.csv';
+      fullArgs.add('--log_service_response_sizes=$dir/$logName');
+    }
     fullArgs.addAll(args);
 
     return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
diff --git a/runtime/observatory_2/lib/service_common.dart b/runtime/observatory_2/lib/service_common.dart
index b61f4a0..d6eba9b 100644
--- a/runtime/observatory_2/lib/service_common.dart
+++ b/runtime/observatory_2/lib/service_common.dart
@@ -149,7 +149,11 @@
       return new Future.error(exception);
     }
     String serial = (_requestSerial++).toString();
-    var request = new _WebSocketRequest(method, params);
+    var request = new _WebSocketRequest(method, <String, dynamic>{
+      ...params,
+      // Include internal response data.
+      '_includePrivateMembers': true,
+    });
     if ((_webSocket != null) && _webSocket.isOpen) {
       // Already connected, send request immediately.
       _sendRequest(serial, request);
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index a3c7061..4e398bd 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(55));
+    expect(result['minor'], equals(56));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory_2/tests/service_2/test_helper.dart b/runtime/observatory_2/tests/service_2/test_helper.dart
index 86e7b13..b2667bf 100644
--- a/runtime/observatory_2/tests/service_2/test_helper.dart
+++ b/runtime/observatory_2/tests/service_2/test_helper.dart
@@ -20,6 +20,10 @@
 /// Determines whether DDS is enabled for this test run.
 const bool useDds = const bool.fromEnvironment('USE_DDS');
 
+/// The directory to output VM service response size data files to.
+const String serviceResponseSizesDir =
+    const String.fromEnvironment('SERVICE_RESPONSE_SIZES_DIR');
+
 /// The extra arguments to use
 const List<String> extraDebuggingArgs = ['--lazy-async-stacks'];
 
@@ -178,6 +182,15 @@
     if (!testeeControlsServer) {
       fullArgs.add('--enable-vm-service:$port');
     }
+    if (serviceResponseSizesDir.isNotEmpty) {
+      // Dump service response size details to a CSV. This feature is not used
+      // on the build bots and the generated output will persist after the test
+      // has completed.
+      final dir = path.prettyUri(serviceResponseSizesDir);
+      final testName = path.withoutExtension(path.basename(args.last));
+      final logName = '${testName}_${useDds ? "" : "no_"}dds_sizes.csv';
+      fullArgs.add('--log_service_response_sizes=$dir/$logName');
+    }
     fullArgs.addAll(args);
 
     return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
diff --git a/runtime/platform/elf.h b/runtime/platform/elf.h
index 8f58005..545e9e8 100644
--- a/runtime/platform/elf.h
+++ b/runtime/platform/elf.h
@@ -171,6 +171,7 @@
 static constexpr intptr_t EM_ARM = 40;
 static constexpr intptr_t EM_X86_64 = 62;
 static constexpr intptr_t EM_AARCH64 = 183;
+static constexpr intptr_t EM_RISCV = 243;
 
 static const intptr_t EV_CURRENT = 1;
 
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 8e8c737..28bf82c 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -197,40 +197,25 @@
 #if defined(_M_X64) || defined(__x86_64__)
 #define HOST_ARCH_X64 1
 #define ARCH_IS_64_BIT 1
-#define kFpuRegisterSize 16
-typedef simd128_value_t fpu_register_t;
 #elif defined(_M_IX86) || defined(__i386__)
 #define HOST_ARCH_IA32 1
 #define ARCH_IS_32_BIT 1
-#define kFpuRegisterSize 16
-typedef simd128_value_t fpu_register_t;
 #elif defined(__ARMEL__)
 #define HOST_ARCH_ARM 1
 #define ARCH_IS_32_BIT 1
-#define kFpuRegisterSize 16
-// Mark the fact that we have defined simd_value_t.
-#define SIMD_VALUE_T_
-typedef struct {
-  union {
-    uint32_t u;
-    float f;
-  } data_[4];
-} simd_value_t;
-typedef simd_value_t fpu_register_t;
-#define simd_value_safe_load(addr) (*reinterpret_cast<simd_value_t*>(addr))
-#define simd_value_safe_store(addr, value)                                     \
-  do {                                                                         \
-    reinterpret_cast<simd_value_t*>(addr)->data_[0] = value.data_[0];          \
-    reinterpret_cast<simd_value_t*>(addr)->data_[1] = value.data_[1];          \
-    reinterpret_cast<simd_value_t*>(addr)->data_[2] = value.data_[2];          \
-    reinterpret_cast<simd_value_t*>(addr)->data_[3] = value.data_[3];          \
-  } while (0)
-
 #elif defined(__aarch64__)
 #define HOST_ARCH_ARM64 1
 #define ARCH_IS_64_BIT 1
-#define kFpuRegisterSize 16
-typedef simd128_value_t fpu_register_t;
+#elif defined(__riscv)
+#if __SIZEOF_POINTER__ == 4
+#define HOST_ARCH_RISCV32 1
+#define ARCH_IS_32_BIT 1
+#elif __SIZEOF_POINTER__ == 8
+#define HOST_ARCH_RISCV64 1
+#define ARCH_IS_64_BIT 1
+#else
+#error Unknown XLEN
+#endif
 #else
 #error Architecture was not detected as supported by Dart.
 #endif
@@ -311,7 +296,8 @@
 #endif
 
 #if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_X64) &&                  \
-    !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64)
+    !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64) &&               \
+    !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
 // No target architecture specified pick the one matching the host architecture.
 #if defined(HOST_ARCH_ARM)
 #define TARGET_ARCH_ARM 1
@@ -321,14 +307,20 @@
 #define TARGET_ARCH_IA32 1
 #elif defined(HOST_ARCH_ARM64)
 #define TARGET_ARCH_ARM64 1
+#elif defined(HOST_ARCH_RISCV32)
+#define TARGET_ARCH_RISCV32 1
+#elif defined(HOST_ARCH_RISCV64)
+#define TARGET_ARCH_RISCV64 1
 #else
 #error Automatic target architecture detection failed.
 #endif
 #endif
 
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) ||                   \
+    defined(TARGET_ARCH_RISCV32)
 #define TARGET_ARCH_IS_32_BIT 1
-#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) ||                \
+    defined(TARGET_ARCH_RISCV64)
 #define TARGET_ARCH_IS_64_BIT 1
 #else
 #error Automatic target architecture detection failed.
@@ -340,11 +332,13 @@
 
 // Verify that host and target architectures match, we cannot
 // have a 64 bit Dart VM generating 32 bit code or vice-versa.
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_RISCV64)
 #if !defined(ARCH_IS_64_BIT) && !defined(FFI_UNIT_TESTS)
 #error Mismatched Host/Target architectures.
 #endif  // !defined(ARCH_IS_64_BIT) && !defined(FFI_UNIT_TESTS)
-#elif defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#elif defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) ||                 \
+    defined(TARGET_ARCH_RISCV32)
 #if defined(HOST_ARCH_X64) && defined(TARGET_ARCH_ARM)
 // This is simarm_x64, which is the only case where host/target architecture
 // mismatch is allowed. Unless, we're running FFI unit tests.
@@ -370,12 +364,18 @@
 #define USING_SIMULATOR 1
 #endif
 #endif
-
 #elif defined(TARGET_ARCH_ARM64)
 #if !defined(HOST_ARCH_ARM64)
 #define USING_SIMULATOR 1
 #endif
-
+#elif defined(TARGET_ARCH_RISCV32)
+#if !defined(HOST_ARCH_RISCV32)
+#define USING_SIMULATOR 1
+#endif
+#elif defined(TARGET_ARCH_RISCV64)
+#if !defined(HOST_ARCH_RISCV64)
+#define USING_SIMULATOR 1
+#endif
 #else
 #error Unknown architecture.
 #endif
@@ -653,7 +653,7 @@
 // gcc enough that it can no longer see that you have cast one pointer
 // type to another thus avoiding the warning.
 template <class D, class S>
-inline D bit_cast(const S& source) {
+DART_FORCE_INLINE D bit_cast(const S& source) {
   static_assert(sizeof(D) == sizeof(S),
                 "Source and destination must have the same size");
 
@@ -669,7 +669,7 @@
 // obscure details in the C++ standard that make reinterpret_cast
 // virtually useless.
 template <class D, class S>
-inline D bit_copy(const S& source) {
+DART_FORCE_INLINE D bit_copy(const S& source) {
   D destination;
   // This use of memcpy is safe: source and destination cannot overlap.
   memcpy(&destination, reinterpret_cast<const void*>(&source),
diff --git a/runtime/tests/vm/dart/deferred_loading_call_modes_test.dart b/runtime/tests/vm/dart/deferred_loading_call_modes_test.dart
index 954a3d9..0f155d2 100644
--- a/runtime/tests/vm/dart/deferred_loading_call_modes_test.dart
+++ b/runtime/tests/vm/dart/deferred_loading_call_modes_test.dart
@@ -2,9 +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.
 
-// VMOptions=--use_table_dispatch=false
-// VMOptions=--use_table_dispatch=true
-
 import "splay_test.dart" deferred as splay; // Some non-trivial code.
 
 main() async {
diff --git a/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart
new file mode 100644
index 0000000..74e128e
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:async';
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+
+void main() {
+  testWeakReference();
+}
+
+class Nonce {
+  final int value;
+
+  Nonce(this.value);
+
+  String toString() => 'Nonce($value)';
+}
+
+void testWeakReference() async {
+  final weakRef = () {
+    final object = Nonce(23);
+    final weakRef = WeakReference(object);
+    // Left to right argument evaluation: evaluate weakRef.target first.
+    Expect.equals(weakRef.target, object);
+    return weakRef;
+  }();
+
+  print('do gc');
+  triggerGc();
+  await Future.delayed(Duration(milliseconds: 1));
+  triggerGc();
+  await Future.delayed(Duration(milliseconds: 1));
+  triggerGc();
+  await Future.delayed(Duration(milliseconds: 1));
+  triggerGc();
+
+  // The weak reference should not target anything anymore.
+  Expect.isNull(weakRef.target);
+
+  print('End of test, shutting down.');
+}
+
+final void Function() triggerGc = () {
+  String _platformPath(String name, {String? path}) {
+    if (path == null) path = "";
+    if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
+      return path + "lib" + name + ".so";
+    if (Platform.isMacOS) return path + "lib" + name + ".dylib";
+    if (Platform.isWindows) return path + name + ".dll";
+    throw Exception("Platform not implemented");
+  }
+
+  DynamicLibrary dlopenPlatformSpecific(String name, {String? path}) {
+    String fullPath = _platformPath(name, path: path);
+    return DynamicLibrary.open(fullPath);
+  }
+
+  final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+  return ffiTestFunctions
+      .lookupFunction<Void Function(), void Function()>("TriggerGC");
+}();
diff --git a/runtime/tests/vm/dart/hash_map_probes_limit_test.dart b/runtime/tests/vm/dart/hash_map_probes_limit_test.dart
new file mode 100644
index 0000000..d1ab065
--- /dev/null
+++ b/runtime/tests/vm/dart/hash_map_probes_limit_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that a relatively large program (kernel compiler)
+// can be compiled with --hash_map_probes_limit.
+
+// VMOptions=--hash_map_probes_limit=1000
+
+import "package:vm/kernel_front_end.dart";
+
+main(List<String> args) async {
+  await runCompiler(createCompilerArgParser().parse(['--help']), '');
+}
diff --git a/runtime/tests/vm/dart/isolate_exit_sandwich_test.dart b/runtime/tests/vm/dart/isolate_exit_sandwich_test.dart
new file mode 100644
index 0000000..8a49598
--- /dev/null
+++ b/runtime/tests/vm/dart/isolate_exit_sandwich_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Checks that Kill message (generated for example by Isolate.exit) prevents
+// any more dart code being executed - in particular when dart code with
+// Isolate.exit() is invoked from native code, which in turns is invoked
+// from dart code(hence "sandwich"-test).
+
+import 'dart:async';
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:expect/expect.dart";
+import '../../../../tests/ffi/dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific('ffi_test_functions');
+
+final lookupAndCallWorkerThatCallsIsolateExit =
+    ffiTestFunctions.lookupFunction<Void Function(Int64), void Function(int)>(
+        'IsolateExitTest_LookupAndCallIsolateExit');
+
+@pragma('vm:entry-point')
+void recurseLookupAndCallWorker(int i) {
+  lookupAndCallWorkerThatCallsIsolateExit(i);
+  print(
+      'coming back after $i invocation of lookupAndCallWorkerThatCallsIsolateExit');
+  assert(false);
+}
+
+// This method is looked up and called by ffi method that ignores unwinding
+// error raised by 'Isolate.exit'.
+@pragma('vm:entry-point')
+Never callIsolateExit() {
+  Isolate.exit();
+}
+
+main(List<String> args) async {
+  if (args.length > 0) {
+    lookupAndCallWorkerThatCallsIsolateExit(4);
+    print('got back');
+    return;
+  }
+  ProcessResult result = await Process.run(
+      Platform.executable, <String>[Platform.script.toString(), 'worker']);
+  Expect.isTrue(result.exitCode != 0);
+  // The child process should be terminated before it had a chance
+  // to print "got back".
+  Expect.isFalse(result.stdout.contains('got back'));
+}
diff --git a/runtime/tests/vm/dart/regress_48043_test.dart b/runtime/tests/vm/dart/regress_48043_test.dart
new file mode 100644
index 0000000..19cf04f
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48043_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48043.
+// Verifies that loads which may call initializer are not forwarded to
+// a previously stored value if it could be an uninitialized sentinel.
+
+// VMOptions=--deterministic --optimization_counter_threshold=120
+
+import "package:expect/expect.dart";
+
+class LateField1 {
+  late int n;
+
+  LateField1() {
+    print(n);
+  }
+}
+
+class LateField2 {
+  late int n;
+
+  LateField2() {
+    print(n);
+    n = 31999;
+  }
+}
+
+class LateField3 {
+  late int n;
+
+  LateField3() {
+    print(n);
+    n = DateTime.now().millisecondsSinceEpoch;
+  }
+}
+
+void doTests() {
+  Expect.throws(() {
+    LateField1();
+  });
+  Expect.throws(() {
+    LateField2();
+  });
+  Expect.throws(() {
+    final obj = LateField3();
+    print(obj.n);
+  });
+}
+
+void main() {
+  for (int i = 0; i < 150; ++i) {
+    doTests();
+  }
+}
diff --git a/runtime/tests/vm/dart/regress_48196_test.dart b/runtime/tests/vm/dart/regress_48196_test.dart
new file mode 100644
index 0000000..4330ef9
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48196_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48196.
+// Verifies that compiler doesn't crash on unreachable code with conflicting
+// types in Unbox instruction.
+
+// Reduced from
+// The Dart Project Fuzz Tester (1.93).
+// Program generated as:
+//   dart dartfuzz.dart --seed 2879764895 --no-fp --no-ffi --flat
+
+// VMOptions=--deterministic --intrinsify=false --use-slow-path
+
+import 'dart:typed_data';
+
+Uint8List var8 = Uint8List.fromList(Uint16List.fromList(new Int8List(31)));
+String var82 = 'Ub#H-k';
+
+foo2() {
+  return Int32x4List(29).sublist(0, 1).sublist(-1, -59);
+}
+
+foo0_Extension0() {
+  Uri.encodeComponent(var82);
+}
+
+MapEntry<String, bool> foo1_Extension0() {
+  for (int loc2 in (Int8List.fromList(var8))) {}
+  return foo1_Extension0();
+}
+
+main() {
+  try {
+    foo2();
+  } catch (e, st) {}
+  try {
+    foo0_Extension0();
+  } catch (e, st) {}
+  try {
+    foo1_Extension0();
+  } catch (e, st) {}
+}
diff --git a/runtime/tests/vm/dart/splay_test.dart b/runtime/tests/vm/dart/splay_test.dart
index 7e974a1..1abb197 100644
--- a/runtime/tests/vm/dart/splay_test.dart
+++ b/runtime/tests/vm/dart/splay_test.dart
@@ -27,6 +27,7 @@
 // VMOptions=--verify_store_buffer
 // VMOptions=--stress_write_barrier_elimination
 // VMOptions=--old_gen_heap_size=100
+// VMOptions=--mark_when_idle
 
 import "dart:math";
 import 'package:benchmark_harness/benchmark_harness.dart';
diff --git a/runtime/tests/vm/dart/typed_data_aot_not_inlining_il_test.dart b/runtime/tests/vm/dart/typed_data_aot_not_inlining_il_test.dart
new file mode 100644
index 0000000..4b50aea
--- /dev/null
+++ b/runtime/tests/vm/dart/typed_data_aot_not_inlining_il_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test asserts that we are not inlining accesses to typed data interfaces
+// (e.g. Uint8List) if there are instantiated 3rd party classes (e.g.
+// UnmodifiableUint8ListView).
+
+import 'dart:typed_data';
+import 'package:vm/testing/il_matchers.dart';
+
+createThirdPartyUint8List() => UnmodifiableUint8ListView(Uint8List(10));
+
+@pragma('vm:never-inline')
+@pragma('vm:testing:print-flow-graph')
+void foo(Uint8List list, int from) {
+  if (from >= list.length) {
+    list[from];
+  }
+}
+
+void matchIL$foo(FlowGraph graph) {
+  graph.match([
+    match.block('Graph'),
+    match.block('Function', [
+      'list' << match.Parameter(index: 0),
+      'from' << match.Parameter(index: 1),
+      'v13' << match.LoadClassId('list'),
+      match.PushArgument('list'),
+      match.DispatchTableCall('v13', selector_name: 'get:length'),
+      match.Branch(match.RelationalOp(match.any, match.any, kind: '>='),
+          ifTrue: 'B3'),
+    ]),
+    'B3' <<
+        match.block('Target', [
+          'v15' << match.LoadClassId('list'),
+          match.PushArgument('list'),
+          match.PushArgument(/* BoxInt64(Parameter) or Parameter */),
+          match.DispatchTableCall('v15', selector_name: '[]'),
+        ]),
+  ]);
+}
+
+void main() {
+  foo(int.parse('1') == 1 ? createThirdPartyUint8List() : Uint8List(1),
+      int.parse('0'));
+}
diff --git a/runtime/tests/vm/dart/typed_data_aot_regress43534_il_test.dart b/runtime/tests/vm/dart/typed_data_aot_regress43534_il_test.dart
new file mode 100644
index 0000000..50fe78c
--- /dev/null
+++ b/runtime/tests/vm/dart/typed_data_aot_regress43534_il_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:typed_data';
+import 'package:vm/testing/il_matchers.dart';
+
+@pragma('vm:never-inline')
+void callWith<T>(void Function(T arg) fun, T arg) {
+  fun(arg);
+}
+
+@pragma('vm:testing:match-inner-flow-graph', 'foo')
+void main() {
+  @pragma('vm:testing:print-flow-graph')
+  foo(Uint8List list) {
+    if (list[0] != 0) throw 'a';
+  }
+
+  callWith<Uint8List>(foo, Uint8List(10));
+}
+
+void matchIL$main(FlowGraph graph) {}
+
+void matchIL$main_foo(FlowGraph graph) {
+  graph.match([
+    match.block('Graph'),
+    match.block('Function', [
+      match.LoadField(),
+      match.GenericCheckBound(),
+      match.LoadUntagged(),
+      match.LoadIndexed(),
+    ]),
+  ]);
+}
diff --git a/runtime/tests/vm/dart/untyped_function_invocation_with_known_function_type_test.dart b/runtime/tests/vm/dart/untyped_function_invocation_with_known_function_type_test.dart
new file mode 100644
index 0000000..9c16501
--- /dev/null
+++ b/runtime/tests/vm/dart/untyped_function_invocation_with_known_function_type_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that compiler doesn't crash when it sees untyped function
+// invocation (FunctionAccessKind.Function) but receiver has a known
+// function type.
+
+import "package:expect/expect.dart";
+
+bool ok = false;
+bool _defaultCheck([dynamic _]) => true;
+
+void foo<T>(bool Function(T error)? check, Object e) {
+  // Function call on the result of 'check ?? _defaultCheck' is untyped
+  // (assumes static type Function). However, AOT compiler can eliminate
+  // null test and might be able to reduce the expression to 'check' with
+  // known function type.
+  if (e is T && (check ?? _defaultCheck)(e)) {
+    ok = true;
+  }
+}
+
+void main() {
+  foo<String>((_) => true, 'hi');
+  Expect.isTrue(ok);
+}
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index 26cc7c7..1af4fa3 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -108,7 +108,6 @@
 Future<void> testAOT(String dillPath,
     {bool useAsm = false,
     bool forceDrops = false,
-    bool useDispatch = true,
     bool stripUtil = false, // Note: forced true if useAsm.
     bool stripFlag = false,
     bool disassemble = false}) async {
@@ -129,9 +128,6 @@
   if (forceDrops) {
     descriptionBuilder.write('-dropped');
   }
-  if (!useDispatch) {
-    descriptionBuilder.write('-nodispatch');
-  }
   if (stripFlag) {
     descriptionBuilder.write('-intstrip');
   }
@@ -158,7 +154,6 @@
         '--no-retain-function-objects',
         '--no-retain-code-objects'
       ],
-      useDispatch ? '--use-table-dispatch' : '--no-use-table-dispatch',
       if (disassemble) '--disassemble', // Not defined in PRODUCT mode.
       dillPath,
     ];
@@ -434,7 +429,6 @@
     // Test unstripped ELF generation directly.
     await testAOT(aotDillPath);
     await testAOT(aotDillPath, forceDrops: true);
-    await testAOT(aotDillPath, forceDrops: true, useDispatch: false);
 
     // Test flag-stripped ELF generation.
     await testAOT(aotDillPath, stripFlag: true);
diff --git a/runtime/tests/vm/dart_2/deferred_loading_call_modes_test.dart b/runtime/tests/vm/dart_2/deferred_loading_call_modes_test.dart
index 5efc2bd..940c992 100644
--- a/runtime/tests/vm/dart_2/deferred_loading_call_modes_test.dart
+++ b/runtime/tests/vm/dart_2/deferred_loading_call_modes_test.dart
@@ -4,9 +4,6 @@
 
 // @dart = 2.9
 
-// VMOptions=--use_table_dispatch=false
-// VMOptions=--use_table_dispatch=true
-
 import "splay_test.dart" deferred as splay; // Some non-trivial code.
 
 main() async {
diff --git a/runtime/tests/vm/dart_2/hash_map_probes_limit_test.dart b/runtime/tests/vm/dart_2/hash_map_probes_limit_test.dart
new file mode 100644
index 0000000..09ff68b
--- /dev/null
+++ b/runtime/tests/vm/dart_2/hash_map_probes_limit_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that a relatively large program (kernel compiler)
+// can be compiled with --hash_map_probes_limit.
+
+// VMOptions=--hash_map_probes_limit=1000
+
+// @dart = 2.9
+
+import "package:vm/kernel_front_end.dart";
+
+main(List<String> args) async {
+  await runCompiler(createCompilerArgParser().parse(['--help']), '');
+}
diff --git a/runtime/tests/vm/dart_2/isolate_exit_sandwich_test.dart b/runtime/tests/vm/dart_2/isolate_exit_sandwich_test.dart
new file mode 100644
index 0000000..0b0a08c
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolate_exit_sandwich_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Checks that Kill message (generated for example by Isolate.exit) prevents
+// any more dart code being executed - in particular when dart code with
+// Isolate.exit() is invoked from native code, which in turns is invoked
+// from dart code(hence "sandwich"-test).
+
+// @dart = 2.9
+
+import 'dart:async';
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:expect/expect.dart";
+import '../../../../tests/ffi/dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific('ffi_test_functions');
+
+final lookupAndCallWorkerThatCallsIsolateExit =
+    ffiTestFunctions.lookupFunction<Void Function(Int64), void Function(int)>(
+        'IsolateExitTest_LookupAndCallIsolateExit');
+
+@pragma('vm:entry-point')
+void recurseLookupAndCallWorker(int i) {
+  lookupAndCallWorkerThatCallsIsolateExit(i);
+  print(
+      'coming back after $i invocation of lookupAndCallWorkerThatCallsIsolateExit');
+}
+
+// This method is looked up and called by ffi method that ignores unwinding
+// error raised by 'Isolate.exit'.
+@pragma('vm:entry-point')
+Never callIsolateExit() {
+  Isolate.exit();
+}
+
+main(List<String> args) async {
+  if (args.length > 0) {
+    lookupAndCallWorkerThatCallsIsolateExit(4);
+    print('got back');
+    return;
+  }
+  ProcessResult result = await Process.run(
+      Platform.executable, <String>[Platform.script.toString(), 'worker']);
+  Expect.isTrue(result.exitCode != 0);
+  // The child process should be terminated before it had a chance
+  // to print "got back".
+  Expect.isFalse(result.stdout.contains('got back'));
+}
diff --git a/runtime/tests/vm/dart_2/regress_48196_test.dart b/runtime/tests/vm/dart_2/regress_48196_test.dart
new file mode 100644
index 0000000..4330ef9
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_48196_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48196.
+// Verifies that compiler doesn't crash on unreachable code with conflicting
+// types in Unbox instruction.
+
+// Reduced from
+// The Dart Project Fuzz Tester (1.93).
+// Program generated as:
+//   dart dartfuzz.dart --seed 2879764895 --no-fp --no-ffi --flat
+
+// VMOptions=--deterministic --intrinsify=false --use-slow-path
+
+import 'dart:typed_data';
+
+Uint8List var8 = Uint8List.fromList(Uint16List.fromList(new Int8List(31)));
+String var82 = 'Ub#H-k';
+
+foo2() {
+  return Int32x4List(29).sublist(0, 1).sublist(-1, -59);
+}
+
+foo0_Extension0() {
+  Uri.encodeComponent(var82);
+}
+
+MapEntry<String, bool> foo1_Extension0() {
+  for (int loc2 in (Int8List.fromList(var8))) {}
+  return foo1_Extension0();
+}
+
+main() {
+  try {
+    foo2();
+  } catch (e, st) {}
+  try {
+    foo0_Extension0();
+  } catch (e, st) {}
+  try {
+    foo1_Extension0();
+  } catch (e, st) {}
+}
diff --git a/runtime/tests/vm/dart_2/splay_test.dart b/runtime/tests/vm/dart_2/splay_test.dart
index a793419..f1b401e 100644
--- a/runtime/tests/vm/dart_2/splay_test.dart
+++ b/runtime/tests/vm/dart_2/splay_test.dart
@@ -31,6 +31,7 @@
 // VMOptions=--verify_store_buffer
 // VMOptions=--stress_write_barrier_elimination
 // VMOptions=--old_gen_heap_size=100
+// VMOptions=--mark_when_idle
 
 import "dart:math";
 import 'package:benchmark_harness/benchmark_harness.dart';
diff --git a/runtime/tests/vm/dart_2/typed_data_aot_not_inlining_il_test.dart b/runtime/tests/vm/dart_2/typed_data_aot_not_inlining_il_test.dart
new file mode 100644
index 0000000..4b50aea
--- /dev/null
+++ b/runtime/tests/vm/dart_2/typed_data_aot_not_inlining_il_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test asserts that we are not inlining accesses to typed data interfaces
+// (e.g. Uint8List) if there are instantiated 3rd party classes (e.g.
+// UnmodifiableUint8ListView).
+
+import 'dart:typed_data';
+import 'package:vm/testing/il_matchers.dart';
+
+createThirdPartyUint8List() => UnmodifiableUint8ListView(Uint8List(10));
+
+@pragma('vm:never-inline')
+@pragma('vm:testing:print-flow-graph')
+void foo(Uint8List list, int from) {
+  if (from >= list.length) {
+    list[from];
+  }
+}
+
+void matchIL$foo(FlowGraph graph) {
+  graph.match([
+    match.block('Graph'),
+    match.block('Function', [
+      'list' << match.Parameter(index: 0),
+      'from' << match.Parameter(index: 1),
+      'v13' << match.LoadClassId('list'),
+      match.PushArgument('list'),
+      match.DispatchTableCall('v13', selector_name: 'get:length'),
+      match.Branch(match.RelationalOp(match.any, match.any, kind: '>='),
+          ifTrue: 'B3'),
+    ]),
+    'B3' <<
+        match.block('Target', [
+          'v15' << match.LoadClassId('list'),
+          match.PushArgument('list'),
+          match.PushArgument(/* BoxInt64(Parameter) or Parameter */),
+          match.DispatchTableCall('v15', selector_name: '[]'),
+        ]),
+  ]);
+}
+
+void main() {
+  foo(int.parse('1') == 1 ? createThirdPartyUint8List() : Uint8List(1),
+      int.parse('0'));
+}
diff --git a/runtime/tests/vm/dart_2/typed_data_aot_regress43534_il_test.dart b/runtime/tests/vm/dart_2/typed_data_aot_regress43534_il_test.dart
new file mode 100644
index 0000000..50fe78c
--- /dev/null
+++ b/runtime/tests/vm/dart_2/typed_data_aot_regress43534_il_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:typed_data';
+import 'package:vm/testing/il_matchers.dart';
+
+@pragma('vm:never-inline')
+void callWith<T>(void Function(T arg) fun, T arg) {
+  fun(arg);
+}
+
+@pragma('vm:testing:match-inner-flow-graph', 'foo')
+void main() {
+  @pragma('vm:testing:print-flow-graph')
+  foo(Uint8List list) {
+    if (list[0] != 0) throw 'a';
+  }
+
+  callWith<Uint8List>(foo, Uint8List(10));
+}
+
+void matchIL$main(FlowGraph graph) {}
+
+void matchIL$main_foo(FlowGraph graph) {
+  graph.match([
+    match.block('Graph'),
+    match.block('Function', [
+      match.LoadField(),
+      match.GenericCheckBound(),
+      match.LoadUntagged(),
+      match.LoadIndexed(),
+    ]),
+  ]);
+}
diff --git a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
index cf3e581..21db861 100644
--- a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
@@ -110,7 +110,6 @@
 Future<void> testAOT(String dillPath,
     {bool useAsm = false,
     bool forceDrops = false,
-    bool useDispatch = true,
     bool stripUtil = false, // Note: forced true if useAsm.
     bool stripFlag = false,
     bool disassemble = false}) async {
@@ -131,9 +130,6 @@
   if (forceDrops) {
     descriptionBuilder.write('-dropped');
   }
-  if (!useDispatch) {
-    descriptionBuilder.write('-nodispatch');
-  }
   if (stripFlag) {
     descriptionBuilder.write('-intstrip');
   }
@@ -160,7 +156,6 @@
         '--no-retain-function-objects',
         '--no-retain-code-objects'
       ],
-      useDispatch ? '--use-table-dispatch' : '--no-use-table-dispatch',
       if (disassemble) '--disassemble', // Not defined in PRODUCT mode.
       dillPath,
     ];
@@ -428,7 +423,6 @@
     // Test unstripped ELF generation directly.
     await testAOT(aotDillPath);
     await testAOT(aotDillPath, forceDrops: true);
-    await testAOT(aotDillPath, forceDrops: true, useDispatch: false);
 
     // Test flag-stripped ELF generation.
     await testAOT(aotDillPath, stripFlag: true);
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 0685477..fdb96d1 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -15,6 +15,7 @@
 dart/byte_array_optimized_test: Pass, Slow
 dart/data_uri_import_test/none: SkipByDesign
 dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
+dart/hash_map_probes_limit_test: Pass, Slow # Test includes large program compilation.
 dart/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
 dart/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
 dart/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
@@ -28,6 +29,7 @@
 dart_2/byte_array_optimized_test: Pass, Slow
 dart_2/data_uri_import_test/none: SkipByDesign
 dart_2/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
+dart_2/hash_map_probes_limit_test: Pass, Slow # Test includes large program compilation.
 dart_2/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
 dart_2/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
 dart_2/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
@@ -64,12 +66,14 @@
 
 [ $builder_tag == tsan ]
 dart/appjit_cha_deopt_test: SkipSlow
+dart/hash_map_probes_limit_test: SkipSlow # Test includes large program compilation.
 dart/regress_40462_test: SkipSlow
 dart/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
 dart/v8_snapshot_profile_writer_test: SkipSlow
 dart_2/appjit_cha_deopt_test: SkipSlow
+dart_2/hash_map_probes_limit_test: SkipSlow # Test includes large program compilation.
 dart_2/regress_40462_test: SkipSlow
 dart_2/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
@@ -127,12 +131,14 @@
 cc/VerifyImplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 dart/b162922506_test: SkipSlow # Generates very large input file
+dart/hash_map_probes_limit_test: SkipSlow # Test includes large program compilation.
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
 dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
 dart/type_casts_with_null_safety_autodetection_test: Pass, Slow # Very slow in debug mode, uses --optimization-counter-threshold=10
 dart_2/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 dart_2/b162922506_test: SkipSlow # Generates very large input file
+dart_2/hash_map_probes_limit_test: SkipSlow # Test includes large program compilation.
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
 dart_2/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
@@ -168,9 +174,7 @@
 [ $system == windows ]
 cc/CorelibCompilerStats: Skip
 dart/disassemble_determinism_test: Slow, Pass # Times out on slower bots.
-dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/40579: Dart C API symbols not available.
 dart_2/disassemble_determinism_test: Slow, Pass # Times out on slower bots.
-dart_2/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/40579: Dart C API symbols not available.
 
 [ $arch == ia32 && $mode == debug && $system == windows ]
 dart/transferable_test: Skip # This is performance test and somehow debug win ia32 bot's performance is unpredictable
@@ -275,6 +279,11 @@
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
 dart_2/snapshot_depfile_test: SkipByDesign # Test needs to run from source
 
+[ $compiler == dartkp && $system == windows ]
+dart/finalizer/weak_reference_run_gc_test: SkipByDesign # https://dartbug.com/40579 Dart C API symbols not available.
+dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/40579 Dart C API symbols not available.
+dart_2/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/40579 Dart C API symbols not available.
+
 [ $compiler == dartkp && ($arch == simarm || $arch == simarm64 || $arch == simarm64c) ]
 dart/causal_stacks/async_throws_stack_lazy_non_symbolic_test: Pass, Slow
 dart_2/causal_stacks/async_throws_stack_lazy_non_symbolic_test: Pass, Slow
@@ -317,11 +326,11 @@
 # up with the real Dart stack trace and hence we don't get correct
 # symbol names.
 [ $arch == simarm || $arch == simarm64 || $arch == simarm64c ]
-cc/DartAPI_NativeFieldAccess: Skip # Test uses dart:ffi which is not supported on simulators.
-cc/DartAPI_NativeFieldAccess_Throws: Skip # Test uses dart:ffi which is not supported on simulators.
-cc/Dart_SetFfiNativeResolver: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-cc/Dart_SetFfiNativeResolver_DoesNotResolve: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-cc/Dart_SetFfiNativeResolver_MissingResolver: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
+cc/DartAPI_NativeFieldAccess: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+cc/DartAPI_NativeFieldAccess_Throws: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+cc/Dart_SetFfiNativeResolver: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+cc/Dart_SetFfiNativeResolver_DoesNotResolve: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+cc/Dart_SetFfiNativeResolver_MissingResolver: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
 cc/LargeMap: SkipByDesign
 cc/Profiler_AllocationSampleTest: SkipByDesign
 cc/Profiler_ArrayAllocation: SkipByDesign
@@ -348,20 +357,21 @@
 cc/Profiler_TrivialRecordAllocation: SkipByDesign
 cc/Profiler_TypedArrayAllocation: SkipByDesign
 cc/Service_Profile: SkipByDesign
-dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-dart/isolates/thread_pool_test: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-dart/regress_41971_test: SkipByDesign # dart:ffi is not supported on simulator
+dart/finalizer/weak_reference_run_gc_test: SkipByDesign # https://dartbug.com/37299 FFI not yet supported on simulators.
+dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+dart/isolates/thread_pool_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+dart/regress_41971_test: SkipByDesign # https://dartbug.com/37299 dart:ffi is not supported on simulator
 dart/sdk_hash_test: SkipSlow # gen_kernel is slow to run on simarm
-dart/unboxed_param_args_descriptor_test: SkipByDesign # FFI helper not supported on simulator
-dart/unboxed_param_tear_off_test: SkipByDesign # FFI helper not supported on simulator
-dart/unboxed_param_test: SkipByDesign # FFI helper not supported on simulator
-dart_2/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-dart_2/isolates/thread_pool_test: SkipByDesign # Test uses dart:ffi which is not supported on simulators.
-dart_2/regress_41971_test: SkipByDesign # dart:ffi is not supported on simulator
+dart/unboxed_param_args_descriptor_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
+dart/unboxed_param_tear_off_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
+dart/unboxed_param_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
+dart_2/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+dart_2/isolates/thread_pool_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
+dart_2/regress_41971_test: SkipByDesign # https://dartbug.com/37299 dart:ffi is not supported on simulator
 dart_2/sdk_hash_test: SkipSlow # gen_kernel is slow to run on simarm
-dart_2/unboxed_param_args_descriptor_test: SkipByDesign # FFI helper not supported on simulator
-dart_2/unboxed_param_tear_off_test: SkipByDesign # FFI helper not supported on simulator
-dart_2/unboxed_param_test: SkipByDesign # FFI helper not supported on simulator
+dart_2/unboxed_param_args_descriptor_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
+dart_2/unboxed_param_tear_off_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
+dart_2/unboxed_param_test: SkipByDesign # https://dartbug.com/37299 FFI helper not supported on simulator
 
 [ $arch == simarm || $arch == simarm64 || $arch == simarm64c || $system != macos ]
 dart/thread_priority_macos_test: SkipByDesign
diff --git a/runtime/third_party/double-conversion/src/utils.h b/runtime/third_party/double-conversion/src/utils.h
index 51d5e61..c419a6c 100644
--- a/runtime/third_party/double-conversion/src/utils.h
+++ b/runtime/third_party/double-conversion/src/utils.h
@@ -67,16 +67,14 @@
 // the output of the division with the expected result. (Inlining must be
 // disabled.)
 // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
-#if defined(_M_X64) || defined(__x86_64__) || \
-    defined(__ARMEL__) || defined(__avr32__) || \
-    defined(__hppa__) || defined(__ia64__) || \
-    defined(__mips__) || \
-    defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
-    defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
-    defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
-    defined(__SH4__) || defined(__alpha__) || \
-    defined(_MIPS_ARCH_MIPS32R2) || \
-    defined(__AARCH64EL__) || defined(__aarch64__)
+#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) ||            \
+    defined(__avr32__) || defined(__hppa__) || defined(__ia64__) ||            \
+    defined(__mips__) || defined(__powerpc__) || defined(__ppc__) ||           \
+    defined(__ppc64__) || defined(_POWER) || defined(_ARCH_PPC) ||             \
+    defined(_ARCH_PPC64) || defined(__sparc__) || defined(__sparc) ||          \
+    defined(__s390__) || defined(__SH4__) || defined(__alpha__) ||             \
+    defined(_MIPS_ARCH_MIPS32R2) || defined(__AARCH64EL__) ||                  \
+    defined(__aarch64__) || defined(__riscv)
 #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
 #elif defined(__mc68000__)
 #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index b6e32b7..6cf216e 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -112,12 +112,16 @@
     if (mode.endsWith('debug-arm32')) return 'DebugSIMARM';
     if (mode.endsWith('debug-arm64')) return 'DebugSIMARM64';
     if (mode.endsWith('debug-arm64c')) return 'DebugSIMARM64C';
+    if (mode.endsWith('debug-riscv32')) return 'DebugSIMRISCV32';
+    if (mode.endsWith('debug-riscv64')) return 'DebugSIMRISCV64';
     if (mode.endsWith('ia32')) return 'ReleaseIA32';
     if (mode.endsWith('x64')) return 'ReleaseX64';
     if (mode.endsWith('x64c')) return 'ReleaseX64C';
     if (mode.endsWith('arm32')) return 'ReleaseSIMARM';
     if (mode.endsWith('arm64')) return 'ReleaseSIMARM64';
     if (mode.endsWith('arm64c')) return 'ReleaseSIMARM64C';
+    if (mode.endsWith('riscv32')) return 'ReleaseSIMRISCV32';
+    if (mode.endsWith('riscv64')) return 'ReleaseSIMRISCV64';
     throw ('unknown tag in mode: $mode');
   }
 
@@ -333,7 +337,8 @@
       ((mode1.contains('arm32') && mode2.contains('arm32')) ||
           (mode1.contains('arm64') && mode2.contains('arm64')) ||
           (mode1.contains('x64') && mode2.contains('x64')) ||
-          (mode1.contains('ia32') && mode2.contains('ia32')));
+          (mode1.contains('riscv32') && mode2.contains('riscv32')) ||
+          (mode1.contains('riscv64') && mode2.contains('riscv64')));
 
   bool ffiCapable(String mode1, String mode2) =>
       mode1.startsWith('jit') &&
@@ -676,12 +681,16 @@
     'jit-debug-arm32',
     'jit-debug-arm64',
     'jit-debug-arm64c',
+    'jit-debug-riscv32',
+    'jit-debug-riscv64',
     'jit-ia32',
     'jit-x64',
     'jit-x64c',
     'jit-arm32',
     'jit-arm64',
     'jit-arm64c',
+    'jit-riscv32',
+    'jit-riscv64',
     'aot-debug-x64',
     'aot-debug-x64c',
     'aot-x64',
@@ -694,9 +703,13 @@
     'aot-debug-arm32',
     'aot-debug-arm64',
     'aot-debug-arm64c',
+    'aot-debug-riscv32',
+    'aot-debug-riscv64',
     'aot-arm32',
     'aot-arm64',
     'aot-arm64c',
+    'aot-riscv32',
+    'aot-riscv64',
     // Too many divergences (due to arithmetic):
     'js-x64',
   ];
diff --git a/runtime/tools/run_clang_tidy.dart b/runtime/tools/run_clang_tidy.dart
index aa32b3b..84b66e8 100644
--- a/runtime/tools/run_clang_tidy.dart
+++ b/runtime/tools/run_clang_tidy.dart
@@ -79,22 +79,26 @@
   'runtime/platform/utils_linux.h',
   'runtime/platform/utils_macos.h',
   'runtime/platform/utils_win.h',
-  'runtime/vm/compiler/assembler/assembler_arm64.h',
   'runtime/vm/compiler/assembler/assembler_arm.h',
+  'runtime/vm/compiler/assembler/assembler_arm64.h',
   'runtime/vm/compiler/assembler/assembler_ia32.h',
+  'runtime/vm/compiler/assembler/assembler_riscv.h',
   'runtime/vm/compiler/assembler/assembler_x64.h',
   'runtime/vm/compiler/runtime_offsets_extracted.h',
-  'runtime/vm/constants_arm64.h',
   'runtime/vm/constants_arm.h',
+  'runtime/vm/constants_arm64.h',
   'runtime/vm/constants_ia32.h',
+  'runtime/vm/constants_riscv.h',
   'runtime/vm/constants_x64.h',
-  'runtime/vm/cpu_arm64.h',
   'runtime/vm/cpu_arm.h',
+  'runtime/vm/cpu_arm64.h',
   'runtime/vm/cpu_ia32.h',
+  'runtime/vm/cpu_riscv.h',
   'runtime/vm/cpu_x64.h',
-  'runtime/vm/instructions_arm64.h',
   'runtime/vm/instructions_arm.h',
+  'runtime/vm/instructions_arm64.h',
   'runtime/vm/instructions_ia32.h',
+  'runtime/vm/instructions_riscv.h',
   'runtime/vm/instructions_x64.h',
   'runtime/vm/os_thread_android.h',
   'runtime/vm/os_thread_fuchsia.h',
@@ -104,9 +108,11 @@
   'runtime/vm/regexp_assembler_bytecode_inl.h',
   'runtime/vm/simulator_arm64.h',
   'runtime/vm/simulator_arm.h',
-  'runtime/vm/stack_frame_arm64.h',
+  'runtime/vm/simulator_riscv.h',
   'runtime/vm/stack_frame_arm.h',
+  'runtime/vm/stack_frame_arm64.h',
   'runtime/vm/stack_frame_ia32.h',
+  'runtime/vm/stack_frame_riscv.h',
   'runtime/vm/stack_frame_x64.h',
 
   // Only available in special builds
diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc
index de02c85..fd5ab028 100644
--- a/runtime/vm/app_snapshot.cc
+++ b/runtime/vm/app_snapshot.cc
@@ -2820,7 +2820,7 @@
       s->AssignRef(map);
       AutoTraceObject(map);
       const intptr_t length = UntaggedCompressedStackMaps::SizeField::decode(
-          map->untag()->payload()->flags_and_size);
+          map->untag()->payload()->flags_and_size());
       s->WriteUnsigned(length);
       target_memory_size_ +=
           compiler::target::CompressedStackMaps::InstanceSize(length);
@@ -2832,9 +2832,9 @@
     for (intptr_t i = 0; i < count; i++) {
       CompressedStackMapsPtr map = objects_[i];
       AutoTraceObject(map);
-      s->WriteUnsigned(map->untag()->payload()->flags_and_size);
+      s->WriteUnsigned(map->untag()->payload()->flags_and_size());
       const intptr_t length = UntaggedCompressedStackMaps::SizeField::decode(
-          map->untag()->payload()->flags_and_size);
+          map->untag()->payload()->flags_and_size());
       uint8_t* cdata =
           reinterpret_cast<uint8_t*>(map->untag()->payload()->data());
       s->WriteBytes(cdata, length);
@@ -2874,7 +2874,7 @@
           static_cast<CompressedStackMapsPtr>(d->Ref(id));
       Deserializer::InitializeHeader(map, kCompressedStackMapsCid,
                                      CompressedStackMaps::InstanceSize(length));
-      map->untag()->payload()->flags_and_size = flags_and_size;
+      map->untag()->payload()->set_flags_and_size(flags_and_size);
       uint8_t* cdata =
           reinterpret_cast<uint8_t*>(map->untag()->payload()->data());
       d->ReadBytes(cdata, length);
@@ -6978,7 +6978,7 @@
 
     // Now write collected stack maps after the binary search table.
     auto write_stack_map = [&](CompressedStackMapsPtr smap) {
-      const auto flags_and_size = smap->untag()->payload()->flags_and_size;
+      const auto flags_and_size = smap->untag()->payload()->flags_and_size();
       const auto payload_size =
           UntaggedCompressedStackMaps::SizeField::decode(flags_and_size);
       pc_mapping.WriteFixed<uint32_t>(flags_and_size);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index ca3d03c..20a2d74e 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -138,16 +138,6 @@
   V(String_toLowerCase, 1)                                                     \
   V(String_toUpperCase, 1)                                                     \
   V(String_concatRange, 3)                                                     \
-  V(Math_sqrt, 1)                                                              \
-  V(Math_sin, 1)                                                               \
-  V(Math_cos, 1)                                                               \
-  V(Math_tan, 1)                                                               \
-  V(Math_asin, 1)                                                              \
-  V(Math_acos, 1)                                                              \
-  V(Math_atan, 1)                                                              \
-  V(Math_atan2, 2)                                                             \
-  V(Math_exp, 1)                                                               \
-  V(Math_log, 1)                                                               \
   V(Math_doublePow, 2)                                                         \
   V(Random_nextState, 1)                                                       \
   V(Random_setupSeed, 1)                                                       \
@@ -330,11 +320,9 @@
   V(GrowableList_setData, 2)                                                   \
   V(Internal_unsafeCast, 1)                                                    \
   V(Internal_nativeEffect, 1)                                                  \
-  V(Internal_reachabilityFence, 1)                                             \
   V(Internal_collectAllGarbage, 0)                                             \
   V(Internal_makeListFixedLength, 1)                                           \
   V(Internal_makeFixedListUnmodifiable, 1)                                     \
-  V(Internal_has63BitSmis, 0)                                                  \
   V(Internal_extractTypeArguments, 2)                                          \
   V(Internal_prependTypeArguments, 4)                                          \
   V(Internal_boundsCheckForPartialInstantiation, 2)                            \
@@ -345,10 +333,6 @@
   V(Internal_deoptimizeFunctionsOnStack, 0)                                    \
   V(InvocationMirror_unpackTypeArguments, 2)                                   \
   V(NoSuchMethodError_existingMethodSignature, 3)                              \
-  V(WeakProperty_getKey, 1)                                                    \
-  V(WeakProperty_setKey, 2)                                                    \
-  V(WeakProperty_getValue, 1)                                                  \
-  V(WeakProperty_setValue, 2)                                                  \
   V(Uri_isWindowsPlatform, 0)                                                  \
   V(UserTag_new, 2)                                                            \
   V(UserTag_label, 1)                                                          \
@@ -361,7 +345,7 @@
   V(VMService_OnStart, 0)                                                      \
   V(VMService_OnExit, 0)                                                       \
   V(VMService_OnServerAddressChange, 1)                                        \
-  V(VMService_ListenStream, 1)                                                 \
+  V(VMService_ListenStream, 2)                                                 \
   V(VMService_CancelStream, 1)                                                 \
   V(VMService_RequestAssets, 0)                                                \
   V(VMService_DecodeAssets, 1)                                                 \
@@ -375,7 +359,6 @@
   V(Ffi_loadUint16, 2)                                                         \
   V(Ffi_loadUint32, 2)                                                         \
   V(Ffi_loadUint64, 2)                                                         \
-  V(Ffi_loadIntPtr, 2)                                                         \
   V(Ffi_loadFloat, 2)                                                          \
   V(Ffi_loadDouble, 2)                                                         \
   V(Ffi_loadPointer, 2)                                                        \
@@ -388,7 +371,6 @@
   V(Ffi_storeUint16, 3)                                                        \
   V(Ffi_storeUint32, 3)                                                        \
   V(Ffi_storeUint64, 3)                                                        \
-  V(Ffi_storeIntPtr, 3)                                                        \
   V(Ffi_storeFloat, 3)                                                         \
   V(Ffi_storeDouble, 3)                                                        \
   V(Ffi_storePointer, 3)                                                       \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 2d58396..587b538 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1133,7 +1133,7 @@
   }
   FinalizeMemberTypes(cls);
 
-  if (cls.is_enum_class()) {
+  if (cls.is_enum_class() && !FLAG_precompiled_mode) {
     AllocateEnumValues(cls);
   }
 
@@ -1216,69 +1216,55 @@
   }
 }
 
-// Allocate instances for each enumeration value, and populate the
-// static field 'values'.
-// By allocating the instances programmatically, we save an implicit final
-// getter function object for each enumeration value and for the
-// values field. We also don't have to generate the code for these getters
-// from thin air (no source code is available).
+// Eagerly allocate instances for enumeration values by evaluating
+// static const field 'values'. Also, pre-allocate
+// deleted sentinel value. This is needed to correctly
+// migrate enumeration values in case of hot reload.
 void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
 
-  // The enum_cls is the actual declared class.
-  // The shared super-class holds the fields for index and name.
-  const Class& super_cls = Class::Handle(zone, enum_cls.SuperClass());
+  const auto& values_field =
+      Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values()));
+  if (!values_field.IsNull()) {
+    ASSERT(values_field.is_static() && values_field.is_const());
 
-  const Field& index_field =
-      Field::Handle(zone, super_cls.LookupInstanceField(Symbols::Index()));
+    const auto& values =
+        Object::Handle(zone, values_field.StaticConstFieldValue());
+    if (values.IsError()) {
+      ReportError(Error::Cast(values));
+    }
+    ASSERT(values.IsArray());
+  }
+
+  const auto& index_field =
+      Field::Handle(zone, object_store->enum_index_field());
   ASSERT(!index_field.IsNull());
 
-  const Field& name_field = Field::Handle(
-      zone, super_cls.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+  const auto& name_field = Field::Handle(zone, object_store->enum_name_field());
   ASSERT(!name_field.IsNull());
 
-  const String& enum_name = String::Handle(zone, enum_cls.ScrubbedName());
+  const auto& enum_name = String::Handle(zone, enum_cls.ScrubbedName());
 
-  const Array& fields = Array::Handle(zone, enum_cls.fields());
-  Field& field = Field::Handle(zone);
-  Instance& enum_value = Instance::Handle(zone);
-  String& enum_ident = String::Handle(zone);
-
-  enum_ident =
-      Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name);
-  enum_value = Instance::New(enum_cls, Heap::kOld);
-  enum_value.SetField(index_field, Smi::Handle(zone, Smi::New(-1)));
-  enum_value.SetField(name_field, enum_ident);
-  enum_value = enum_value.Canonicalize(thread);
-  ASSERT(!enum_value.IsNull());
-  ASSERT(enum_value.IsCanonical());
-  const Field& sentinel = Field::Handle(
+  const auto& sentinel_ident = String::Handle(
+      zone,
+      Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name));
+  auto& sentinel_value =
+      Instance::Handle(zone, Instance::New(enum_cls, Heap::kOld));
+  sentinel_value.SetField(index_field, Smi::Handle(zone, Smi::New(-1)));
+  sentinel_value.SetField(name_field, sentinel_ident);
+  sentinel_value = sentinel_value.Canonicalize(thread);
+  ASSERT(!sentinel_value.IsNull());
+  ASSERT(sentinel_value.IsCanonical());
+  const auto& sentinel_field = Field::Handle(
       zone, enum_cls.LookupStaticField(Symbols::_DeletedEnumSentinel()));
-  ASSERT(!sentinel.IsNull());
+  ASSERT(!sentinel_field.IsNull());
 
   // The static const field contains `Object::null()` instead of
   // `Object::sentinel()` - so it's not considered an initializing store.
-  sentinel.SetStaticConstFieldValue(enum_value,
-                                    /*assert_initializing_store*/ false);
-
-  ASSERT(enum_cls.kernel_offset() > 0);
-  Object& error = Error::Handle(zone);
-  for (intptr_t i = 0; i < fields.Length(); i++) {
-    field = Field::RawCast(fields.At(i));
-    if (!field.is_static() || !field.is_const() ||
-        (sentinel.ptr() == field.ptr())) {
-      continue;
-    }
-    // Hot-reload expects the static const fields to be evaluated when
-    // performing a reload.
-    if (!FLAG_precompiled_mode) {
-      error = field.StaticConstFieldValue();
-      if (error.IsError()) {
-        ReportError(Error::Cast(error));
-      }
-    }
-  }
+  sentinel_field.SetStaticConstFieldValue(sentinel_value,
+                                          /*assert_initializing_store*/ false);
 }
 
 void ClassFinalizer::PrintClassInformation(const Class& cls) {
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 9b647b3..6edd6b9 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -152,12 +152,8 @@
   V(Float)                                                                     \
   V(Double)
 
-#define CLASS_LIST_FFI_NUMERIC(V)                                              \
-  CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V)                                         \
-  V(IntPtr)
-
 #define CLASS_LIST_FFI_TYPE_MARKER(V)                                          \
-  CLASS_LIST_FFI_NUMERIC(V)                                                    \
+  CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V)                                         \
   V(Void)                                                                      \
   V(Handle)                                                                    \
   V(Bool)
diff --git a/runtime/vm/code_patcher_riscv.cc b/runtime/vm/code_patcher_riscv.cc
new file mode 100644
index 0000000..415e645
--- /dev/null
+++ b/runtime/vm/code_patcher_riscv.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/code_patcher.h"
+#include "vm/cpu.h"
+#include "vm/instructions.h"
+#include "vm/object.h"
+
+namespace dart {
+
+class PoolPointerCall : public ValueObject {
+ public:
+  PoolPointerCall(uword pc, const Code& code)
+      : end_(pc), object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
+    ASSERT(*reinterpret_cast<uint16_t*>(end_ - 2) == 0x9082);  // jalr ra
+    uint32_t load_entry = *reinterpret_cast<uint32_t*>(end_ - 6);
+#if XLEN == 32
+    ASSERT((load_entry == 0x00362083) ||  // lw ra, entry(code)
+           (load_entry == 0x00b62083));   // lw ra, unchecked_entry(code)
+#elif XLEN == 64
+    ASSERT((load_entry == 0x00763083) ||  // ld ra, entry(code)
+           (load_entry = 0x01763083));    // ld ra, unchecked_entry(code)
+#endif
+    InstructionPattern::DecodeLoadWordFromPool(end_ - 6, &reg_, &index_);
+  }
+
+  intptr_t pp_index() const { return index_; }
+
+  CodePtr Target() const {
+    return static_cast<CodePtr>(object_pool_.ObjectAt(pp_index()));
+  }
+
+  void SetTarget(const Code& target) const {
+    object_pool_.SetObjectAt(pp_index(), target);
+    // No need to flush the instruction cache, since the code is not modified.
+  }
+
+ private:
+  uword end_;
+  const ObjectPool& object_pool_;
+  Register reg_;
+  intptr_t index_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
+};
+
+CodePtr CodePatcher::GetStaticCallTargetAt(uword return_address,
+                                           const Code& code) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  PoolPointerCall call(return_address, code);
+  return call.Target();
+}
+
+void CodePatcher::PatchStaticCallAt(uword return_address,
+                                    const Code& code,
+                                    const Code& new_target) {
+  PatchPoolPointerCallAt(return_address, code, new_target);
+}
+
+void CodePatcher::PatchPoolPointerCallAt(uword return_address,
+                                         const Code& code,
+                                         const Code& new_target) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  PoolPointerCall call(return_address, code);
+  call.SetTarget(new_target);
+}
+
+void CodePatcher::InsertDeoptimizationCallAt(uword start) {
+  UNREACHABLE();
+}
+
+CodePtr CodePatcher::GetInstanceCallAt(uword return_address,
+                                       const Code& caller_code,
+                                       Object* data) {
+  ASSERT(caller_code.ContainsInstructionAt(return_address));
+  ICCallPattern call(return_address, caller_code);
+  if (data != NULL) {
+    *data = call.Data();
+  }
+  return call.TargetCode();
+}
+
+void CodePatcher::PatchInstanceCallAt(uword return_address,
+                                      const Code& caller_code,
+                                      const Object& data,
+                                      const Code& target) {
+  auto thread = Thread::Current();
+  thread->isolate_group()->RunWithStoppedMutators([&]() {
+    PatchInstanceCallAtWithMutatorsStopped(thread, return_address, caller_code,
+                                           data, target);
+  });
+}
+
+void CodePatcher::PatchInstanceCallAtWithMutatorsStopped(
+    Thread* thread,
+    uword return_address,
+    const Code& caller_code,
+    const Object& data,
+    const Code& target) {
+  ASSERT(caller_code.ContainsInstructionAt(return_address));
+  ICCallPattern call(return_address, caller_code);
+  call.SetData(data);
+  call.SetTargetCode(target);
+}
+
+FunctionPtr CodePatcher::GetUnoptimizedStaticCallAt(uword return_address,
+                                                    const Code& code,
+                                                    ICData* ic_data_result) {
+  ASSERT(code.ContainsInstructionAt(return_address));
+  ICCallPattern static_call(return_address, code);
+  ICData& ic_data = ICData::Handle();
+  ic_data ^= static_call.Data();
+  if (ic_data_result != NULL) {
+    *ic_data_result = ic_data.ptr();
+  }
+  return ic_data.GetTargetAt(0);
+}
+
+void CodePatcher::PatchSwitchableCallAt(uword return_address,
+                                        const Code& caller_code,
+                                        const Object& data,
+                                        const Code& target) {
+  auto thread = Thread::Current();
+  // Ensure all threads are suspended as we update data and target pair.
+  thread->isolate_group()->RunWithStoppedMutators([&]() {
+    PatchSwitchableCallAtWithMutatorsStopped(thread, return_address,
+                                             caller_code, data, target);
+  });
+}
+
+void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped(
+    Thread* thread,
+    uword return_address,
+    const Code& caller_code,
+    const Object& data,
+    const Code& target) {
+  if (FLAG_precompiled_mode) {
+    BareSwitchableCallPattern call(return_address);
+    call.SetData(data);
+    call.SetTarget(target);
+  } else {
+    SwitchableCallPattern call(return_address, caller_code);
+    call.SetData(data);
+    call.SetTarget(target);
+  }
+}
+
+uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address,
+                                                  const Code& caller_code) {
+  if (FLAG_precompiled_mode) {
+    BareSwitchableCallPattern call(return_address);
+    return call.target_entry();
+  } else {
+    SwitchableCallPattern call(return_address, caller_code);
+    return call.target_entry();
+  }
+}
+
+ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address,
+                                               const Code& caller_code) {
+  if (FLAG_precompiled_mode) {
+    BareSwitchableCallPattern call(return_address);
+    return call.data();
+  } else {
+    SwitchableCallPattern call(return_address, caller_code);
+    return call.data();
+  }
+}
+
+void CodePatcher::PatchNativeCallAt(uword return_address,
+                                    const Code& caller_code,
+                                    NativeFunction target,
+                                    const Code& trampoline) {
+  Thread::Current()->isolate_group()->RunWithStoppedMutators([&]() {
+    ASSERT(caller_code.ContainsInstructionAt(return_address));
+    NativeCallPattern call(return_address, caller_code);
+    call.set_target(trampoline);
+    call.set_native_function(target);
+  });
+}
+
+CodePtr CodePatcher::GetNativeCallAt(uword return_address,
+                                     const Code& caller_code,
+                                     NativeFunction* target) {
+  ASSERT(caller_code.ContainsInstructionAt(return_address));
+  NativeCallPattern call(return_address, caller_code);
+  *target = call.native_function();
+  return call.target();
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/code_patcher_riscv_test.cc b/runtime/vm/code_patcher_riscv_test.cc
new file mode 100644
index 0000000..e6d4480
--- /dev/null
+++ b/runtime/vm/code_patcher_riscv_test.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/code_patcher.h"
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/dart_entry.h"
+#include "vm/instructions.h"
+#include "vm/native_entry.h"
+#include "vm/native_entry_test.h"
+#include "vm/runtime_entry.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+#define __ assembler->
+
+ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
+  Thread* thread = Thread::Current();
+  const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
+  const Script& script = Script::Handle();
+  const Class& owner_class = Class::Handle(Class::New(
+      Library::Handle(), class_name, script, TokenPosition::kNoSource));
+  const String& function_name =
+      String::Handle(Symbols::New(thread, "callerFunction"));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  const Function& function = Function::Handle(Function::New(
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
+
+  const String& target_name =
+      String::Handle(Symbols::New(thread, "targetFunction"));
+  const intptr_t kTypeArgsLen = 0;
+  const intptr_t kNumArgs = 1;
+  const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
+      kTypeArgsLen, kNumArgs, Object::null_array()));
+  const ICData& ic_data = ICData::ZoneHandle(ICData::New(
+      function, target_name, args_descriptor, 15, 1, ICData::kInstance));
+  const Code& stub = StubCode::OneArgCheckInlineCache();
+
+  // Code is generated, but not executed. Just parsed with CodePatcher.
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  __ LoadUniqueObject(IC_DATA_REG, ic_data);
+  __ LoadUniqueObject(CODE_REG, stub);
+  __ Call(compiler::FieldAddress(
+      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(IcDataAccess, test) {
+  uword end = test->payload_start() + test->code().Size();
+  uword return_address = end - CInstr::kInstrSize;
+  ICData& ic_data = ICData::Handle();
+  CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
+  EXPECT_STREQ("targetFunction",
+               String::Handle(ic_data.target_name()).ToCString());
+  EXPECT_EQ(1, ic_data.NumArgsTested());
+  EXPECT_EQ(0, ic_data.NumberOfChecks());
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index a8e2f04..d4aa2e9 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -509,7 +509,7 @@
         if (replacement != nullptr) break;
         FALL_THROUGH;
       case Token::kTRUNCDIV:
-#if !defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64)
+#if !defined(TARGET_ARCH_IS_64_BIT)
         // TODO(ajcbik): 32-bit archs too?
         break;
 #else
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 930e8ad..756c8b1 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -87,7 +87,6 @@
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, trace_optimizing_compiler);
 DECLARE_FLAG(bool, trace_bailout);
-DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 DECLARE_FLAG(bool, trace_inlining_intervals);
 DECLARE_FLAG(int, inlining_hotness);
@@ -487,10 +486,8 @@
       // as well as other type checks.
       HierarchyInfo hierarchy_info(T);
 
-      if (FLAG_use_table_dispatch) {
-        dispatch_table_generator_ = new compiler::DispatchTableGenerator(Z);
-        dispatch_table_generator_->Initialize(IG->class_table());
-      }
+      dispatch_table_generator_ = new compiler::DispatchTableGenerator(Z);
+      dispatch_table_generator_->Initialize(IG->class_table());
 
       // Precompile constructors to compute information such as
       // optimized instruction count (used in inlining heuristics).
@@ -874,6 +871,17 @@
               function.token_pos().ToCString(),
               Function::KindToCString(function.kind()));
   }
+  if (function.SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
+    THR_Print(
+        "Warning: %s from %s is too large. Some optimizations have been "
+        "disabled, and the compiler might run out of memory. "
+        "Consider refactoring this code into smaller components.\n",
+        function.QualifiedUserVisibleNameCString(),
+        String::Handle(
+            Z, Library::Handle(Z, Class::Handle(Z, function.Owner()).library())
+                   .url())
+            .ToCString());
+  }
 
   ASSERT(!function.is_abstract());
 
@@ -1446,8 +1454,6 @@
 }
 
 void Precompiler::AddTableSelector(const compiler::TableSelector* selector) {
-  ASSERT(FLAG_use_table_dispatch);
-
   if (is_tracing()) {
     tracer_->WriteTableSelectorRef(selector->id);
   }
@@ -1459,10 +1465,6 @@
 }
 
 bool Precompiler::IsHitByTableSelector(const Function& function) {
-  if (!FLAG_use_table_dispatch) {
-    return false;
-  }
-
   const int32_t selector_id = selector_map()->SelectorId(function);
   if (selector_id == compiler::SelectorMap::kInvalidSelectorId) return false;
   return seen_table_selectors_.HasKey(selector_id);
@@ -2011,7 +2013,6 @@
 
 void Precompiler::FinalizeDispatchTable() {
   PRECOMPILER_TIMER_SCOPE(this, FinalizeDispatchTable);
-  if (!FLAG_use_table_dispatch) return;
   HANDLESCOPE(T);
   // Build the entries used to serialize the dispatch table before
   // dropping functions, as we may clear references to Code objects.
@@ -2464,11 +2465,6 @@
       if (cls.is_allocated()) {
         retain = true;
       }
-      if (cls.is_enum_class()) {
-        // Enum classes have live instances, so we cannot unregister
-        // them.
-        retain = true;
-      }
 
       constants = cls.constants();
       retained_constants = GrowableObjectArray::New();
@@ -3124,7 +3120,7 @@
   // true. use_far_branches is always false on ia32 and x64.
   bool done = false;
   // volatile because the variable may be clobbered by a longjmp.
-  volatile bool use_far_branches = false;
+  volatile intptr_t far_branch_level = 0;
   SpeculativeInliningPolicy speculative_policy(
       true, FLAG_max_speculative_inlining_attempts);
 
@@ -3212,7 +3208,7 @@
       // (See TryCommitToParent invocation below).
       compiler::ObjectPoolBuilder object_pool_builder(
           precompiler_->global_object_pool_builder());
-      compiler::Assembler assembler(&object_pool_builder, use_far_branches);
+      compiler::Assembler assembler(&object_pool_builder, far_branch_level);
 
       CodeStatistics* function_stats = NULL;
       if (FLAG_print_instruction_stats) {
@@ -3287,8 +3283,8 @@
         // Compilation failed due to an out of range branch offset in the
         // assembler. We try again (done = false) with far branches enabled.
         done = false;
-        ASSERT(!use_far_branches);
-        use_far_branches = true;
+        RELEASE_ASSERT(far_branch_level < 2);
+        far_branch_level++;
       } else if (error.ptr() == Object::speculative_inlining_error().ptr()) {
         // The return value of setjmp is the deopt id of the check instruction
         // that caused the bailout.
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 678905c..ba2aee7 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -119,7 +119,9 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline uword Hash(Key key) { return key->token_pos().Hash(); }
+  static inline uword Hash(Key key) {
+    return Utils::WordHash(CombineHashes(key->id(), key->token_pos().Hash()));
+  }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     return pair->ptr() == key->ptr();
@@ -219,7 +221,7 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline uword Hash(Key key) { return key->GetClassId(); }
+  static inline uword Hash(Key key) { return key->CanonicalizeHash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     return pair->ptr() == key->ptr();
@@ -247,7 +249,6 @@
   }
 
   compiler::SelectorMap* selector_map() {
-    ASSERT(FLAG_use_table_dispatch);
     return dispatch_table_generator_->selector_map();
   }
 
diff --git a/runtime/vm/compiler/aot/precompiler_tracer.cc b/runtime/vm/compiler/aot/precompiler_tracer.cc
index d0a2e5f..9588400 100644
--- a/runtime/vm/compiler/aot/precompiler_tracer.cc
+++ b/runtime/vm/compiler/aot/precompiler_tracer.cc
@@ -90,9 +90,7 @@
       const auto& fun = Function::Cast(obj);
       cls_ = fun.Owner();
       const intptr_t selector_id =
-          FLAG_use_table_dispatch
-              ? precompiler_->selector_map()->SelectorId(fun)
-              : -1;
+          precompiler_->selector_map()->SelectorId(fun);
       Write("\"%c\",%" Pd ",%" Pd ",%" Pd "",
             fun.IsDynamicFunction() ? 'F' : 'S', InternEntity(cls_),
             InternString(NameForTrace(fun)), selector_id);
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 3b8931c..77cb516 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -15,10 +15,12 @@
 namespace compiler {
 
 // When entering intrinsics code:
+// PP: Caller's ObjectPool in JIT / global ObjectPool in AOT
+// CODE_REG: Callee's Code in JIT / not passed in AOT
 // R4: Arguments descriptor
 // LR: Return address
-// The R4 register can be destroyed only if there is no slow-path, i.e.
-// if the intrinsified method always executes a return.
+// The R4 and CODE_REG registers can be destroyed only if there is no slow-path,
+// i.e. if the intrinsified method always executes a return.
 // The FP register should not be modified, because it is used by the profiler.
 // The PP and THR registers (see constants_arm.h) must be preserved.
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index f9c178a..600e28c 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -15,10 +15,12 @@
 namespace compiler {
 
 // When entering intrinsics code:
+// PP: Caller's ObjectPool in JIT / global ObjectPool in AOT
+// CODE_REG: Callee's Code in JIT / not passed in AOT
 // R4: Arguments descriptor
 // LR: Return address
-// The R4 register can be destroyed only if there is no slow-path, i.e.
-// if the intrinsified method always executes a return.
+// The R4 and CODE_REG registers can be destroyed only if there is no slow-path,
+// i.e. if the intrinsified method always executes a return.
 // The FP register should not be modified, because it is used by the profiler.
 // The PP and THR registers (see constants_arm64.h) must be preserved.
 
@@ -51,9 +53,8 @@
       R1);
 
   // Set the length field in the growable array object to 0.
-  __ LoadImmediate(R1, 0);
   __ StoreCompressedIntoObjectNoBarrier(
-      R0, FieldAddress(R0, target::GrowableObjectArray::length_offset()), R1);
+      R0, FieldAddress(R0, target::GrowableObjectArray::length_offset()), ZR);
   __ ret();  // Returns the newly allocated object in R0.
 
   __ Bind(normal_ir_body);
diff --git a/runtime/vm/compiler/asm_intrinsifier_riscv.cc b/runtime/vm/compiler/asm_intrinsifier_riscv.cc
new file mode 100644
index 0000000..bd85776
--- /dev/null
+++ b/runtime/vm/compiler/asm_intrinsifier_riscv.cc
@@ -0,0 +1,725 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
+#include "vm/compiler/assembler/assembler.h"
+
+namespace dart {
+namespace compiler {
+
+// When entering intrinsics code:
+// PP: Caller's ObjectPool in JIT / global ObjectPool in AOT
+// CODE_REG: Callee's Code in JIT / not passed in AOT
+// S4: Arguments descriptor
+// RA: Return address
+// The S4 and CODE_REG registers can be destroyed only if there is no slow-path,
+// i.e. if the intrinsified method always executes a return.
+// The FP register should not be modified, because it is used by the profiler.
+// The PP and THR registers (see constants_riscv.h) must be preserved.
+
+#define __ assembler->
+
+// Allocate a GrowableObjectArray:: using the backing array specified.
+// On stack: type argument (+1), data (+0).
+void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  // The newly allocated object is returned in R0.
+  const intptr_t kTypeArgumentsOffset = 1 * target::kWordSize;
+  const intptr_t kArrayOffset = 0 * target::kWordSize;
+
+  // Try allocating in new space.
+  const Class& cls = GrowableObjectArrayClass();
+  __ TryAllocate(cls, normal_ir_body, Assembler::kFarJump, A0, A1);
+
+  // Store backing array object in growable array object.
+  __ lx(A1, Address(SP, kArrayOffset));  // Data argument.
+  // R0 is new, no barrier needed.
+  __ StoreCompressedIntoObjectNoBarrier(
+      A0, FieldAddress(A0, target::GrowableObjectArray::data_offset()), A1);
+
+  // R0: new growable array object start as a tagged pointer.
+  // Store the type argument field in the growable array object.
+  __ lx(A1, Address(SP, kTypeArgumentsOffset));  // Type argument.
+  __ StoreCompressedIntoObjectNoBarrier(
+      A0,
+      FieldAddress(A0, target::GrowableObjectArray::type_arguments_offset()),
+      A1);
+
+  // Set the length field in the growable array object to 0.
+  __ StoreCompressedIntoObjectNoBarrier(
+      A0, FieldAddress(A0, target::GrowableObjectArray::length_offset()), ZR);
+  __ ret();  // Returns the newly allocated object in A0.
+
+  __ Bind(normal_ir_body);
+}
+
+// Loads args from stack into A0 and A1
+// Tests if they are smis, jumps to label not_smi if not.
+static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
+  __ lx(A0, Address(SP, +1 * target::kWordSize));
+  __ lx(A1, Address(SP, +0 * target::kWordSize));
+  __ or_(TMP, A0, A1);
+  __ BranchIfNotSmi(TMP, not_smi, Assembler::kNearJump);
+}
+
+void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
+  const Register left = A0;
+  const Register right = A1;
+  const Register result = A0;
+
+  TestBothArgumentsSmis(assembler, normal_ir_body);
+  __ CompareImmediate(right, target::ToRawSmi(target::kSmiBits),
+                      compiler::kObjectBytes);
+  __ BranchIf(CS, normal_ir_body, Assembler::kNearJump);
+
+  __ SmiUntag(right);
+  __ sll(TMP, left, right);
+  __ sra(TMP2, TMP, right);
+  __ bne(TMP2, left, normal_ir_body, Assembler::kNearJump);
+  __ mv(result, TMP);
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+static void CompareIntegers(Assembler* assembler,
+                            Label* normal_ir_body,
+                            Condition true_condition) {
+  Label true_label;
+  TestBothArgumentsSmis(assembler, normal_ir_body);
+  __ CompareObjectRegisters(A0, A1);
+  __ BranchIf(true_condition, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  CompareIntegers(assembler, normal_ir_body, LT);
+}
+
+void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
+                                          Label* normal_ir_body) {
+  CompareIntegers(assembler, normal_ir_body, GT);
+}
+
+void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  CompareIntegers(assembler, normal_ir_body, LE);
+}
+
+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 AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  Label true_label, check_for_mint;
+  // For integer receiver '===' check first.
+  __ lx(A0, Address(SP, 1 * target::kWordSize));
+  __ lx(A1, Address(SP, 0 * target::kWordSize));
+  __ CompareObjectRegisters(A0, A1);
+  __ BranchIf(EQ, &true_label, Assembler::kNearJump);
+
+  __ or_(TMP, A0, A1);
+  __ BranchIfNotSmi(TMP, &check_for_mint, Assembler::kNearJump);
+  // If R0 or R1 is not a smi do Mint checks.
+
+  // Both arguments are smi, '===' is good enough.
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  // At least one of the arguments was not Smi.
+  Label receiver_not_smi;
+  __ Bind(&check_for_mint);
+
+  __ BranchIfNotSmi(A0, &receiver_not_smi,
+                    Assembler::kNearJump);  // Check receiver.
+
+  // 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.
+
+  __ CompareClassId(A1, kDoubleCid, TMP);
+  __ BranchIf(EQ, normal_ir_body, Assembler::kNearJump);
+  __ LoadObject(A0,
+                CastHandle<Object>(FalseObject()));  // Smi == Mint -> false.
+  __ ret();
+
+  __ Bind(&receiver_not_smi);
+  // A0: receiver.
+
+  __ CompareClassId(A0, kMintCid, TMP);
+  __ BranchIf(NE, normal_ir_body, Assembler::kNearJump);
+  // Receiver is Mint, return false if right is Smi.
+  __ BranchIfNotSmi(A1, normal_ir_body, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  // TODO(srdjan): Implement Mint == Mint comparison.
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Integer_equal(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  Integer_equalToInteger(assembler, normal_ir_body);
+}
+
+void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
+                                                   Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+// FA0: left
+// FA1: right
+static void PrepareDoubleOp(Assembler* assembler, Label* normal_ir_body) {
+  Label double_op;
+  __ lx(A0, Address(SP, 1 * target::kWordSize));  // Left
+  __ lx(A1, Address(SP, 0 * target::kWordSize));  // Right
+
+  __ fld(FA0, FieldAddress(A0, target::Double::value_offset()));
+
+  __ SmiUntag(TMP, A1);
+#if XLEN == 32
+  __ fcvtdw(FA1, TMP);
+#else
+  __ fcvtdl(FA1, TMP);
+#endif
+  __ BranchIfSmi(A1, &double_op, Assembler::kNearJump);
+  __ CompareClassId(A1, kDoubleCid, TMP);
+  __ BranchIf(NE, normal_ir_body, Assembler::kNearJump);
+  __ fld(FA1, FieldAddress(A1, target::Double::value_offset()));
+
+  __ Bind(&double_op);
+}
+
+void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  Label true_label;
+  PrepareDoubleOp(assembler, normal_ir_body);
+  __ fltd(TMP, FA1, FA0);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
+                                              Label* normal_ir_body) {
+  Label true_label;
+  PrepareDoubleOp(assembler, normal_ir_body);
+  __ fled(TMP, FA1, FA0);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  Label true_label;
+  PrepareDoubleOp(assembler, normal_ir_body);
+  __ fltd(TMP, FA0, FA1);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_equal(Assembler* assembler,
+                                   Label* normal_ir_body) {
+  Label true_label;
+  PrepareDoubleOp(assembler, normal_ir_body);
+  __ feqd(TMP, FA0, FA1);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
+                                           Label* normal_ir_body) {
+  Label true_label;
+  PrepareDoubleOp(assembler, normal_ir_body);
+  __ fled(TMP, FA0, FA1);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+// Expects left argument to be double (receiver). Right argument is unknown.
+// Both arguments are on stack.
+static void DoubleArithmeticOperations(Assembler* assembler,
+                                       Label* normal_ir_body,
+                                       Token::Kind kind) {
+  PrepareDoubleOp(assembler, normal_ir_body);
+  switch (kind) {
+    case Token::kADD:
+      __ faddd(FA0, FA0, FA1);
+      break;
+    case Token::kSUB:
+      __ fsubd(FA0, FA0, FA1);
+      break;
+    case Token::kMUL:
+      __ fmuld(FA0, FA0, FA1);
+      break;
+    case Token::kDIV:
+      __ fdivd(FA0, FA0, FA1);
+      break;
+    default:
+      UNREACHABLE();
+  }
+  const Class& double_class = DoubleClass();
+  __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, A0, TMP);
+  __ StoreDFieldToOffset(FA0, A0, target::Double::value_offset());
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
+  DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
+}
+
+void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
+  DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
+}
+
+void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
+  DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
+}
+
+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 AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 0 * target::kWordSize));
+  __ BranchIfNotSmi(A0, normal_ir_body, Assembler::kNearJump);
+  // Is Smi.
+  __ SmiUntag(A0);
+#if XLEN == 32
+  __ fcvtdw(FA0, A0);
+#else
+  __ fcvtdl(FA0, A0);
+#endif
+  const Class& double_class = DoubleClass();
+  __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump, A0, TMP);
+  __ StoreDFieldToOffset(FA0, A0, target::Double::value_offset());
+  __ ret();
+  __ Bind(normal_ir_body);
+}
+
+static void DoubleIsClass(Assembler* assembler, intx_t fclass) {
+  Label true_label;
+  __ lx(A0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFieldFromOffset(FA0, A0, target::Double::value_offset());
+  __ fclassd(TMP, FA0);
+  __ andi(TMP, TMP, fclass);
+  __ bnez(TMP, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+}
+
+void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  DoubleIsClass(assembler, kFClassSignallingNan | kFClassQuietNan);
+}
+
+void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
+                                           Label* normal_ir_body) {
+  DoubleIsClass(assembler, kFClassNegInfinity | kFClassPosInfinity);
+}
+
+void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
+                                           Label* normal_ir_body) {
+  DoubleIsClass(assembler, kFClassNegInfinity | kFClassNegNormal |
+                               kFClassNegSubnormal | kFClassNegZero);
+}
+
+void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+//    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
+//    _state[kSTATE_LO] = state & _MASK_32;
+//    _state[kSTATE_HI] = state >> 32;
+void AsmIntrinsifier::Random_nextState(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
+                                   Label* normal_ir_body) {
+  Label true_label;
+  __ lx(A0, Address(SP, 1 * target::kWordSize));
+  __ lx(A1, Address(SP, 0 * target::kWordSize));
+  __ beq(A0, A1, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+}
+
+// Return type quickly for simple types (not parameterized and not signature).
+void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
+                                                Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 0 * target::kWordSize));
+#if XLEN == 32
+  // Smi field.
+  __ lw(A0, FieldAddress(A0, target::String::hash_offset()));
+#else
+  // uint32_t field in header.
+  __ lwu(A0, FieldAddress(A0, target::String::hash_offset()));
+  __ SmiTag(A0);
+#endif
+  __ beqz(A0, normal_ir_body, Assembler::kNearJump);
+  __ ret();
+
+  // Hash not yet computed.
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 0 * target::kWordSize));
+  __ LoadCompressed(A0, FieldAddress(A0, target::Type::hash_offset()));
+  __ beqz(A0, normal_ir_body, Assembler::kNearJump);
+  __ ret();
+  // Hash not yet computed.
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::Type_equality(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 0 * target::kWordSize));
+  __ LoadCompressed(A0, FieldAddress(A0, target::FunctionType::hash_offset()));
+  __ beqz(A0, normal_ir_body, Assembler::kNearJump);
+  __ ret();
+  // Hash not yet computed.
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+// Keep in sync with Instance::IdentityHashCode.
+// Note int and double never reach here because they override _identityHashCode.
+// Special cases are also not needed for null or bool because they were pre-set
+// during VM isolate finalization.
+void AsmIntrinsifier::Object_getHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
+#if XLEN == 32
+  UNREACHABLE();
+#else
+  Label not_yet_computed;
+  __ lx(A0, Address(SP, 0 * target::kWordSize));  // Object.
+  __ lwu(A0, FieldAddress(
+                 A0, target::Object::tags_offset() +
+                         target::UntaggedObject::kHashTagPos / kBitsPerByte));
+  __ beqz(A0, &not_yet_computed);
+  __ SmiTag(A0);
+  __ ret();
+
+  __ Bind(&not_yet_computed);
+  __ LoadFromOffset(A1, THR, target::Thread::random_offset());
+  __ AndImmediate(T2, A1, 0xffffffff);  // state_lo
+  __ srli(T3, A1, 32);                  // state_hi
+  __ LoadImmediate(A1, 0xffffda61);     // A
+  __ mul(A1, A1, T2);
+  __ add(A1, A1, T3);  // new_state = (A * state_lo) + state_hi
+  __ StoreToOffset(A1, THR, target::Thread::random_offset());
+  __ AndImmediate(A1, A1, 0x3fffffff);
+  __ beqz(A1, &not_yet_computed);
+
+  __ lx(A0, Address(SP, 0 * target::kWordSize));  // Object
+  __ subi(A0, A0, kHeapObjectTag);
+  __ slli(T3, A1, target::UntaggedObject::kHashTagPos);
+
+  Label retry, already_set_in_r4;
+  __ Bind(&retry);
+  __ lr(T2, Address(A0, 0));
+  __ srli(T4, T2, target::UntaggedObject::kHashTagPos);
+  __ bnez(T4, &already_set_in_r4);
+  __ or_(T2, T2, T3);
+  __ sc(T4, T2, Address(A0, 0));
+  __ bnez(T4, &retry);
+  // Fall-through with A1 containing new hash value (untagged).
+  __ SmiTag(A0, A1);
+  __ ret();
+  __ Bind(&already_set_in_r4);
+  __ SmiTag(A0, T4);
+  __ ret();
+#endif
+}
+
+void GenerateSubstringMatchesSpecialization(Assembler* assembler,
+                                            intptr_t receiver_cid,
+                                            intptr_t other_cid,
+                                            Label* return_true,
+                                            Label* return_false) {
+  UNIMPLEMENTED();
+}
+
+// bool _substringMatches(int start, String other)
+// This intrinsic handles a OneByteString or TwoByteString receiver with a
+// OneByteString other.
+void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
+                                                Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+// Arg0: OneByteString (receiver).
+// Arg1: Start index as Smi.
+// Arg2: End index as Smi.
+// The indexes must be valid.
+void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
+                                                       Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::WriteIntoOneByteString(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 2 * target::kWordSize));  // OneByteString.
+  __ lx(A1, Address(SP, 1 * target::kWordSize));  // Index.
+  __ lx(A2, Address(SP, 0 * target::kWordSize));  // Value.
+  __ SmiUntag(A1);
+  __ SmiUntag(A2);
+  __ add(A1, A1, A0);
+  __ sb(A2, FieldAddress(A1, target::OneByteString::data_offset()));
+  __ ret();
+}
+
+void AsmIntrinsifier::WriteIntoTwoByteString(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ lx(A0, Address(SP, 2 * target::kWordSize));  // TwoByteString.
+  __ lx(A1, Address(SP, 1 * target::kWordSize));  // Index.
+  __ lx(A2, Address(SP, 0 * target::kWordSize));  // Value.
+  // Untag index and multiply by element size -> no-op.
+  __ SmiUntag(A2);
+  __ add(A1, A1, A0);
+  __ sh(A2, FieldAddress(A1, target::OneByteString::data_offset()));
+  __ ret();
+}
+
+void AsmIntrinsifier::AllocateOneByteString(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::AllocateTwoByteString(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+// TODO(srdjan): Add combinations (one-byte/two-byte/external strings).
+static void StringEquality(Assembler* assembler,
+                           Label* normal_ir_body,
+                           intptr_t string_cid) {
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  StringEquality(assembler, normal_ir_body, kOneByteStringCid);
+}
+
+void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  StringEquality(assembler, normal_ir_body, kTwoByteStringCid);
+}
+
+void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                                   Label* normal_ir_body,
+                                                   bool sticky) {
+  if (FLAG_interpret_irregexp) return;
+
+  // TODO(riscv)
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ LoadIsolate(A0);
+  __ lx(A0, Address(A0, target::Isolate::default_tag_offset()));
+  __ ret();
+}
+
+void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ LoadIsolate(A0);
+  __ lx(A0, Address(A0, target::Isolate::current_tag_offset()));
+  __ ret();
+}
+
+void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
+                                                   Label* normal_ir_body) {
+#if !defined(SUPPORT_TIMELINE)
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+#else
+  Label true_label;
+  // Load TimelineStream*.
+  __ lx(A0, Address(THR, target::Thread::dart_stream_offset()));
+  // Load uintptr_t from TimelineStream*.
+  __ lx(A0, Address(A0, target::TimelineStream::enabled_offset()));
+  __ bnez(A0, &true_label, Assembler::kNearJump);
+  __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+  __ ret();
+  __ Bind(&true_label);
+  __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+  __ ret();
+#endif
+}
+
+#undef __
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index e2f7b24..656bce9 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -15,10 +15,12 @@
 namespace compiler {
 
 // When entering intrinsics code:
+// PP: Caller's ObjectPool in JIT / global ObjectPool in AOT
+// CODE_REG: Callee's Code in JIT / not passed in AOT
 // R10: Arguments descriptor
 // TOS: Return address
-// The R10 registers can be destroyed only if there is no slow-path, i.e.
-// if the intrinsified method always executes a return.
+// The R10 and CODE_REG registers can be destroyed only if there is no
+// slow-path, i.e. if the intrinsified method always executes a return.
 // The RBP register should not be modified, because it is used by the profiler.
 // The PP and THR registers (see constants_x64.h) must be preserved.
 
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 336640a..cfed11a 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -25,6 +25,8 @@
 #include "vm/compiler/assembler/assembler_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/compiler/assembler/assembler_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/compiler/assembler/assembler_riscv.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index a9a71ee..139be88 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -30,9 +30,9 @@
 namespace compiler {
 
 Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches)
+                     intptr_t far_branch_level)
     : AssemblerBase(object_pool_builder),
-      use_far_branches_(use_far_branches),
+      use_far_branches_(far_branch_level != 0),
       constant_pool_allowed_(false) {
   generate_invoke_write_barrier_wrapper_ = [&](Condition cond, Register reg) {
     Call(
@@ -622,7 +622,9 @@
   }
 }
 
-void Assembler::ExitFullSafepoint(Register tmp1, Register tmp2) {
+void Assembler::ExitFullSafepoint(Register tmp1,
+                                  Register tmp2,
+                                  bool ignore_unwind_in_progress) {
   Register addr = tmp1;
   Register state = tmp2;
 
@@ -650,7 +652,14 @@
   }
 
   Bind(&slow_path);
-  ldr(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  if (ignore_unwind_in_progress) {
+    ldr(TMP,
+        Address(THR,
+                target::Thread::
+                    exit_safepoint_ignore_unwind_in_progress_stub_offset()));
+  } else {
+    ldr(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  }
   ldr(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
   blx(TMP);
 
@@ -659,10 +668,13 @@
 
 void Assembler::TransitionNativeToGenerated(Register addr,
                                             Register state,
-                                            bool exit_safepoint) {
+                                            bool exit_safepoint,
+                                            bool ignore_unwind_in_progress) {
   if (exit_safepoint) {
-    ExitFullSafepoint(addr, state);
+    ExitFullSafepoint(addr, state, ignore_unwind_in_progress);
   } else {
+    // flag only makes sense if we are leaving safepoint
+    ASSERT(!ignore_unwind_in_progress);
 #if defined(DEBUG)
     // Ensure we've already left the safepoint.
     ASSERT(target::Thread::full_safepoint_state_acquired() != 0);
@@ -1604,10 +1616,8 @@
 void Assembler::SetupGlobalPoolAndDispatchTable() {
   ASSERT(FLAG_precompiled_mode);
   ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
-  if (FLAG_use_table_dispatch) {
-    ldr(DISPATCH_TABLE_REG,
-        Address(THR, target::Thread::dispatch_table_array_offset()));
-  }
+  ldr(DISPATCH_TABLE_REG,
+      Address(THR, target::Thread::dispatch_table_array_offset()));
 }
 
 void Assembler::LoadIsolate(Register rd) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 457b1da..78bb68e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -354,7 +354,7 @@
 class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches = false);
+                     intptr_t far_branch_level = 0);
   ~Assembler() {}
 
   void PushRegister(Register r) { Push(r); }
@@ -614,9 +614,12 @@
                                    bool enter_safepoint);
   void TransitionNativeToGenerated(Register scratch0,
                                    Register scratch1,
-                                   bool exit_safepoint);
+                                   bool exit_safepoint,
+                                   bool ignore_unwind_in_progress = false);
   void EnterFullSafepoint(Register scratch0, Register scratch1);
-  void ExitFullSafepoint(Register scratch0, Register scratch1);
+  void ExitFullSafepoint(Register scratch0,
+                         Register scratch1,
+                         bool ignore_unwind_in_progress);
 
   // Miscellaneous instructions.
   void clrex();
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 3bfb9a8..943457c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -26,9 +26,9 @@
 namespace compiler {
 
 Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches)
+                     intptr_t far_branch_level)
     : AssemblerBase(object_pool_builder),
-      use_far_branches_(use_far_branches),
+      use_far_branches_(far_branch_level != 0),
       constant_pool_allowed_(false) {
   generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
     Call(Address(THR,
@@ -435,22 +435,6 @@
   }
 }
 
-void Assembler::LoadWordFromPoolIndexFixed(Register dst, intptr_t index) {
-  ASSERT(constant_pool_allowed());
-  ASSERT(dst != PP);
-  Operand op;
-  // PP is _un_tagged on ARM64.
-  const uint32_t offset = target::ObjectPool::element_offset(index);
-  const uint32_t upper20 = offset & 0xfffff000;
-  const uint32_t lower12 = offset & 0x00000fff;
-  const Operand::OperandType ot =
-      Operand::CanHold(upper20, kXRegSizeInBits, &op);
-  ASSERT(ot == Operand::Immediate);
-  ASSERT(Address::CanHoldOffset(lower12));
-  add(dst, PP, op);
-  ldr(dst, Address(dst, lower12));
-}
-
 void Assembler::LoadDoubleWordFromPoolIndex(Register lower,
                                             Register upper,
                                             intptr_t index) {
@@ -1568,10 +1552,8 @@
   ASSERT(FLAG_precompiled_mode);
   ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
   sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
-  if (FLAG_use_table_dispatch) {
-    ldr(DISPATCH_TABLE_REG,
-        Address(THR, target::Thread::dispatch_table_array_offset()));
-  }
+  ldr(DISPATCH_TABLE_REG,
+      Address(THR, target::Thread::dispatch_table_array_offset()));
 }
 
 void Assembler::CheckCodePointer() {
@@ -1753,7 +1735,8 @@
   }
 }
 
-void Assembler::ExitFullSafepoint(Register state) {
+void Assembler::ExitFullSafepoint(Register state,
+                                  bool ignore_unwind_in_progress) {
   // We generate the same number of instructions whether or not the slow-path is
   // forced, for consistency with EnterFullSafepoint.
   Register addr = TMP2;
@@ -1780,7 +1763,14 @@
   }
 
   Bind(&slow_path);
-  ldr(addr, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  if (ignore_unwind_in_progress) {
+    ldr(addr,
+        Address(THR,
+                target::Thread::
+                    exit_safepoint_ignore_unwind_in_progress_stub_offset()));
+  } else {
+    ldr(addr, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  }
   ldr(addr, FieldAddress(addr, target::Code::entry_point_offset()));
   blr(addr);
 
@@ -1788,10 +1778,13 @@
 }
 
 void Assembler::TransitionNativeToGenerated(Register state,
-                                            bool exit_safepoint) {
+                                            bool exit_safepoint,
+                                            bool ignore_unwind_in_progress) {
   if (exit_safepoint) {
-    ExitFullSafepoint(state);
+    ExitFullSafepoint(state, ignore_unwind_in_progress);
   } else {
+    // flag only makes sense if we are leaving safepoint
+    ASSERT(!ignore_unwind_in_progress);
 #if defined(DEBUG)
     // Ensure we've already left the safepoint.
     ASSERT(target::Thread::full_safepoint_state_acquired() != 0);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 886ab74..a1126ec 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -512,7 +512,7 @@
 class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches = false);
+                     intptr_t far_branch_level = 0);
   ~Assembler() {}
 
   void PushRegister(Register r) { Push(r); }
@@ -2054,9 +2054,11 @@
                                    Register new_exit_frame,
                                    Register new_exit_through_ffi,
                                    bool enter_safepoint);
-  void TransitionNativeToGenerated(Register scratch, bool exit_safepoint);
+  void TransitionNativeToGenerated(Register scratch,
+                                   bool exit_safepoint,
+                                   bool ignore_unwind_in_progress = false);
   void EnterFullSafepoint(Register scratch);
-  void ExitFullSafepoint(Register scratch);
+  void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress);
 
   void CheckCodePointer();
   void RestoreCodePointer();
@@ -2250,8 +2252,6 @@
 
   compiler::LRState lr_state_ = compiler::LRState::OnEntry();
 
-  void LoadWordFromPoolIndexFixed(Register dst, intptr_t index);
-
   // Note: the function never clobbers TMP, TMP2 scratch registers.
   void LoadObjectHelper(Register dst, const Object& obj, bool is_unique);
 
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index c3410b4..85259a3 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -20,7 +20,8 @@
 
 namespace dart {
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
 DECLARE_FLAG(bool, use_far_branches);
 #endif
 
@@ -214,6 +215,64 @@
 class Address;
 class FieldAddress;
 
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+class Label : public ZoneAllocated {
+ public:
+  Label() {}
+  ~Label() {
+    // Assert if label is being destroyed with unresolved branches pending.
+    ASSERT(!IsLinked());
+  }
+
+  intptr_t Position() const {
+    ASSERT(IsBound());
+    return position_;
+  }
+
+  bool IsBound() const { return position_ != -1; }
+  bool IsUnused() const { return !IsBound() && !IsLinked(); }
+  bool IsLinked() const {
+    return unresolved_cb_ != -1 || unresolved_cj_ != -1 ||
+           unresolved_b_ != -1 || unresolved_j_ != -1 || unresolved_far_ != -1;
+  }
+
+ private:
+  int32_t position_ = -1;
+  void BindTo(intptr_t position) {
+    ASSERT(!IsBound());
+    ASSERT(!IsLinked());
+    position_ = position;
+    ASSERT(IsBound());
+  }
+
+  // Linked lists of unresolved forward branches, threaded through the branch
+  // instructions. The offset encoded in each unresolved branch the delta to the
+  // next instruction in the list, terminated with 0 delta. Each branch class
+  // has a separate list because the offset range of each is different.
+#define DEFINE_BRANCH_CLASS(name)                                              \
+  int32_t unresolved_##name##_ = -1;                                           \
+  int32_t link_##name(int32_t position) {                                      \
+    ASSERT(position > unresolved_##name##_);                                   \
+    int32_t offset;                                                            \
+    if (unresolved_##name##_ == -1) {                                          \
+      offset = 0;                                                              \
+    } else {                                                                   \
+      offset = position - unresolved_##name##_;                                \
+      ASSERT(offset > 0);                                                      \
+    }                                                                          \
+    unresolved_##name##_ = position;                                           \
+    return offset;                                                             \
+  }
+  DEFINE_BRANCH_CLASS(cb);
+  DEFINE_BRANCH_CLASS(cj);
+  DEFINE_BRANCH_CLASS(b);
+  DEFINE_BRANCH_CLASS(j);
+  DEFINE_BRANCH_CLASS(far);
+
+  friend class MicroAssembler;
+  DISALLOW_COPY_AND_ASSIGN(Label);
+};
+#else
 class Label : public ZoneAllocated {
  public:
   Label() : position_(0), unresolved_(0) {
@@ -324,6 +383,7 @@
   friend class Assembler;
   DISALLOW_COPY_AND_ASSIGN(Label);
 };
+#endif
 
 // External labels keep a function pointer to allow them
 // to be called from code generated by the assembler.
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 459cbf2..a3b12b0 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2361,7 +2361,8 @@
   }
 }
 
-void Assembler::ExitFullSafepoint(Register scratch) {
+void Assembler::ExitFullSafepoint(Register scratch,
+                                  bool ignore_unwind_in_progress) {
   ASSERT(scratch != EAX);
   // We generate the same number of instructions whether or not the slow-path is
   // forced, for consistency with EnterFullSafepoint.
@@ -2386,7 +2387,14 @@
   }
 
   Bind(&slow_path);
-  movl(scratch, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  if (ignore_unwind_in_progress) {
+    movl(scratch,
+         Address(THR,
+                 target::Thread::
+                     exit_safepoint_ignore_unwind_in_progress_stub_offset()));
+  } else {
+    movl(scratch, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  }
   movl(scratch, FieldAddress(scratch, target::Code::entry_point_offset()));
   call(scratch);
 
@@ -2394,10 +2402,13 @@
 }
 
 void Assembler::TransitionNativeToGenerated(Register scratch,
-                                            bool exit_safepoint) {
+                                            bool exit_safepoint,
+                                            bool ignore_unwind_in_progress) {
   if (exit_safepoint) {
-    ExitFullSafepoint(scratch);
+    ExitFullSafepoint(scratch, ignore_unwind_in_progress);
   } else {
+    // flag only makes sense if we are leaving safepoint
+    ASSERT(!ignore_unwind_in_progress);
 #if defined(DEBUG)
     // Ensure we've already left the safepoint.
     movl(scratch, Address(THR, target::Thread::safepoint_state_offset()));
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index e5b2b1a..69207d5 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -229,12 +229,12 @@
 class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches = false)
+                     intptr_t far_branch_level = 0)
       : AssemblerBase(object_pool_builder),
         jit_cookie_(0),
         code_(NewZoneHandle(ThreadState::Current()->zone())) {
     // This mode is only needed and implemented for ARM.
-    ASSERT(!use_far_branches);
+    ASSERT(far_branch_level == 0);
   }
   ~Assembler() {}
 
@@ -819,9 +819,11 @@
                                    Register new_exit_frame,
                                    Register new_exit_through_ffi,
                                    bool enter_safepoint);
-  void TransitionNativeToGenerated(Register scratch, bool exit_safepoint);
+  void TransitionNativeToGenerated(Register scratch,
+                                   bool exit_safepoint,
+                                   bool ignore_unwind_in_progress = false);
   void EnterFullSafepoint(Register scratch);
-  void ExitFullSafepoint(Register scratch);
+  void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress);
 
   // Create a frame for calling into runtime that preserves all volatile
   // registers.  Frame's RSP is guaranteed to be correctly aligned and
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
new file mode 100644
index 0000000..1c67022
--- /dev/null
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -0,0 +1,4391 @@
+// 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.
+
+#include "vm/globals.h"  // NOLINT
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/cpu.h"
+#include "vm/instructions.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, check_code_pointer);
+DECLARE_FLAG(bool, precompiled_mode);
+
+DEFINE_FLAG(int, far_branch_level, 0, "Always use far branches");
+
+namespace compiler {
+
+MicroAssembler::MicroAssembler(ObjectPoolBuilder* object_pool_builder,
+                               intptr_t far_branch_level,
+                               ExtensionSet extensions)
+    : AssemblerBase(object_pool_builder),
+      extensions_(extensions),
+      far_branch_level_(far_branch_level) {
+  ASSERT(far_branch_level >= 0);
+  ASSERT(far_branch_level <= 2);
+}
+
+MicroAssembler::~MicroAssembler() {}
+
+void MicroAssembler::Bind(Label* label) {
+  ASSERT(!label->IsBound());
+  intptr_t target_position = Position();
+  intptr_t branch_position;
+
+#define BIND(head, update)                                                     \
+  branch_position = label->head;                                               \
+  while (branch_position >= 0) {                                               \
+    ASSERT(Utils::IsAligned(branch_position, Supports(RV_C) ? 2 : 4));         \
+    intptr_t new_offset = target_position - branch_position;                   \
+    ASSERT(Utils::IsAligned(new_offset, Supports(RV_C) ? 2 : 4));              \
+    intptr_t old_offset = update(branch_position, new_offset);                 \
+    if (old_offset == 0) break;                                                \
+    branch_position -= old_offset;                                             \
+  }                                                                            \
+  label->head = -1
+
+  BIND(unresolved_cb_, UpdateCBOffset);
+  BIND(unresolved_cj_, UpdateCJOffset);
+  BIND(unresolved_b_, UpdateBOffset);
+  BIND(unresolved_j_, UpdateJOffset);
+  BIND(unresolved_far_, UpdateFarOffset);
+
+  label->BindTo(target_position);
+}
+
+intptr_t MicroAssembler::UpdateCBOffset(intptr_t branch_position,
+                                        intptr_t new_offset) {
+  CInstr instr(Read16(branch_position));
+  ASSERT((instr.opcode() == C_BEQZ) || (instr.opcode() == C_BNEZ));
+  intptr_t old_offset = instr.b_imm();
+  if (!IsCBImm(new_offset)) {
+    FATAL("Incorrect Assembler::kNearJump");
+  }
+  Write16(branch_position,
+          instr.opcode() | EncodeCRs1p(instr.rs1p()) | EncodeCBImm(new_offset));
+  return old_offset;
+}
+
+intptr_t MicroAssembler::UpdateCJOffset(intptr_t branch_position,
+                                        intptr_t new_offset) {
+  CInstr instr(Read16(branch_position));
+  ASSERT((instr.opcode() == C_J) || (instr.opcode() == C_JAL));
+  intptr_t old_offset = instr.j_imm();
+  if (!IsCJImm(new_offset)) {
+    FATAL("Incorrect Assembler::kNearJump");
+  }
+  Write16(branch_position, instr.opcode() | EncodeCJImm(new_offset));
+  return old_offset;
+}
+
+intptr_t MicroAssembler::UpdateBOffset(intptr_t branch_position,
+                                       intptr_t new_offset) {
+  Instr instr(Read32(branch_position));
+  ASSERT(instr.opcode() == BRANCH);
+  intptr_t old_offset = instr.btype_imm();
+  if (!IsBTypeImm(new_offset)) {
+    BailoutWithBranchOffsetError();
+  }
+  Write32(branch_position, EncodeRs2(instr.rs2()) | EncodeRs1(instr.rs1()) |
+                               EncodeFunct3(instr.funct3()) |
+                               EncodeOpcode(instr.opcode()) |
+                               EncodeBTypeImm(new_offset));
+  return old_offset;
+}
+
+intptr_t MicroAssembler::UpdateJOffset(intptr_t branch_position,
+                                       intptr_t new_offset) {
+  Instr instr(Read32(branch_position));
+  ASSERT(instr.opcode() == JAL);
+  intptr_t old_offset = instr.jtype_imm();
+  if (!IsJTypeImm(new_offset)) {
+    BailoutWithBranchOffsetError();
+  }
+  Write32(branch_position, EncodeRd(instr.rd()) | EncodeOpcode(instr.opcode()) |
+                               EncodeJTypeImm(new_offset));
+  return old_offset;
+}
+
+intptr_t MicroAssembler::UpdateFarOffset(intptr_t branch_position,
+                                         intptr_t new_offset) {
+  Instr auipc_instr(Read32(branch_position));
+  ASSERT(auipc_instr.opcode() == AUIPC);
+  ASSERT(auipc_instr.rd() == FAR_TMP);
+  Instr jr_instr(Read32(branch_position + 4));
+  ASSERT(jr_instr.opcode() == JALR);
+  ASSERT(jr_instr.rd() == ZR);
+  ASSERT(jr_instr.funct3() == F3_0);
+  ASSERT(jr_instr.rs1() == FAR_TMP);
+  intptr_t old_offset = auipc_instr.utype_imm() + jr_instr.itype_imm();
+  intx_t lo = new_offset << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (new_offset - lo) << (XLEN - 32) >> (XLEN - 32);
+  if (!IsUTypeImm(hi)) {
+    FATAL("Jump/branch distance exceeds 2GB!");
+  }
+  Write32(branch_position,
+          EncodeUTypeImm(hi) | EncodeRd(FAR_TMP) | EncodeOpcode(AUIPC));
+  Write32(branch_position + 4, EncodeITypeImm(lo) | EncodeRs1(FAR_TMP) |
+                                   EncodeFunct3(F3_0) | EncodeRd(ZR) |
+                                   EncodeOpcode(JALR));
+  return old_offset;
+}
+
+void MicroAssembler::lui(Register rd, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C) && (rd != ZR) && (rd != SP) && IsCUImm(imm)) {
+    c_lui(rd, imm);
+    return;
+  }
+  EmitUType(imm, rd, LUI);
+}
+
+void MicroAssembler::lui_fixed(Register rd, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitUType(imm, rd, LUI);
+}
+
+void MicroAssembler::auipc(Register rd, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitUType(imm, rd, AUIPC);
+}
+
+void MicroAssembler::jal(Register rd, Label* label, JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C) &&
+      ((distance == kNearJump) ||
+       (label->IsBound() && IsCJImm(label->Position() - Position())))) {
+    if (rd == ZR) {
+      c_j(label);
+      return;
+    }
+#if XLEN == 32
+    if (rd == RA) {
+      c_jal(label);
+      return;
+    }
+#endif  // XLEN == 32
+  }
+  EmitJump(rd, label, JAL, distance);
+}
+
+void MicroAssembler::jalr(Register rd, Register rs1, intptr_t offset) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if (rs1 != ZR && offset == 0) {
+      if (rd == ZR) {
+        c_jr(rs1);
+        return;
+      } else if (rd == RA) {
+        c_jalr(rs1);
+        return;
+      }
+    }
+  }
+  EmitIType(offset, rs1, F3_0, rd, JALR);
+}
+
+void MicroAssembler::jalr_fixed(Register rd, Register rs1, intptr_t offset) {
+  ASSERT(Supports(RV_I));
+  EmitIType(offset, rs1, F3_0, rd, JALR);
+}
+
+void MicroAssembler::beq(Register rs1,
+                         Register rs2,
+                         Label* label,
+                         JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C) &&
+      ((distance == kNearJump) ||
+       (label->IsBound() && IsCBImm(label->Position() - Position())))) {
+    if ((rs1 == ZR) && IsCRs1p(rs2)) {
+      c_beqz(rs2, label);
+      return;
+    } else if ((rs2 == ZR) && IsCRs1p(rs1)) {
+      c_beqz(rs1, label);
+      return;
+    }
+  }
+  EmitBranch(rs1, rs2, label, BEQ, distance);
+}
+
+void MicroAssembler::bne(Register rs1,
+                         Register rs2,
+                         Label* label,
+                         JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C) &&
+      ((distance == kNearJump) ||
+       (label->IsBound() && IsCBImm(label->Position() - Position())))) {
+    if ((rs1 == ZR) && IsCRs1p(rs2)) {
+      c_bnez(rs2, label);
+      return;
+    } else if ((rs2 == ZR) && IsCRs1p(rs1)) {
+      c_bnez(rs1, label);
+      return;
+    }
+  }
+  EmitBranch(rs1, rs2, label, BNE, distance);
+}
+
+void MicroAssembler::blt(Register rs1,
+                         Register rs2,
+                         Label* label,
+                         JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  EmitBranch(rs1, rs2, label, BLT, distance);
+}
+
+void MicroAssembler::bge(Register rs1,
+                         Register rs2,
+                         Label* label,
+                         JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  EmitBranch(rs1, rs2, label, BGE, distance);
+}
+
+void MicroAssembler::bltu(Register rs1,
+                          Register rs2,
+                          Label* label,
+                          JumpDistance distance) {
+  ASSERT(Supports(RV_I));
+  EmitBranch(rs1, rs2, label, BLTU, distance);
+}
+
+void MicroAssembler::bgeu(Register rs1,
+                          Register rs2,
+                          Label* label,
+                          JumpDistance distance) {
+  EmitBranch(rs1, rs2, label, BGEU, distance);
+}
+
+void MicroAssembler::lb(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitIType(addr.offset(), addr.base(), LB, rd, LOAD);
+}
+
+void MicroAssembler::lh(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitIType(addr.offset(), addr.base(), LH, rd, LOAD);
+}
+
+void MicroAssembler::lw(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd != ZR) && (addr.base() == SP) && IsCSPLoad4Imm(addr.offset())) {
+      c_lwsp(rd, addr);
+      return;
+    }
+    if (IsCRdp(rd) && IsCRs1p(addr.base()) && IsCMem4Imm(addr.offset())) {
+      c_lw(rd, addr);
+      return;
+    }
+  }
+  EmitIType(addr.offset(), addr.base(), LW, rd, LOAD);
+}
+
+void MicroAssembler::lbu(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitIType(addr.offset(), addr.base(), LBU, rd, LOAD);
+}
+
+void MicroAssembler::lhu(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitIType(addr.offset(), addr.base(), LHU, rd, LOAD);
+}
+
+void MicroAssembler::sb(Register rs2, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitSType(addr.offset(), rs2, addr.base(), SB, STORE);
+}
+
+void MicroAssembler::sh(Register rs2, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitSType(addr.offset(), rs2, addr.base(), SH, STORE);
+}
+
+void MicroAssembler::sw(Register rs2, Address addr) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPStore4Imm(addr.offset())) {
+      c_swsp(rs2, addr);
+      return;
+    }
+    if (IsCRs2p(rs2) && IsCRs1p(addr.base()) && IsCMem4Imm(addr.offset())) {
+      c_sw(rs2, addr);
+      return;
+    }
+  }
+  EmitSType(addr.offset(), rs2, addr.base(), SW, STORE);
+}
+
+void MicroAssembler::addi(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd != ZR) && (rs1 == ZR) && IsCIImm(imm)) {
+      c_li(rd, imm);
+      return;
+    }
+    if ((rd == rs1) && IsCIImm(imm) && (imm != 0)) {
+      c_addi(rd, rs1, imm);
+      return;
+    }
+    if ((rd == SP) && (rs1 == SP) && IsCI16Imm(imm) && (imm != 0)) {
+      c_addi16sp(rd, rs1, imm);
+      return;
+    }
+    if (IsCRdp(rd) && (rs1 == SP) && IsCI4SPNImm(imm) && (imm != 0)) {
+      c_addi4spn(rd, rs1, imm);
+      return;
+    }
+    if (imm == 0) {
+      if ((rd == ZR) && (rs1 == ZR)) {
+        c_nop();
+        return;
+      }
+      if ((rd != ZR) && (rs1 != ZR)) {
+        c_mv(rd, rs1);
+        return;
+      }
+    }
+  }
+  EmitIType(imm, rs1, ADDI, rd, OPIMM);
+}
+
+void MicroAssembler::slti(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(imm, rs1, SLTI, rd, OPIMM);
+}
+
+void MicroAssembler::sltiu(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(imm, rs1, SLTIU, rd, OPIMM);
+}
+
+void MicroAssembler::xori(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(imm, rs1, XORI, rd, OPIMM);
+}
+
+void MicroAssembler::ori(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(imm, rs1, ORI, rd, OPIMM);
+}
+
+void MicroAssembler::andi(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCIImm(imm)) {
+      c_andi(rd, rs1, imm);
+      return;
+    }
+  }
+  EmitIType(imm, rs1, ANDI, rd, OPIMM);
+}
+
+void MicroAssembler::slli(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < XLEN));
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && (shamt != 0) && IsCIImm(shamt)) {
+      c_slli(rd, rs1, shamt);
+      return;
+    }
+  }
+  EmitRType(F7_0, shamt, rs1, SLLI, rd, OPIMM);
+}
+
+void MicroAssembler::srli(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < XLEN));
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && (shamt != 0) && IsCIImm(shamt)) {
+      c_srli(rd, rs1, shamt);
+      return;
+    }
+  }
+  EmitRType(F7_0, shamt, rs1, SRI, rd, OPIMM);
+}
+
+void MicroAssembler::srai(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < XLEN));
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && (shamt != 0) && IsCIImm(shamt)) {
+      c_srai(rd, rs1, shamt);
+      return;
+    }
+  }
+  EmitRType(SRA, shamt, rs1, SRI, rd, OPIMM);
+}
+
+void MicroAssembler::add(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if (rd == rs1) {
+      c_add(rd, rs1, rs2);
+      return;
+    }
+    if (rd == rs2) {
+      c_add(rd, rs2, rs1);
+      return;
+    }
+  }
+  EmitRType(F7_0, rs2, rs1, ADD, rd, OP);
+}
+
+void MicroAssembler::sub(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_sub(rd, rs1, rs2);
+      return;
+    }
+  }
+  EmitRType(SUB, rs2, rs1, ADD, rd, OP);
+}
+
+void MicroAssembler::sll(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SLL, rd, OP);
+}
+
+void MicroAssembler::slt(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SLT, rd, OP);
+}
+
+void MicroAssembler::sltu(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SLTU, rd, OP);
+}
+
+void MicroAssembler::xor_(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_xor(rd, rs1, rs2);
+      return;
+    }
+    if ((rd == rs2) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_xor(rd, rs2, rs1);
+      return;
+    }
+  }
+  EmitRType(F7_0, rs2, rs1, XOR, rd, OP);
+}
+
+void MicroAssembler::srl(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SR, rd, OP);
+}
+
+void MicroAssembler::sra(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(SRA, rs2, rs1, SR, rd, OP);
+}
+
+void MicroAssembler::or_(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_or(rd, rs1, rs2);
+      return;
+    }
+    if ((rd == rs2) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_or(rd, rs2, rs1);
+      return;
+    }
+  }
+  EmitRType(F7_0, rs2, rs1, OR, rd, OP);
+}
+
+void MicroAssembler::and_(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_and(rd, rs1, rs2);
+      return;
+    }
+    if ((rd == rs2) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_and(rd, rs2, rs1);
+      return;
+    }
+  }
+  EmitRType(F7_0, rs2, rs1, AND, rd, OP);
+}
+
+void MicroAssembler::fence(HartEffects predecessor, HartEffects successor) {
+  ASSERT((predecessor & kAll) == predecessor);
+  ASSERT((successor & kAll) == successor);
+  ASSERT(Supports(RV_I));
+  EmitIType((predecessor << 4) | successor, ZR, FENCE, ZR, MISCMEM);
+}
+
+void MicroAssembler::fencei() {
+  ASSERT(Supports(RV_I));
+  EmitIType(0, ZR, FENCEI, ZR, MISCMEM);
+}
+
+void MicroAssembler::ecall() {
+  ASSERT(Supports(RV_I));
+  EmitIType(ECALL, ZR, F3_0, ZR, SYSTEM);
+}
+void MicroAssembler::ebreak() {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    c_ebreak();
+    return;
+  }
+  EmitIType(EBREAK, ZR, F3_0, ZR, SYSTEM);
+}
+void MicroAssembler::SimulatorPrintObject(Register rs1) {
+  ASSERT(Supports(RV_I));
+  EmitIType(ECALL, rs1, F3_0, ZR, SYSTEM);
+}
+
+void MicroAssembler::csrrw(Register rd, uint32_t csr, Register rs1) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, rs1, CSRRW, rd, SYSTEM);
+}
+
+void MicroAssembler::csrrs(Register rd, uint32_t csr, Register rs1) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, rs1, CSRRS, rd, SYSTEM);
+}
+
+void MicroAssembler::csrrc(Register rd, uint32_t csr, Register rs1) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, rs1, CSRRC, rd, SYSTEM);
+}
+
+void MicroAssembler::csrrwi(Register rd, uint32_t csr, uint32_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, Register(imm), CSRRWI, rd, SYSTEM);
+}
+
+void MicroAssembler::csrrsi(Register rd, uint32_t csr, uint32_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, Register(imm), CSRRSI, rd, SYSTEM);
+}
+
+void MicroAssembler::csrrci(Register rd, uint32_t csr, uint32_t imm) {
+  ASSERT(Supports(RV_I));
+  EmitIType(csr, Register(imm), CSRRCI, rd, SYSTEM);
+}
+
+void MicroAssembler::trap() {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    Emit16(0);  // Permanently reserved illegal instruction.
+  } else {
+    Emit32(0);  // Permanently reserved illegal instruction.
+  }
+}
+
+#if XLEN >= 64
+void MicroAssembler::lwu(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  EmitIType(addr.offset(), addr.base(), LWU, rd, LOAD);
+}
+
+void MicroAssembler::ld(Register rd, Address addr) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd != ZR) && (addr.base() == SP) && IsCSPLoad8Imm(addr.offset())) {
+      c_ldsp(rd, addr);
+      return;
+    }
+    if (IsCRdp(rd) && IsCRs1p(addr.base()) && IsCMem8Imm(addr.offset())) {
+      c_ld(rd, addr);
+      return;
+    }
+  }
+  EmitIType(addr.offset(), addr.base(), LD, rd, LOAD);
+}
+
+void MicroAssembler::sd(Register rs2, Address addr) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPStore8Imm(addr.offset())) {
+      c_sdsp(rs2, addr);
+      return;
+    }
+    if (IsCRs2p(rs2) && IsCRs1p(addr.base()) && IsCMem8Imm(addr.offset())) {
+      c_sd(rs2, addr);
+      return;
+    }
+  }
+  EmitSType(addr.offset(), rs2, addr.base(), SD, STORE);
+}
+
+void MicroAssembler::addiw(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd != ZR) && (rs1 == ZR) && IsCIImm(imm)) {
+      c_li(rd, imm);
+      return;
+    }
+    if ((rd == rs1) && (rd != ZR) && IsCIImm(imm)) {
+      c_addiw(rd, rs1, imm);
+      return;
+    }
+  }
+  EmitIType(imm, rs1, ADDI, rd, OPIMM32);
+}
+
+void MicroAssembler::slliw(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < 32));
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, shamt, rs1, SLLI, rd, OPIMM32);
+}
+
+void MicroAssembler::srliw(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < 32));
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, shamt, rs1, SRI, rd, OPIMM32);
+}
+
+void MicroAssembler::sraiw(Register rd, Register rs1, intptr_t shamt) {
+  ASSERT((shamt > 0) && (shamt < XLEN));
+  ASSERT(Supports(RV_I));
+  EmitRType(SRA, shamt, rs1, SRI, rd, OPIMM32);
+}
+
+void MicroAssembler::addw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_addw(rd, rs1, rs2);
+      return;
+    }
+    if ((rd == rs2) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_addw(rd, rs2, rs1);
+      return;
+    }
+  }
+  EmitRType(F7_0, rs2, rs1, ADD, rd, OP32);
+}
+
+void MicroAssembler::subw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  if (Supports(RV_C)) {
+    if ((rd == rs1) && IsCRs1p(rs1) && IsCRs2p(rs2)) {
+      c_subw(rd, rs1, rs2);
+      return;
+    }
+  }
+  EmitRType(SUB, rs2, rs1, ADD, rd, OP32);
+}
+
+void MicroAssembler::sllw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SLL, rd, OP32);
+}
+
+void MicroAssembler::srlw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(F7_0, rs2, rs1, SR, rd, OP32);
+}
+void MicroAssembler::sraw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_I));
+  EmitRType(SRA, rs2, rs1, SR, rd, OP32);
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::mul(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, MUL, rd, OP);
+}
+
+void MicroAssembler::mulh(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, MULH, rd, OP);
+}
+
+void MicroAssembler::mulhsu(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, MULHSU, rd, OP);
+}
+
+void MicroAssembler::mulhu(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, MULHU, rd, OP);
+}
+
+void MicroAssembler::div(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, DIV, rd, OP);
+}
+
+void MicroAssembler::divu(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, DIVU, rd, OP);
+}
+
+void MicroAssembler::rem(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, REM, rd, OP);
+}
+
+void MicroAssembler::remu(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, REMU, rd, OP);
+}
+
+#if XLEN >= 64
+void MicroAssembler::mulw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, MULW, rd, OP32);
+}
+
+void MicroAssembler::divw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, DIVW, rd, OP32);
+}
+
+void MicroAssembler::divuw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, DIVUW, rd, OP32);
+}
+
+void MicroAssembler::remw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, REMW, rd, OP32);
+}
+
+void MicroAssembler::remuw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_M));
+  EmitRType(MULDIV, rs2, rs1, REMUW, rd, OP32);
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::lrw(Register rd, Address addr, std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(LR, order, ZR, addr.base(), WIDTH32, rd, AMO);
+}
+void MicroAssembler::scw(Register rd,
+                         Register rs2,
+                         Address addr,
+                         std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(SC, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amoswapw(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOSWAP, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amoaddw(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOADD, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amoxorw(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOXOR, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amoandw(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOAND, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amoorw(Register rd,
+                            Register rs2,
+                            Address addr,
+                            std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOOR, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amominw(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMIN, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amomaxw(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMAX, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amominuw(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMINU, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+void MicroAssembler::amomaxuw(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMAXU, order, rs2, addr.base(), WIDTH32, rd, AMO);
+}
+
+#if XLEN >= 64
+void MicroAssembler::lrd(Register rd, Address addr, std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(LR, order, ZR, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::scd(Register rd,
+                         Register rs2,
+                         Address addr,
+                         std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(SC, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amoswapd(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOSWAP, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amoaddd(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOADD, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amoxord(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOXOR, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amoandd(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOAND, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amoord(Register rd,
+                            Register rs2,
+                            Address addr,
+                            std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOOR, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amomind(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMIN, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amomaxd(Register rd,
+                             Register rs2,
+                             Address addr,
+                             std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMAX, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amominud(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMINU, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+
+void MicroAssembler::amomaxud(Register rd,
+                              Register rs2,
+                              Address addr,
+                              std::memory_order order) {
+  ASSERT(addr.offset() == 0);
+  ASSERT(Supports(RV_A));
+  EmitRType(AMOMAXU, order, rs2, addr.base(), WIDTH64, rd, AMO);
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::flw(FRegister rd, Address addr) {
+  ASSERT(Supports(RV_F));
+#if XLEN == 32
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPLoad4Imm(addr.offset())) {
+      c_flwsp(rd, addr);
+      return;
+    }
+    if (IsCFRdp(rd) && IsCRs1p(addr.base()) && IsCMem4Imm(addr.offset())) {
+      c_flw(rd, addr);
+      return;
+    }
+  }
+#endif  // XLEN == 32
+  EmitIType(addr.offset(), addr.base(), S, rd, LOADFP);
+}
+
+void MicroAssembler::fsw(FRegister rs2, Address addr) {
+  ASSERT(Supports(RV_F));
+#if XLEN == 32
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPStore4Imm(addr.offset())) {
+      c_fswsp(rs2, addr);
+      return;
+    }
+    if (IsCFRs2p(rs2) && IsCRs1p(addr.base()) && IsCMem4Imm(addr.offset())) {
+      c_fsw(rs2, addr);
+      return;
+    }
+  }
+#endif  // XLEN == 32
+  EmitSType(addr.offset(), rs2, addr.base(), S, STOREFP);
+}
+
+void MicroAssembler::fmadds(FRegister rd,
+                            FRegister rs1,
+                            FRegister rs2,
+                            FRegister rs3,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitR4Type(rs3, F2_S, rs2, rs1, rounding, rd, FMADD);
+}
+
+void MicroAssembler::fmsubs(FRegister rd,
+                            FRegister rs1,
+                            FRegister rs2,
+                            FRegister rs3,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitR4Type(rs3, F2_S, rs2, rs1, rounding, rd, FMSUB);
+}
+
+void MicroAssembler::fnmsubs(FRegister rd,
+                             FRegister rs1,
+                             FRegister rs2,
+                             FRegister rs3,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitR4Type(rs3, F2_S, rs2, rs1, rounding, rd, FNMSUB);
+}
+
+void MicroAssembler::fnmadds(FRegister rd,
+                             FRegister rs1,
+                             FRegister rs2,
+                             FRegister rs3,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitR4Type(rs3, F2_S, rs2, rs1, rounding, rd, FNMADD);
+}
+
+void MicroAssembler::fadds(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FADDS, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsubs(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FSUBS, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fmuls(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FMULS, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fdivs(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FDIVS, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsqrts(FRegister rd,
+                            FRegister rs1,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FSQRTS, FRegister(0), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjs(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FSGNJS, rs2, rs1, J, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjns(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FSGNJS, rs2, rs1, JN, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjxs(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FSGNJS, rs2, rs1, JX, rd, OPFP);
+}
+
+void MicroAssembler::fmins(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FMINMAXS, rs2, rs1, MIN, rd, OPFP);
+}
+
+void MicroAssembler::fmaxs(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FMINMAXS, rs2, rs1, MAX, rd, OPFP);
+}
+
+void MicroAssembler::feqs(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCMPS, rs2, rs1, FEQ, rd, OPFP);
+}
+
+void MicroAssembler::flts(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCMPS, rs2, rs1, FLT, rd, OPFP);
+}
+
+void MicroAssembler::fles(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCMPS, rs2, rs1, FLE, rd, OPFP);
+}
+
+void MicroAssembler::fclasss(Register rd, FRegister rs1) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCLASSS, FRegister(0), rs1, F3_1, rd, OPFP);
+}
+
+void MicroAssembler::fcvtws(Register rd, FRegister rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTintS, FRegister(W), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtwus(Register rd,
+                             FRegister rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTintS, FRegister(WU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtsw(FRegister rd, Register rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTSint, FRegister(W), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtswu(FRegister rd,
+                             Register rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTSint, FRegister(WU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fmvxw(Register rd, FRegister rs1) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FMVXW, FRegister(0), rs1, F3_0, rd, OPFP);
+}
+
+void MicroAssembler::fmvwx(FRegister rd, Register rs1) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FMVWX, FRegister(0), rs1, F3_0, rd, OPFP);
+}
+
+#if XLEN >= 64
+void MicroAssembler::fcvtls(Register rd, FRegister rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTintS, FRegister(L), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtlus(Register rd,
+                             FRegister rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTintS, FRegister(LU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtsl(FRegister rd, Register rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTSint, FRegister(L), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtslu(FRegister rd,
+                             Register rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_F));
+  EmitRType(FCVTSint, FRegister(LU), rs1, rounding, rd, OPFP);
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::fld(FRegister rd, Address addr) {
+  ASSERT(Supports(RV_D));
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPLoad8Imm(addr.offset())) {
+      c_fldsp(rd, addr);
+      return;
+    }
+    if (IsCFRdp(rd) && IsCRs1p(addr.base()) && IsCMem8Imm(addr.offset())) {
+      c_fld(rd, addr);
+      return;
+    }
+  }
+  EmitIType(addr.offset(), addr.base(), D, rd, LOADFP);
+}
+
+void MicroAssembler::fsd(FRegister rs2, Address addr) {
+  ASSERT(Supports(RV_D));
+  if (Supports(RV_C)) {
+    if ((addr.base() == SP) && IsCSPStore8Imm(addr.offset())) {
+      c_fsdsp(rs2, addr);
+      return;
+    }
+    if (IsCFRs2p(rs2) && IsCRs1p(addr.base()) && IsCMem8Imm(addr.offset())) {
+      c_fsd(rs2, addr);
+      return;
+    }
+  }
+  EmitSType(addr.offset(), rs2, addr.base(), D, STOREFP);
+}
+
+void MicroAssembler::fmaddd(FRegister rd,
+                            FRegister rs1,
+                            FRegister rs2,
+                            FRegister rs3,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitR4Type(rs3, F2_D, rs2, rs1, rounding, rd, FMADD);
+}
+
+void MicroAssembler::fmsubd(FRegister rd,
+                            FRegister rs1,
+                            FRegister rs2,
+                            FRegister rs3,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitR4Type(rs3, F2_D, rs2, rs1, rounding, rd, FMSUB);
+}
+
+void MicroAssembler::fnmsubd(FRegister rd,
+                             FRegister rs1,
+                             FRegister rs2,
+                             FRegister rs3,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitR4Type(rs3, F2_D, rs2, rs1, rounding, rd, FNMSUB);
+}
+
+void MicroAssembler::fnmaddd(FRegister rd,
+                             FRegister rs1,
+                             FRegister rs2,
+                             FRegister rs3,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitR4Type(rs3, F2_D, rs2, rs1, rounding, rd, FNMADD);
+}
+
+void MicroAssembler::faddd(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FADDD, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsubd(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FSUBD, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fmuld(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FMULD, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fdivd(FRegister rd,
+                           FRegister rs1,
+                           FRegister rs2,
+                           RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FDIVD, rs2, rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsqrtd(FRegister rd,
+                            FRegister rs1,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FSQRTD, FRegister(0), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjd(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FSGNJD, rs2, rs1, J, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjnd(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FSGNJD, rs2, rs1, JN, rd, OPFP);
+}
+
+void MicroAssembler::fsgnjxd(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FSGNJD, rs2, rs1, JX, rd, OPFP);
+}
+
+void MicroAssembler::fmind(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FMINMAXD, rs2, rs1, MIN, rd, OPFP);
+}
+
+void MicroAssembler::fmaxd(FRegister rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FMINMAXD, rs2, rs1, MAX, rd, OPFP);
+}
+
+void MicroAssembler::fcvtsd(FRegister rd,
+                            FRegister rs1,
+                            RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTS, FRegister(1), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtds(FRegister rd, FRegister rs1) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTD, FRegister(0), rs1, F3_0, rd, OPFP);
+}
+
+void MicroAssembler::feqd(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCMPD, rs2, rs1, FEQ, rd, OPFP);
+}
+
+void MicroAssembler::fltd(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCMPD, rs2, rs1, FLT, rd, OPFP);
+}
+
+void MicroAssembler::fled(Register rd, FRegister rs1, FRegister rs2) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCMPD, rs2, rs1, FLE, rd, OPFP);
+}
+
+void MicroAssembler::fclassd(Register rd, FRegister rs1) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCLASSD, FRegister(0), rs1, F3_1, rd, OPFP);
+}
+
+void MicroAssembler::fcvtwd(Register rd, FRegister rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTintD, FRegister(W), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtwud(Register rd,
+                             FRegister rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTintD, FRegister(WU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtdw(FRegister rd, Register rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTDint, FRegister(W), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtdwu(FRegister rd,
+                             Register rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTDint, FRegister(WU), rs1, rounding, rd, OPFP);
+}
+
+#if XLEN >= 64
+void MicroAssembler::fcvtld(Register rd, FRegister rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTintD, FRegister(L), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtlud(Register rd,
+                             FRegister rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTintD, FRegister(LU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fmvxd(Register rd, FRegister rs1) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FMVXD, FRegister(0), rs1, F3_0, rd, OPFP);
+}
+
+void MicroAssembler::fcvtdl(FRegister rd, Register rs1, RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTDint, FRegister(L), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fcvtdlu(FRegister rd,
+                             Register rs1,
+                             RoundingMode rounding) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FCVTDint, FRegister(LU), rs1, rounding, rd, OPFP);
+}
+
+void MicroAssembler::fmvdx(FRegister rd, Register rs1) {
+  ASSERT(Supports(RV_D));
+  EmitRType(FMVDX, FRegister(0), rs1, F3_0, rd, OPFP);
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::c_lwsp(Register rd, Address addr) {
+  ASSERT(rd != ZR);
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  Emit16(C_LWSP | EncodeCRd(rd) | EncodeCSPLoad4Imm(addr.offset()));
+}
+
+#if XLEN == 32
+void MicroAssembler::c_flwsp(FRegister rd, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_F));
+  Emit16(C_FLWSP | EncodeCFRd(rd) | EncodeCSPLoad4Imm(addr.offset()));
+}
+#else
+void MicroAssembler::c_ldsp(Register rd, Address addr) {
+  ASSERT(rd != ZR);
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  Emit16(C_LDSP | EncodeCRd(rd) | EncodeCSPLoad8Imm(addr.offset()));
+}
+#endif
+
+void MicroAssembler::c_fldsp(FRegister rd, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_D));
+  Emit16(C_FLDSP | EncodeCFRd(rd) | EncodeCSPLoad8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_swsp(Register rs2, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  Emit16(C_SWSP | EncodeCRs2(rs2) | EncodeCSPStore4Imm(addr.offset()));
+}
+
+#if XLEN == 32
+void MicroAssembler::c_fswsp(FRegister rs2, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_F));
+  Emit16(C_FSWSP | EncodeCFRs2(rs2) | EncodeCSPStore4Imm(addr.offset()));
+}
+#else
+void MicroAssembler::c_sdsp(Register rs2, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  Emit16(C_SDSP | EncodeCRs2(rs2) | EncodeCSPStore8Imm(addr.offset()));
+}
+#endif
+void MicroAssembler::c_fsdsp(FRegister rs2, Address addr) {
+  ASSERT(addr.base() == SP);
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_D));
+  Emit16(C_FSDSP | EncodeCFRs2(rs2) | EncodeCSPStore8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_lw(Register rd, Address addr) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_LW | EncodeCRdp(rd) | EncodeCRs1p(addr.base()) |
+         EncodeCMem4Imm(addr.offset()));
+}
+
+void MicroAssembler::c_ld(Register rd, Address addr) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_LD | EncodeCRdp(rd) | EncodeCRs1p(addr.base()) |
+         EncodeCMem8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_flw(FRegister rd, Address addr) {
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_F));
+  Emit16(C_FLW | EncodeCFRdp(rd) | EncodeCRs1p(addr.base()) |
+         EncodeCMem4Imm(addr.offset()));
+}
+
+void MicroAssembler::c_fld(FRegister rd, Address addr) {
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_D));
+  Emit16(C_FLD | EncodeCFRdp(rd) | EncodeCRs1p(addr.base()) |
+         EncodeCMem8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_sw(Register rs2, Address addr) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_SW | EncodeCRs1p(addr.base()) | EncodeCRs2p(rs2) |
+         EncodeCMem4Imm(addr.offset()));
+}
+
+void MicroAssembler::c_sd(Register rs2, Address addr) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_SD | EncodeCRs1p(addr.base()) | EncodeCRs2p(rs2) |
+         EncodeCMem8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_fsw(FRegister rs2, Address addr) {
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_F));
+  Emit16(C_FSW | EncodeCRs1p(addr.base()) | EncodeCFRs2p(rs2) |
+         EncodeCMem4Imm(addr.offset()));
+}
+
+void MicroAssembler::c_fsd(FRegister rs2, Address addr) {
+  ASSERT(Supports(RV_C));
+  ASSERT(Supports(RV_D));
+  Emit16(C_FSD | EncodeCRs1p(addr.base()) | EncodeCFRs2p(rs2) |
+         EncodeCMem8Imm(addr.offset()));
+}
+
+void MicroAssembler::c_j(Label* label) {
+  ASSERT(Supports(RV_C));
+  EmitCJump(label, C_J);
+}
+
+#if XLEN == 32
+void MicroAssembler::c_jal(Label* label) {
+  ASSERT(Supports(RV_C));
+  EmitCJump(label, C_JAL);
+}
+#endif  // XLEN == 32
+
+void MicroAssembler::c_jr(Register rs1) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rs1 != ZR);
+  Emit16(C_JR | EncodeCRs1(rs1) | EncodeCRs2(ZR));
+}
+
+void MicroAssembler::c_jalr(Register rs1) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_JALR | EncodeCRs1(rs1) | EncodeCRs2(ZR));
+}
+
+void MicroAssembler::c_beqz(Register rs1p, Label* label) {
+  ASSERT(Supports(RV_C));
+  EmitCBranch(rs1p, label, C_BEQZ);
+}
+
+void MicroAssembler::c_bnez(Register rs1p, Label* label) {
+  ASSERT(Supports(RV_C));
+  EmitCBranch(rs1p, label, C_BNEZ);
+}
+
+void MicroAssembler::c_li(Register rd, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd != ZR);
+  Emit16(C_LI | EncodeCRd(rd) | EncodeCIImm(imm));
+}
+
+void MicroAssembler::c_lui(Register rd, uintptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd != ZR);
+  ASSERT(rd != SP);
+  Emit16(C_LUI | EncodeCRd(rd) | EncodeCUImm(imm));
+}
+
+void MicroAssembler::c_addi(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(imm != 0);
+  ASSERT(rd == rs1);
+  Emit16(C_ADDI | EncodeCRd(rd) | EncodeCIImm(imm));
+}
+
+#if XLEN >= 64
+void MicroAssembler::c_addiw(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  Emit16(C_ADDIW | EncodeCRd(rd) | EncodeCIImm(imm));
+}
+#endif
+void MicroAssembler::c_addi16sp(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  Emit16(C_ADDI16SP | EncodeCRd(rd) | EncodeCI16Imm(imm));
+}
+
+void MicroAssembler::c_addi4spn(Register rdp, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rs1 == SP);
+  ASSERT(imm != 0);
+  Emit16(C_ADDI4SPN | EncodeCRdp(rdp) | EncodeCI4SPNImm(imm));
+}
+
+void MicroAssembler::c_slli(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  ASSERT(imm != 0);
+  Emit16(C_SLLI | EncodeCRd(rd) | EncodeCIImm(imm));
+}
+
+void MicroAssembler::c_srli(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  ASSERT(imm != 0);
+  Emit16(C_SRLI | EncodeCRs1p(rd) | EncodeCIImm(imm));
+}
+
+void MicroAssembler::c_srai(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  ASSERT(imm != 0);
+  Emit16(C_SRAI | EncodeCRs1p(rd) | EncodeCIImm(imm));
+}
+
+void MicroAssembler::c_andi(Register rd, Register rs1, intptr_t imm) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  Emit16(C_ANDI | EncodeCRs1p(rd) | EncodeCIImm(imm));
+}
+
+void MicroAssembler::c_mv(Register rd, Register rs2) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd != ZR);
+  ASSERT(rs2 != ZR);
+  Emit16(C_MV | EncodeCRd(rd) | EncodeCRs2(rs2));
+}
+
+void MicroAssembler::c_add(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd != ZR);
+  ASSERT(rd == rs1);
+  ASSERT(rs2 != ZR);
+  Emit16(C_ADD | EncodeCRd(rd) | EncodeCRs2(rs2));
+}
+
+void MicroAssembler::c_and(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  ASSERT(rd == rs1);
+  Emit16(C_AND | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+
+void MicroAssembler::c_or(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_OR | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+
+void MicroAssembler::c_xor(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_XOR | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+
+void MicroAssembler::c_sub(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_SUB | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+
+#if XLEN >= 64
+void MicroAssembler::c_addw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_ADDW | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+
+void MicroAssembler::c_subw(Register rd, Register rs1, Register rs2) {
+  ASSERT(Supports(RV_C));
+  Emit16(C_SUBW | EncodeCRs1p(rs1) | EncodeCRs2p(rs2));
+}
+#endif  // XLEN >= 64
+
+void MicroAssembler::c_nop() {
+  ASSERT(Supports(RV_C));
+  Emit16(C_NOP);
+}
+
+void MicroAssembler::c_ebreak() {
+  ASSERT(Supports(RV_C));
+  Emit16(C_EBREAK);
+}
+
+static Funct3 InvertFunct3(Funct3 func) {
+  switch (func) {
+    case BEQ:
+      return BNE;
+    case BNE:
+      return BEQ;
+    case BGE:
+      return BLT;
+    case BGEU:
+      return BLTU;
+    case BLT:
+      return BGE;
+    case BLTU:
+      return BGEU;
+    default:
+      UNREACHABLE();
+  }
+}
+
+void MicroAssembler::EmitBranch(Register rs1,
+                                Register rs2,
+                                Label* label,
+                                Funct3 func,
+                                JumpDistance distance) {
+  intptr_t offset;
+  if (label->IsBound()) {
+    // Backward branch: use near or far branch based on actual distance.
+    offset = label->Position() - Position();
+    if (IsBTypeImm(offset)) {
+      EmitBType(offset, rs2, rs1, func, BRANCH);
+      return;
+    }
+
+    if (IsJTypeImm(offset + 4)) {
+      intptr_t start = Position();
+      const intptr_t kFarBranchLength = 8;
+      EmitBType(kFarBranchLength, rs2, rs1, InvertFunct3(func), BRANCH);
+      offset = label->Position() - Position();
+      EmitJType(offset, ZR, JAL);
+      intptr_t end = Position();
+      ASSERT_EQUAL(end - start, kFarBranchLength);
+      return;
+    }
+
+    intptr_t start = Position();
+    const intptr_t kFarBranchLength = 12;
+    EmitBType(kFarBranchLength, rs2, rs1, InvertFunct3(func), BRANCH);
+    offset = label->Position() - Position();
+    intx_t lo = offset << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (offset - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (!IsUTypeImm(hi)) {
+      FATAL("Branch distance exceeds 2GB!");
+    }
+    EmitUType(hi, FAR_TMP, AUIPC);
+    EmitIType(lo, FAR_TMP, F3_0, ZR, JALR);
+    intptr_t end = Position();
+    ASSERT_EQUAL(end - start, kFarBranchLength);
+    return;
+  } else {
+    // Forward branch: speculatively use near branches and re-assemble with far
+    // branches if any need greater length.
+    if (distance == kNearJump) {
+      offset = label->link_b(Position());
+      if (!IsBTypeImm(offset)) {
+        FATAL("Incorrect Assembler::kNearJump");
+      }
+      EmitBType(offset, rs2, rs1, func, BRANCH);
+    } else if (far_branch_level() == 0) {
+      offset = label->link_b(Position());
+      if (!IsBTypeImm(offset)) {
+        // TODO(riscv): This isn't so much because the branch is out of range
+        // as some previous jump to the same target would be out of B-type
+        // range... A possible alternative is to have separate lists on Labels
+        // for pending B-type and J-type instructions.
+        BailoutWithBranchOffsetError();
+      }
+      EmitBType(offset, rs2, rs1, func, BRANCH);
+    } else if (far_branch_level() == 1) {
+      intptr_t start = Position();
+      const intptr_t kFarBranchLength = 8;
+      EmitBType(kFarBranchLength, rs2, rs1, InvertFunct3(func), BRANCH);
+      offset = label->link_j(Position());
+      EmitJType(offset, ZR, JAL);
+      intptr_t end = Position();
+      ASSERT_EQUAL(end - start, kFarBranchLength);
+    } else {
+      intptr_t start = Position();
+      const intptr_t kFarBranchLength = 12;
+      EmitBType(kFarBranchLength, rs2, rs1, InvertFunct3(func), BRANCH);
+      offset = label->link_far(Position());
+      intx_t lo = offset << (XLEN - 12) >> (XLEN - 12);
+      intx_t hi = (offset - lo) << (XLEN - 32) >> (XLEN - 32);
+      if (!IsUTypeImm(hi)) {
+        FATAL("Branch distance exceeds 2GB!");
+      }
+      EmitUType(hi, FAR_TMP, AUIPC);
+      EmitIType(lo, FAR_TMP, F3_0, ZR, JALR);
+      intptr_t end = Position();
+      ASSERT_EQUAL(end - start, kFarBranchLength);
+    }
+  }
+}
+
+void MicroAssembler::EmitJump(Register rd,
+                              Label* label,
+                              Opcode op,
+                              JumpDistance distance) {
+  intptr_t offset;
+  if (label->IsBound()) {
+    // Backward jump: use near or far jump based on actual distance.
+    offset = label->Position() - Position();
+
+    if (IsJTypeImm(offset)) {
+      EmitJType(offset, rd, JAL);
+      return;
+    }
+    intx_t lo = offset << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (offset - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (!IsUTypeImm(hi)) {
+      FATAL("Jump distance exceeds 2GB!");
+    }
+    EmitUType(hi, FAR_TMP, AUIPC);
+    EmitIType(lo, FAR_TMP, F3_0, ZR, JALR);
+    return;
+  } else {
+    // Forward jump: speculatively use near jumps and re-assemble with far
+    // jumps if any need greater length.
+    if (distance == kNearJump) {
+      offset = label->link_j(Position());
+      if (!IsJTypeImm(offset)) {
+        FATAL("Incorrect Assembler::kNearJump");
+      }
+      EmitJType(offset, rd, JAL);
+    } else if (far_branch_level() < 2) {
+      offset = label->link_j(Position());
+      if (!IsJTypeImm(offset)) {
+        BailoutWithBranchOffsetError();
+      }
+      EmitJType(offset, rd, JAL);
+    } else {
+      offset = label->link_far(Position());
+      intx_t lo = offset << (XLEN - 12) >> (XLEN - 12);
+      intx_t hi = (offset - lo) << (XLEN - 32) >> (XLEN - 32);
+      if (!IsUTypeImm(hi)) {
+        FATAL("Jump distance exceeds 2GB!");
+      }
+      EmitUType(hi, FAR_TMP, AUIPC);
+      EmitIType(lo, FAR_TMP, F3_0, ZR, JALR);
+    }
+  }
+}
+
+void MicroAssembler::EmitCBranch(Register rs1p, Label* label, COpcode op) {
+  intptr_t offset;
+  if (label->IsBound()) {
+    offset = label->Position() - Position();
+  } else {
+    offset = label->link_cb(Position());
+  }
+  if (!IsCBImm(offset)) {
+    FATAL("Incorrect Assembler::kNearJump");
+  }
+  Emit16(op | EncodeCRs1p(rs1p) | EncodeCBImm(offset));
+}
+
+void MicroAssembler::EmitCJump(Label* label, COpcode op) {
+  intptr_t offset;
+  if (label->IsBound()) {
+    offset = label->Position() - Position();
+  } else {
+    offset = label->link_cj(Position());
+  }
+  if (!IsCJImm(offset)) {
+    FATAL("Incorrect Assembler::kNearJump");
+  }
+  Emit16(op | EncodeCJImm(offset));
+}
+
+void MicroAssembler::EmitRType(Funct5 funct5,
+                               std::memory_order order,
+                               Register rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               Register rd,
+                               Opcode opcode) {
+  intptr_t funct7 = funct5 << 2;
+  switch (order) {
+    case std::memory_order_acq_rel:
+      funct7 |= 0b11;
+      break;
+    case std::memory_order_acquire:
+      funct7 |= 0b10;
+      break;
+    case std::memory_order_release:
+      funct7 |= 0b01;
+      break;
+    case std::memory_order_relaxed:
+      funct7 |= 0b00;
+      break;
+    default:
+      FATAL("Invalid memory order");
+  }
+  EmitRType((Funct7)funct7, rs2, rs1, funct3, rd, opcode);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               Register rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               Register rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               FRegister rs1,
+                               Funct3 funct3,
+                               FRegister rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeFRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               FRegister rs1,
+                               RoundingMode round,
+                               FRegister rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeFRs1(rs1);
+  e |= EncodeRoundingMode(round);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               Register rs1,
+                               RoundingMode round,
+                               FRegister rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeRoundingMode(round);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               FRegister rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               FRegister rs1,
+                               Funct3 funct3,
+                               Register rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeFRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               FRegister rs2,
+                               FRegister rs1,
+                               RoundingMode round,
+                               Register rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeFRs1(rs1);
+  e |= EncodeRoundingMode(round);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitRType(Funct7 funct7,
+                               intptr_t shamt,
+                               Register rs1,
+                               Funct3 funct3,
+                               Register rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFunct7(funct7);
+  e |= EncodeShamt(shamt);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitR4Type(FRegister rs3,
+                                Funct2 funct2,
+                                FRegister rs2,
+                                FRegister rs1,
+                                RoundingMode round,
+                                FRegister rd,
+                                Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeFRs3(rs3);
+  e |= EncodeFunct2(funct2);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeFRs1(rs1);
+  e |= EncodeRoundingMode(round);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitIType(intptr_t imm,
+                               Register rs1,
+                               Funct3 funct3,
+                               Register rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeITypeImm(imm);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitIType(intptr_t imm,
+                               Register rs1,
+                               Funct3 funct3,
+                               FRegister rd,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeITypeImm(imm);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeFRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitSType(intptr_t imm,
+                               Register rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeSTypeImm(imm);
+  e |= EncodeRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitSType(intptr_t imm,
+                               FRegister rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeSTypeImm(imm);
+  e |= EncodeFRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitBType(intptr_t imm,
+                               Register rs2,
+                               Register rs1,
+                               Funct3 funct3,
+                               Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeBTypeImm(imm);
+  e |= EncodeRs2(rs2);
+  e |= EncodeRs1(rs1);
+  e |= EncodeFunct3(funct3);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitUType(intptr_t imm, Register rd, Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeUTypeImm(imm);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+void MicroAssembler::EmitJType(intptr_t imm, Register rd, Opcode opcode) {
+  uint32_t e = 0;
+  e |= EncodeJTypeImm(imm);
+  e |= EncodeRd(rd);
+  e |= EncodeOpcode(opcode);
+  Emit32(e);
+}
+
+Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
+                     intptr_t far_branch_level)
+    : MicroAssembler(object_pool_builder,
+                     far_branch_level,
+                     FLAG_use_compressed_instructions ? RV_GC : RV_G),
+      constant_pool_allowed_(false) {
+  generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
+    // Note this does not destory RA.
+    lx(TMP,
+       Address(THR, target::Thread::write_barrier_wrappers_thread_offset(reg)));
+    jalr(TMP, TMP);
+  };
+  generate_invoke_array_write_barrier_ = [&]() {
+    Call(
+        Address(THR, target::Thread::array_write_barrier_entry_point_offset()));
+  };
+}
+
+void Assembler::PushRegister(Register r) {
+  ASSERT(r != SP);
+  subi(SP, SP, target::kWordSize);
+  sx(r, Address(SP, 0));
+}
+void Assembler::PopRegister(Register r) {
+  ASSERT(r != SP);
+  lx(r, Address(SP, 0));
+  addi(SP, SP, target::kWordSize);
+}
+
+void Assembler::PushRegisterPair(Register r0, Register r1) {
+  ASSERT(r0 != SP);
+  ASSERT(r1 != SP);
+  subi(SP, SP, 2 * target::kWordSize);
+  sx(r1, Address(SP, target::kWordSize));
+  sx(r0, Address(SP, 0));
+}
+
+void Assembler::PopRegisterPair(Register r0, Register r1) {
+  ASSERT(r0 != SP);
+  ASSERT(r1 != SP);
+  lx(r1, Address(SP, target::kWordSize));
+  lx(r0, Address(SP, 0));
+  addi(SP, SP, 2 * target::kWordSize);
+}
+
+void Assembler::PushRegisters(const RegisterSet& regs) {
+  // The order in which the registers are pushed must match the order
+  // in which the registers are encoded in the safepoint's stack map.
+
+  intptr_t size = (regs.CpuRegisterCount() * target::kWordSize) +
+                  (regs.FpuRegisterCount() * kFpuRegisterSize);
+  if (size == 0) {
+    return;  // Skip no-op SP update.
+  }
+
+  subi(SP, SP, size);
+  intptr_t offset = size;
+  for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; i--) {
+    FRegister reg = static_cast<FRegister>(i);
+    if (regs.ContainsFpuRegister(reg)) {
+      offset -= kFpuRegisterSize;
+      fsd(reg, Address(SP, offset));
+    }
+  }
+  for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
+    Register reg = static_cast<Register>(i);
+    if (regs.ContainsRegister(reg)) {
+      offset -= target::kWordSize;
+      sx(reg, Address(SP, offset));
+    }
+  }
+  ASSERT(offset == 0);
+}
+void Assembler::PopRegisters(const RegisterSet& regs) {
+  // The order in which the registers are pushed must match the order
+  // in which the registers are encoded in the safepoint's stack map.
+
+  intptr_t size = (regs.CpuRegisterCount() * target::kWordSize) +
+                  (regs.FpuRegisterCount() * kFpuRegisterSize);
+  if (size == 0) {
+    return;  // Skip no-op SP update.
+  }
+  intptr_t offset = 0;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    Register reg = static_cast<Register>(i);
+    if (regs.ContainsRegister(reg)) {
+      lx(reg, Address(SP, offset));
+      offset += target::kWordSize;
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    FRegister reg = static_cast<FRegister>(i);
+    if (regs.ContainsFpuRegister(reg)) {
+      fld(reg, Address(SP, offset));
+      offset += kFpuRegisterSize;
+    }
+  }
+  ASSERT(offset == size);
+  addi(SP, SP, size);
+}
+
+void Assembler::PushNativeCalleeSavedRegisters() {
+  RegisterSet regs(kAbiPreservedCpuRegs, kAbiPreservedFpuRegs);
+  intptr_t size = (regs.CpuRegisterCount() * target::kWordSize) +
+                  (regs.FpuRegisterCount() * sizeof(double));
+  subi(SP, SP, size);
+  intptr_t offset = 0;
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    FRegister reg = static_cast<FRegister>(i);
+    if (regs.ContainsFpuRegister(reg)) {
+      fsd(reg, Address(SP, offset));
+      offset += sizeof(double);
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    Register reg = static_cast<Register>(i);
+    if (regs.ContainsRegister(reg)) {
+      sx(reg, Address(SP, offset));
+      offset += target::kWordSize;
+    }
+  }
+  ASSERT(offset == size);
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+  RegisterSet regs(kAbiPreservedCpuRegs, kAbiPreservedFpuRegs);
+  intptr_t size = (regs.CpuRegisterCount() * target::kWordSize) +
+                  (regs.FpuRegisterCount() * sizeof(double));
+  intptr_t offset = 0;
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    FRegister reg = static_cast<FRegister>(i);
+    if (regs.ContainsFpuRegister(reg)) {
+      fld(reg, Address(SP, offset));
+      offset += sizeof(double);
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    Register reg = static_cast<Register>(i);
+    if (regs.ContainsRegister(reg)) {
+      lx(reg, Address(SP, offset));
+      offset += target::kWordSize;
+    }
+  }
+  ASSERT(offset == size);
+  addi(SP, SP, size);
+}
+
+void Assembler::ExtendValue(Register rd, Register rn, OperandSize sz) {
+  switch (sz) {
+#if XLEN == 64
+    case kEightBytes:
+      if (rd == rn) return;  // No operation needed.
+      return mv(rd, rn);
+    case kUnsignedFourBytes:
+      return UNIMPLEMENTED();
+    case kFourBytes:
+      return sextw(rd, rn);
+#elif XLEN == 32
+    case kUnsignedFourBytes:
+    case kFourBytes:
+      if (rd == rn) return;  // No operation needed.
+      return mv(rd, rn);
+#endif
+    case kUnsignedTwoBytes:
+    case kTwoBytes:
+    case kUnsignedByte:
+    case kByte:
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  UNIMPLEMENTED();
+}
+void Assembler::ExtendAndSmiTagValue(Register rd, Register rn, OperandSize sz) {
+  if (sz == kWordBytes) {
+    SmiTag(rd, rn);
+    return;
+  }
+
+  switch (sz) {
+#if XLEN == 64
+    case kUnsignedFourBytes:
+      slli(rd, rn, XLEN - kBitsPerInt32);
+      srli(rd, rd, XLEN - kBitsPerInt32 - kSmiTagShift);
+      return;
+    case kFourBytes:
+      slli(rd, rn, XLEN - kBitsPerInt32);
+      srai(rd, rd, XLEN - kBitsPerInt32 - kSmiTagShift);
+      return;
+#endif
+    case kUnsignedTwoBytes:
+      slli(rd, rn, XLEN - kBitsPerInt16);
+      srli(rd, rd, XLEN - kBitsPerInt16 - kSmiTagShift);
+      return;
+    case kTwoBytes:
+      slli(rd, rn, XLEN - kBitsPerInt16);
+      srai(rd, rd, XLEN - kBitsPerInt16 - kSmiTagShift);
+      return;
+    case kUnsignedByte:
+      slli(rd, rn, XLEN - kBitsPerInt8);
+      srli(rd, rd, XLEN - kBitsPerInt8 - kSmiTagShift);
+      return;
+    case kByte:
+      slli(rd, rn, XLEN - kBitsPerInt8);
+      srai(rd, rd, XLEN - kBitsPerInt8 - kSmiTagShift);
+      return;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+}
+
+// Unconditional jump to a given address in memory. Clobbers TMP.
+void Assembler::Jump(const Address& address) {
+  lx(TMP2, address);
+  jr(TMP2);
+}
+
+void Assembler::LoadField(Register dst, const FieldAddress& address) {
+  lx(dst, address);
+}
+
+#if defined(USING_THREAD_SANITIZER)
+void Assembler::TsanLoadAcquire(Register addr) {
+  UNIMPLEMENTED();
+}
+void Assembler::TsanStoreRelease(Register addr) {
+  UNIMPLEMENTED();
+}
+#endif
+
+void Assembler::LoadAcquire(Register dst, Register address, int32_t offset) {
+  ASSERT(dst != address);
+  LoadFromOffset(dst, address, offset);
+  fence(HartEffects::kRead, HartEffects::kMemory);
+
+#if defined(USING_THREAD_SANITIZER)
+  if (offset == 0) {
+    TsanLoadAcquire(address);
+  } else {
+    AddImmediate(TMP2, address, offset);
+    TsanLoadAcquire(TMP2);
+  }
+#endif
+}
+
+void Assembler::LoadAcquireCompressed(Register dst,
+                                      Register address,
+                                      int32_t offset) {
+  LoadAcquire(dst, address, offset);
+}
+
+void Assembler::StoreRelease(Register src, Register address, int32_t offset) {
+  fence(HartEffects::kMemory, HartEffects::kRead);
+  StoreToOffset(src, address, offset);
+}
+
+void Assembler::StoreReleaseCompressed(Register src,
+                                       Register address,
+                                       int32_t offset) {
+  UNIMPLEMENTED();
+}
+
+void Assembler::CompareWithCompressedFieldFromOffset(Register value,
+                                                     Register base,
+                                                     int32_t offset) {
+  UNIMPLEMENTED();
+}
+
+void Assembler::CompareWithMemoryValue(Register value,
+                                       Address address,
+                                       OperandSize sz) {
+  UNIMPLEMENTED();
+}
+
+void Assembler::CompareFunctionTypeNullabilityWith(Register type,
+                                                   int8_t value) {
+  EnsureHasClassIdInDEBUG(kFunctionTypeCid, type, TMP);
+  lbu(TMP,
+      FieldAddress(type, compiler::target::FunctionType::nullability_offset()));
+  CompareImmediate(TMP, value);
+}
+void Assembler::CompareTypeNullabilityWith(Register type, int8_t value) {
+  EnsureHasClassIdInDEBUG(kTypeCid, type, TMP);
+  lbu(TMP, FieldAddress(type, compiler::target::Type::nullability_offset()));
+  CompareImmediate(TMP, value);
+}
+
+void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
+  if (frame_space != 0) {
+    addi(SP, SP, -frame_space);
+  }
+  const intptr_t kAbiStackAlignment = 16;  // For both 32 and 64 bit.
+  andi(SP, SP, ~(kAbiStackAlignment - 1));
+}
+
+// In debug mode, this generates code to check that:
+//   FP + kExitLinkSlotFromEntryFp == SP
+// or triggers breakpoint otherwise.
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+  Label done;
+  ASSERT(!constant_pool_allowed());
+  LoadImmediate(TMP, target::frame_layout.exit_link_slot_from_entry_fp *
+                         target::kWordSize);
+  add(TMP, TMP, FPREG);
+  beq(TMP, SPREG, &done, kNearJump);
+
+  Breakpoint();
+
+  Bind(&done);
+#endif
+}
+
+void Assembler::CompareRegisters(Register rn, Register rm) {
+  ASSERT(deferred_compare_ == kNone);
+  deferred_compare_ = kCompareReg;
+  deferred_left_ = rn;
+  deferred_reg_ = rm;
+}
+void Assembler::CompareObjectRegisters(Register rn, Register rm) {
+  CompareRegisters(rn, rm);
+}
+void Assembler::TestRegisters(Register rn, Register rm) {
+  ASSERT(deferred_compare_ == kNone);
+  deferred_compare_ = kTestReg;
+  deferred_left_ = rn;
+  deferred_reg_ = rm;
+}
+
+void Assembler::BranchIf(Condition condition,
+                         Label* label,
+                         JumpDistance distance) {
+  ASSERT(deferred_compare_ != kNone);
+
+  if (deferred_compare_ == kCompareImm || deferred_compare_ == kCompareReg) {
+    Register left = deferred_left_;
+    Register right;
+    if (deferred_compare_ == kCompareImm) {
+      if (deferred_imm_ == 0) {
+        right = ZR;
+      } else {
+        LoadImmediate(TMP2, deferred_imm_);
+        right = TMP2;
+      }
+    } else {
+      right = deferred_reg_;
+    }
+    switch (condition) {
+      case EQUAL:
+        beq(left, right, label, distance);
+        break;
+      case NOT_EQUAL:
+        bne(left, right, label, distance);
+        break;
+      case LESS:
+        blt(left, right, label, distance);
+        break;
+      case LESS_EQUAL:
+        ble(left, right, label, distance);
+        break;
+      case GREATER_EQUAL:
+        bge(left, right, label, distance);
+        break;
+      case GREATER:
+        bgt(left, right, label, distance);
+        break;
+      case UNSIGNED_LESS:
+        bltu(left, right, label, distance);
+        break;
+      case UNSIGNED_LESS_EQUAL:
+        bleu(left, right, label, distance);
+        break;
+      case UNSIGNED_GREATER_EQUAL:
+        bgeu(left, right, label, distance);
+        break;
+      case UNSIGNED_GREATER:
+        bgtu(left, right, label, distance);
+        break;
+      case OVERFLOW:
+      case NO_OVERFLOW:
+        FATAL("Use Add/Subtract/MultiplyBranchOverflow instead.");
+      default:
+        UNREACHABLE();
+    }
+  } else if (deferred_compare_ == kTestImm || deferred_compare_ == kTestReg) {
+    if (deferred_compare_ == kTestImm) {
+      AndImmediate(TMP2, deferred_left_, deferred_imm_);
+    } else {
+      and_(TMP2, deferred_left_, deferred_reg_);
+    }
+    switch (condition) {
+      case ZERO:
+        beqz(TMP2, label, distance);
+        break;
+      case NOT_ZERO:
+        bnez(TMP2, label, distance);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    UNREACHABLE();
+  }
+  deferred_compare_ = kNone;  // Consumed.
+}
+
+void Assembler::SetIf(Condition condition, Register rd) {
+  ASSERT(deferred_compare_ != kNone);
+
+  if (deferred_compare_ == kCompareImm) {
+    if (deferred_imm_ == 0) {
+      deferred_compare_ = kCompareReg;
+      deferred_reg_ = ZR;
+      SetIf(condition, rd);
+      return;
+    }
+    if (!IsITypeImm(deferred_imm_) || !IsITypeImm(deferred_imm_ + 1)) {
+      LoadImmediate(TMP2, deferred_imm_);
+      deferred_compare_ = kCompareReg;
+      deferred_reg_ = TMP2;
+      SetIf(condition, rd);
+      return;
+    }
+    Register left = deferred_left_;
+    intx_t right = deferred_imm_;
+    switch (condition) {
+      case EQUAL:
+        xori(rd, left, right);
+        seqz(rd, rd);
+        break;
+      case NOT_EQUAL:
+        xori(rd, left, right);
+        snez(rd, rd);
+        break;
+      case LESS:
+        slti(rd, left, right);
+        break;
+      case LESS_EQUAL:
+        slti(rd, left, right + 1);
+        break;
+      case GREATER_EQUAL:
+        slti(rd, left, right);
+        xori(rd, rd, 1);
+        break;
+      case GREATER:
+        slti(rd, left, right + 1);
+        xori(rd, rd, 1);
+        break;
+      case UNSIGNED_LESS:
+        sltiu(rd, left, right);
+        break;
+      case UNSIGNED_LESS_EQUAL:
+        sltiu(rd, left, right + 1);
+        break;
+      case UNSIGNED_GREATER_EQUAL:
+        sltiu(rd, left, right);
+        xori(rd, rd, 1);
+        break;
+      case UNSIGNED_GREATER:
+        sltiu(rd, left, right + 1);
+        xori(rd, rd, 1);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else if (deferred_compare_ == kCompareReg) {
+    Register left = deferred_left_;
+    Register right = deferred_reg_;
+    switch (condition) {
+      case EQUAL:
+        if (right == ZR) {
+          seqz(rd, left);
+        } else {
+          xor_(rd, left, right);
+          seqz(rd, rd);
+        }
+        break;
+      case NOT_EQUAL:
+        if (right == ZR) {
+          snez(rd, left);
+        } else {
+          xor_(rd, left, right);
+          snez(rd, rd);
+        }
+        break;
+      case LESS:
+        slt(rd, left, right);
+        break;
+      case LESS_EQUAL:
+        slt(rd, right, left);
+        xori(rd, rd, 1);
+        break;
+      case GREATER_EQUAL:
+        slt(rd, left, right);
+        xori(rd, rd, 1);
+        break;
+      case GREATER:
+        slt(rd, right, left);
+        break;
+      case UNSIGNED_LESS:
+        sltu(rd, left, right);
+        break;
+      case UNSIGNED_LESS_EQUAL:
+        sltu(rd, right, left);
+        xori(rd, rd, 1);
+        break;
+      case UNSIGNED_GREATER_EQUAL:
+        sltu(rd, left, right);
+        xori(rd, rd, 1);
+        break;
+      case UNSIGNED_GREATER:
+        sltu(rd, right, left);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else if (deferred_compare_ == kTestImm || deferred_compare_ == kTestReg) {
+    if (deferred_compare_ == kTestImm) {
+      AndImmediate(TMP2, deferred_left_, deferred_imm_);
+    } else {
+      and_(TMP2, deferred_left_, deferred_reg_);
+    }
+    switch (condition) {
+      case ZERO:
+        seqz(rd, TMP2);
+        break;
+      case NOT_ZERO:
+        snez(rd, TMP2);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    UNREACHABLE();
+  }
+
+  deferred_compare_ = kNone;  // Consumed.
+}
+
+void Assembler::BranchIfZero(Register rn, Label* label, JumpDistance distance) {
+  beqz(rn, label, distance);
+}
+
+void Assembler::BranchIfNotSmi(Register reg,
+                               Label* label,
+                               JumpDistance distance) {
+  ASSERT(reg != TMP2);
+  andi(TMP2, reg, kSmiTagMask);
+  bnez(TMP2, label, distance);
+}
+void Assembler::BranchIfSmi(Register reg, Label* label, JumpDistance distance) {
+  ASSERT(reg != TMP2);
+  andi(TMP2, reg, kSmiTagMask);
+  beqz(TMP2, label, distance);
+}
+
+void Assembler::Jump(const Code& target,
+                     Register pp,
+                     ObjectPoolBuilderEntry::Patchability patchable) {
+  const intptr_t index =
+      object_pool_builder().FindObject(ToObject(target), patchable);
+  LoadWordFromPoolIndex(CODE_REG, index, pp);
+  Jump(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+}
+
+void Assembler::JumpAndLink(const Code& target,
+                            ObjectPoolBuilderEntry::Patchability patchable,
+                            CodeEntryKind entry_kind) {
+  const intptr_t index =
+      object_pool_builder().FindObject(ToObject(target), patchable);
+  LoadWordFromPoolIndex(CODE_REG, index);
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
+}
+
+void Assembler::JumpAndLinkToRuntime() {
+  Call(Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
+}
+
+void Assembler::JumpAndLinkWithEquivalence(const Code& target,
+                                           const Object& equivalence,
+                                           CodeEntryKind entry_kind) {
+  const intptr_t index =
+      object_pool_builder().FindObject(ToObject(target), equivalence);
+  LoadWordFromPoolIndex(CODE_REG, index);
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
+}
+
+void Assembler::Call(Address target) {
+  lx(RA, target);
+  jalr(RA);
+}
+
+void Assembler::AddImmediate(Register rd,
+                             Register rs1,
+                             intx_t imm,
+                             OperandSize sz) {
+  if (IsITypeImm(imm)) {
+    addi(rd, rs1, imm);
+  } else {
+    ASSERT(rs1 != TMP2);
+    LoadImmediate(TMP2, imm);
+    add(rd, rs1, TMP2);
+  }
+}
+void Assembler::AndImmediate(Register rd,
+                             Register rs1,
+                             intx_t imm,
+                             OperandSize sz) {
+  if (IsITypeImm(imm)) {
+    andi(rd, rs1, imm);
+  } else {
+    ASSERT(rs1 != TMP2);
+    LoadImmediate(TMP2, imm);
+    and_(rd, rs1, TMP2);
+  }
+}
+void Assembler::OrImmediate(Register rd,
+                            Register rs1,
+                            intx_t imm,
+                            OperandSize sz) {
+  if (IsITypeImm(imm)) {
+    ori(rd, rs1, imm);
+  } else {
+    ASSERT(rs1 != TMP2);
+    LoadImmediate(TMP2, imm);
+    or_(rd, rs1, TMP2);
+  }
+}
+void Assembler::XorImmediate(Register rd,
+                             Register rs1,
+                             intx_t imm,
+                             OperandSize sz) {
+  if (IsITypeImm(imm)) {
+    xori(rd, rs1, imm);
+  } else {
+    ASSERT(rs1 != TMP2);
+    LoadImmediate(TMP2, imm);
+    xor_(rd, rs1, TMP2);
+  }
+}
+
+void Assembler::TestImmediate(Register rn, intx_t imm, OperandSize sz) {
+  ASSERT(deferred_compare_ == kNone);
+  deferred_compare_ = kTestImm;
+  deferred_left_ = rn;
+  deferred_imm_ = imm;
+}
+void Assembler::CompareImmediate(Register rn, intx_t imm, OperandSize sz) {
+  ASSERT(deferred_compare_ == kNone);
+  deferred_compare_ = kCompareImm;
+  deferred_left_ = rn;
+  deferred_imm_ = imm;
+}
+
+void Assembler::LoadFromOffset(Register dest,
+                               const Address& address,
+                               OperandSize sz) {
+  LoadFromOffset(dest, address.base(), address.offset(), sz);
+}
+void Assembler::LoadFromOffset(Register dest,
+                               Register base,
+                               int32_t offset,
+                               OperandSize sz) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  switch (sz) {
+#if XLEN == 64
+    case kEightBytes:
+      return ld(dest, Address(base, offset));
+    case kUnsignedFourBytes:
+      return lwu(dest, Address(base, offset));
+#elif XLEN == 32
+    case kUnsignedFourBytes:
+      return lw(dest, Address(base, offset));
+#endif
+    case kFourBytes:
+      return lw(dest, Address(base, offset));
+    case kUnsignedTwoBytes:
+      return lhu(dest, Address(base, offset));
+    case kTwoBytes:
+      return lh(dest, Address(base, offset));
+    case kUnsignedByte:
+      return lbu(dest, Address(base, offset));
+    case kByte:
+      return lb(dest, Address(base, offset));
+    default:
+      UNREACHABLE();
+  }
+}
+// For loading indexed payloads out of tagged objects like Arrays. If the
+// payload objects are word-sized, use TIMES_HALF_WORD_SIZE if the contents of
+// [index] is a Smi, otherwise TIMES_WORD_SIZE if unboxed.
+void Assembler::LoadIndexedPayload(Register dest,
+                                   Register base,
+                                   int32_t payload_offset,
+                                   Register index,
+                                   ScaleFactor scale,
+                                   OperandSize sz) {
+  slli(TMP, index, scale);
+  add(TMP, TMP, base);
+  LoadFromOffset(dest, TMP, payload_offset - kHeapObjectTag, sz);
+}
+void Assembler::LoadIndexedCompressed(Register dest,
+                                      Register base,
+                                      int32_t offset,
+                                      Register index) {
+  LoadIndexedPayload(dest, base, offset, index, TIMES_WORD_SIZE, kObjectBytes);
+}
+
+void Assembler::LoadSFromOffset(FRegister dest, Register base, int32_t offset) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  flw(dest, Address(base, offset));
+}
+
+void Assembler::LoadDFromOffset(FRegister dest, Register base, int32_t offset) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  fld(dest, Address(base, offset));
+}
+
+void Assembler::LoadFromStack(Register dst, intptr_t depth) {
+  UNIMPLEMENTED();
+}
+void Assembler::StoreToStack(Register src, intptr_t depth) {
+  UNIMPLEMENTED();
+}
+void Assembler::CompareToStack(Register src, intptr_t depth) {
+  UNIMPLEMENTED();
+}
+
+void Assembler::StoreToOffset(Register src,
+                              const Address& address,
+                              OperandSize sz) {
+  StoreToOffset(src, address.base(), address.offset(), sz);
+}
+void Assembler::StoreToOffset(Register src,
+                              Register base,
+                              int32_t offset,
+                              OperandSize sz) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  switch (sz) {
+#if XLEN == 64
+    case kEightBytes:
+      return sd(src, Address(base, offset));
+#endif
+    case kUnsignedFourBytes:
+    case kFourBytes:
+      return sw(src, Address(base, offset));
+    case kUnsignedTwoBytes:
+    case kTwoBytes:
+      return sh(src, Address(base, offset));
+    case kUnsignedByte:
+    case kByte:
+      return sb(src, Address(base, offset));
+    default:
+      UNREACHABLE();
+  }
+}
+
+void Assembler::StoreSToOffset(FRegister src, Register base, int32_t offset) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  fsw(src, Address(base, offset));
+}
+
+void Assembler::StoreDToOffset(FRegister src, Register base, int32_t offset) {
+  ASSERT(base != TMP2);
+  if (!IsITypeImm(offset)) {
+    intx_t imm = offset;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    if (hi == 0) {
+      UNREACHABLE();
+    } else {
+      lui(TMP2, hi);
+      add(TMP2, TMP2, base);
+      base = TMP2;
+      offset = lo;
+    }
+  }
+  fsd(src, Address(base, offset));
+}
+
+void Assembler::LoadUnboxedDouble(FpuRegister dst,
+                                  Register base,
+                                  int32_t offset) {
+  fld(dst, Address(base, offset));
+}
+void Assembler::StoreUnboxedDouble(FpuRegister src,
+                                   Register base,
+                                   int32_t offset) {
+  fsd(src, Address(base, offset));
+}
+void Assembler::MoveUnboxedDouble(FpuRegister dst, FpuRegister src) {
+  fmvd(dst, src);
+}
+
+void Assembler::LoadCompressed(Register dest, const Address& slot) {
+  lx(dest, slot);
+}
+void Assembler::LoadCompressedFromOffset(Register dest,
+                                         Register base,
+                                         int32_t offset) {
+  lx(dest, Address(base, offset));
+}
+void Assembler::LoadCompressedSmi(Register dest, const Address& slot) {
+  lx(dest, slot);
+}
+void Assembler::LoadCompressedSmiFromOffset(Register dest,
+                                            Register base,
+                                            int32_t offset) {
+  lx(dest, Address(base, offset));
+}
+
+// Store into a heap object and apply the generational and incremental write
+// barriers. All stores into heap objects must pass through this function or,
+// if the value can be proven either Smi or old-and-premarked, its NoBarrier
+// variants.
+// Preserves object and value registers.
+void Assembler::StoreIntoObject(Register object,
+                                const Address& dest,
+                                Register value,
+                                CanBeSmi can_value_be_smi,
+                                MemoryOrder memory_order) {
+  // stlr does not feature an address operand.
+  ASSERT(memory_order == kRelaxedNonAtomic);
+  sx(value, dest);
+  StoreBarrier(object, value, can_value_be_smi);
+}
+void Assembler::StoreCompressedIntoObject(Register object,
+                                          const Address& dest,
+                                          Register value,
+                                          CanBeSmi can_value_be_smi,
+                                          MemoryOrder memory_order) {
+  StoreIntoObject(object, dest, value, can_value_be_smi, memory_order);
+}
+void Assembler::StoreBarrier(Register object,
+                             Register value,
+                             CanBeSmi can_value_be_smi) {
+  // x.slot = x. Barrier should have be removed at the IL level.
+  ASSERT(object != value);
+  ASSERT(object != RA);
+  ASSERT(value != RA);
+  ASSERT(object != TMP);
+  ASSERT(object != TMP2);
+  ASSERT(value != TMP);
+  ASSERT(value != TMP2);
+
+  // In parallel, test whether
+  //  - object is old and not remembered and value is new, or
+  //  - object is old and value is old and not marked and concurrent marking is
+  //    in progress
+  // If so, call the WriteBarrier stub, which will either add object to the
+  // store buffer (case 1) or add value to the marking stack (case 2).
+  // Compare UntaggedObject::StorePointer.
+  Label done;
+  if (can_value_be_smi == kValueCanBeSmi) {
+    BranchIfSmi(value, &done, kNearJump);
+  }
+  lbu(TMP, FieldAddress(object, target::Object::tags_offset()));
+  lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
+  srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
+  and_(TMP, TMP, TMP2);
+  and_(TMP, TMP, WRITE_BARRIER_MASK);
+  beqz(TMP, &done, kNearJump);
+
+  Register objectForCall = object;
+  if (value != kWriteBarrierValueReg) {
+    // Unlikely. Only non-graph intrinsics.
+    // TODO(rmacnak): Shuffle registers in intrinsics.
+    if (object != kWriteBarrierValueReg) {
+      PushRegister(kWriteBarrierValueReg);
+    } else {
+      COMPILE_ASSERT(S2 != kWriteBarrierValueReg);
+      COMPILE_ASSERT(S3 != kWriteBarrierValueReg);
+      objectForCall = (value == S2) ? S3 : S2;
+      PushRegisterPair(kWriteBarrierValueReg, objectForCall);
+      mv(objectForCall, object);
+    }
+    mv(kWriteBarrierValueReg, value);
+  }
+
+  // Note this uses TMP as the link register, so RA remains preserved.
+  generate_invoke_write_barrier_wrapper_(objectForCall);
+
+  if (value != kWriteBarrierValueReg) {
+    if (object != kWriteBarrierValueReg) {
+      PopRegister(kWriteBarrierValueReg);
+    } else {
+      PopRegisterPair(kWriteBarrierValueReg, objectForCall);
+    }
+  }
+  Bind(&done);
+}
+void Assembler::StoreIntoArray(Register object,
+                               Register slot,
+                               Register value,
+                               CanBeSmi can_value_be_smi) {
+  sx(value, Address(slot, 0));
+  StoreIntoArrayBarrier(object, slot, value, can_value_be_smi);
+}
+void Assembler::StoreCompressedIntoArray(Register object,
+                                         Register slot,
+                                         Register value,
+                                         CanBeSmi can_value_be_smi) {
+  StoreIntoArray(object, slot, value, can_value_be_smi);
+}
+void Assembler::StoreIntoArrayBarrier(Register object,
+                                      Register slot,
+                                      Register value,
+                                      CanBeSmi can_value_be_smi) {
+  // TODO(riscv): Use RA2 to avoid spilling RA inline?
+  const bool spill_lr = true;
+  ASSERT(object != TMP);
+  ASSERT(object != TMP2);
+  ASSERT(value != TMP);
+  ASSERT(value != TMP2);
+  ASSERT(slot != TMP);
+  ASSERT(slot != TMP2);
+
+  // In parallel, test whether
+  //  - object is old and not remembered and value is new, or
+  //  - object is old and value is old and not marked and concurrent marking is
+  //    in progress
+  // If so, call the WriteBarrier stub, which will either add object to the
+  // store buffer (case 1) or add value to the marking stack (case 2).
+  // Compare UntaggedObject::StorePointer.
+  Label done;
+  if (can_value_be_smi == kValueCanBeSmi) {
+    BranchIfSmi(value, &done, kNearJump);
+  }
+  lbu(TMP, FieldAddress(object, target::Object::tags_offset()));
+  lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
+  srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
+  and_(TMP, TMP, TMP2);
+  and_(TMP, TMP, WRITE_BARRIER_MASK);
+  beqz(TMP, &done, kNearJump);
+  if (spill_lr) {
+    PushRegister(RA);
+  }
+  if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
+      (slot != kWriteBarrierSlotReg)) {
+    // Spill and shuffle unimplemented. Currently StoreIntoArray is only used
+    // from StoreIndexInstr, which gets these exact registers from the register
+    // allocator.
+    UNIMPLEMENTED();
+  }
+  generate_invoke_array_write_barrier_();
+  if (spill_lr) {
+    PopRegister(RA);
+  }
+  Bind(&done);
+}
+
+void Assembler::StoreIntoObjectOffset(Register object,
+                                      int32_t offset,
+                                      Register value,
+                                      CanBeSmi can_value_be_smi,
+                                      MemoryOrder memory_order) {
+  if (memory_order == kRelease) {
+    StoreRelease(value, object, offset - kHeapObjectTag);
+  } else {
+    StoreToOffset(value, object, offset - kHeapObjectTag);
+  }
+  StoreBarrier(object, value, can_value_be_smi);
+}
+void Assembler::StoreCompressedIntoObjectOffset(Register object,
+                                                int32_t offset,
+                                                Register value,
+                                                CanBeSmi can_value_be_smi,
+                                                MemoryOrder memory_order) {
+  StoreIntoObjectOffset(object, offset, value, can_value_be_smi, memory_order);
+}
+void Assembler::StoreIntoObjectNoBarrier(Register object,
+                                         const Address& dest,
+                                         Register value,
+                                         MemoryOrder memory_order) {
+  ASSERT(memory_order == kRelaxedNonAtomic);
+  sx(value, dest);
+#if defined(DEBUG)
+  Label done;
+  beq(object, value, &done, kNearJump);
+  BranchIfSmi(value, &done, kNearJump);
+  lbu(TMP, FieldAddress(object, target::Object::tags_offset()));
+  lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
+  srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
+  and_(TMP, TMP, TMP2);
+  and_(TMP, TMP, WRITE_BARRIER_MASK);
+  beqz(TMP, &done, kNearJump);
+  Stop("Store buffer update is required");
+  Bind(&done);
+#endif
+}
+void Assembler::StoreCompressedIntoObjectNoBarrier(Register object,
+                                                   const Address& dest,
+                                                   Register value,
+                                                   MemoryOrder memory_order) {
+  StoreIntoObjectNoBarrier(object, dest, value, memory_order);
+}
+void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
+                                               int32_t offset,
+                                               Register value,
+                                               MemoryOrder memory_order) {
+  if (memory_order == kRelease) {
+    StoreRelease(value, object, offset);
+  } else {
+    StoreToOffset(value, object, offset - kHeapObjectTag);
+  }
+#if defined(DEBUG)
+  Label done;
+  beq(object, value, &done, kNearJump);
+  BranchIfSmi(value, &done, kNearJump);
+  lbu(TMP, FieldAddress(object, target::Object::tags_offset()));
+  lbu(TMP2, FieldAddress(value, target::Object::tags_offset()));
+  srli(TMP, TMP, target::UntaggedObject::kBarrierOverlapShift);
+  and_(TMP, TMP, TMP2);
+  and_(TMP, TMP, WRITE_BARRIER_MASK);
+  beqz(TMP, &done, kNearJump);
+  Stop("Store buffer update is required");
+  Bind(&done);
+#endif
+}
+void Assembler::StoreCompressedIntoObjectOffsetNoBarrier(
+    Register object,
+    int32_t offset,
+    Register value,
+    MemoryOrder memory_order) {
+  StoreIntoObjectOffsetNoBarrier(object, offset, value, memory_order);
+}
+void Assembler::StoreIntoObjectNoBarrier(Register object,
+                                         const Address& dest,
+                                         const Object& value) {
+  ASSERT(IsOriginalObject(value));
+  ASSERT(IsNotTemporaryScopedHandle(value));
+  // No store buffer update.
+  if (IsSameObject(compiler::NullObject(), value)) {
+    sx(NULL_REG, dest);
+  } else if (target::IsSmi(object) && (target::ToRawSmi(object) == 0)) {
+    sx(ZR, dest);
+  } else {
+    LoadObject(TMP2, value);
+    sx(TMP2, dest);
+  }
+}
+void Assembler::StoreCompressedIntoObjectNoBarrier(Register object,
+                                                   const Address& dest,
+                                                   const Object& value,
+                                                   MemoryOrder memory_order) {
+  UNIMPLEMENTED();
+}
+void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
+                                               int32_t offset,
+                                               const Object& value,
+                                               MemoryOrder memory_order) {
+  if (memory_order == kRelease) {
+    Register value_reg = TMP2;
+    if (IsSameObject(compiler::NullObject(), value)) {
+      value_reg = NULL_REG;
+    } else if (target::IsSmi(object) && (target::ToRawSmi(object) == 0)) {
+      value_reg = ZR;
+    } else {
+      LoadObject(value_reg, value);
+    }
+    StoreIntoObjectOffsetNoBarrier(object, offset, value_reg, memory_order);
+  } else if (IsITypeImm(offset - kHeapObjectTag)) {
+    StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
+  } else {
+    AddImmediate(TMP, object, offset - kHeapObjectTag);
+    StoreIntoObjectNoBarrier(object, Address(TMP), value);
+  }
+}
+void Assembler::StoreCompressedIntoObjectOffsetNoBarrier(
+    Register object,
+    int32_t offset,
+    const Object& value,
+    MemoryOrder memory_order) {
+  UNIMPLEMENTED();
+}
+
+// Stores a non-tagged value into a heap object.
+void Assembler::StoreInternalPointer(Register object,
+                                     const Address& dest,
+                                     Register value) {
+  sx(value, dest);
+}
+
+// Object pool, loading from pool, etc.
+void Assembler::LoadPoolPointer(Register pp) {
+  CheckCodePointer();
+  lx(pp, FieldAddress(CODE_REG, target::Code::object_pool_offset()));
+
+  // When in the PP register, the pool pointer is untagged. When we
+  // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP
+  // then untags when restoring from the stack. This will make loading from the
+  // object pool only one instruction for the first 4096 entries. Otherwise,
+  // because the offset wouldn't be aligned, it would be only one instruction
+  // for the first 64 entries.
+  subi(pp, pp, kHeapObjectTag);
+  set_constant_pool_allowed(pp == PP);
+}
+
+intptr_t Assembler::FindImmediate(int64_t imm) {
+  UNIMPLEMENTED();
+}
+bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(IsOriginalObject(object));
+  if (!constant_pool_allowed()) {
+    return false;
+  }
+
+  ASSERT(IsNotTemporaryScopedHandle(object));
+  ASSERT(IsInOldSpace(object));
+  return true;
+}
+void Assembler::LoadNativeEntry(
+    Register dst,
+    const ExternalLabel* label,
+    ObjectPoolBuilderEntry::Patchability patchable) {
+  const intptr_t index =
+      object_pool_builder().FindNativeFunction(label, patchable);
+  LoadWordFromPoolIndex(dst, index);
+}
+void Assembler::LoadIsolate(Register dst) {
+  lx(dst, Address(THR, target::Thread::isolate_offset()));
+}
+void Assembler::LoadIsolateGroup(Register dst) {
+  lx(dst, Address(THR, target::Thread::isolate_group_offset()));
+}
+
+void Assembler::LoadImmediate(Register reg, intx_t imm) {
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+
+#if XLEN > 32
+  if (!Utils::IsInt(32, imm)) {
+    LoadImmediate(reg, (imm - lo) >> 12);
+    slli(reg, reg, 12);
+    if (lo != 0) {
+      addi(reg, reg, lo);
+    }
+    return;
+  }
+#endif
+
+  if (hi == 0) {
+    addi(reg, ZR, lo);
+  } else {
+    lui(reg, hi);
+    if (lo != 0) {
+#if XLEN == 32
+      addi(reg, reg, lo);
+#else
+      addiw(reg, reg, lo);
+#endif
+    }
+  }
+}
+
+void Assembler::LoadDImmediate(FRegister reg, double immd) {
+  int64_t imm = bit_cast<int64_t, double>(immd);
+  if (imm == 0) {
+#if XLEN >= 64
+    fmvdx(reg, ZR);  // bit_cast uint64_t -> double
+#else
+    fcvtdwu(reg, ZR);  // static_cast uint32_t -> double
+#endif
+  } else {
+    ASSERT(constant_pool_allowed());
+#if XLEN >= 64
+    intptr_t index = object_pool_builder().FindImmediate(imm);
+    intptr_t offset = target::ObjectPool::element_offset(index);
+#else
+    intptr_t lo_index =
+        object_pool_builder().AddImmediate(Utils::Low32Bits(imm));
+    intptr_t hi_index =
+        object_pool_builder().AddImmediate(Utils::High32Bits(imm));
+    ASSERT(lo_index + 1 == hi_index);
+    intptr_t offset = target::ObjectPool::element_offset(lo_index);
+#endif
+    LoadDFromOffset(reg, PP, offset);
+  }
+}
+
+// Load word from pool from the given offset using encoding that
+// InstructionPattern::DecodeLoadWordFromPool can decode.
+//
+// Note: the function never clobbers TMP, TMP2 scratch registers.
+void Assembler::LoadWordFromPoolIndex(Register dst,
+                                      intptr_t index,
+                                      Register pp) {
+  ASSERT((pp != PP) || constant_pool_allowed());
+  ASSERT(dst != pp);
+  const uint32_t offset = target::ObjectPool::element_offset(index);
+  // PP is untagged.
+  intx_t imm = offset;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  if (hi == 0) {
+    lx(dst, Address(pp, lo));
+  } else {
+    lui(dst, hi);
+    add(dst, dst, pp);
+    lx(dst, Address(dst, lo));
+  }
+}
+
+void Assembler::CompareObject(Register reg, const Object& object) {
+  ASSERT(IsOriginalObject(object));
+  if (IsSameObject(compiler::NullObject(), object)) {
+    CompareObjectRegisters(reg, NULL_REG);
+  } else if (target::IsSmi(object)) {
+    CompareImmediate(reg, target::ToRawSmi(object));
+  } else {
+    LoadObject(TMP, object);
+    CompareObjectRegisters(reg, TMP);
+  }
+}
+
+void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
+#if XLEN == 64
+  srliw(result, tags, target::UntaggedObject::kClassIdTagPos);
+#else
+  srli(result, tags, target::UntaggedObject::kClassIdTagPos);
+#endif
+}
+void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
+  ASSERT(target::UntaggedObject::kSizeTagPos == 8);
+  ASSERT(target::UntaggedObject::kSizeTagSize == 8);
+  srli(result, tags, target::UntaggedObject::kSizeTagPos);
+  andi(result, result, (1 << target::UntaggedObject::kSizeTagSize) - 1);
+  slli(result, result, target::ObjectAlignment::kObjectAlignmentLog2);
+}
+
+void Assembler::LoadClassId(Register result, Register object) {
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
+  const intptr_t class_id_offset =
+      target::Object::tags_offset() +
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
+  lhu(result, FieldAddress(object, class_id_offset));
+}
+void Assembler::LoadClassById(Register result, Register class_id) {
+  ASSERT(result != class_id);
+
+  const intptr_t table_offset =
+      target::IsolateGroup::cached_class_table_table_offset();
+
+  LoadIsolateGroup(result);
+  LoadFromOffset(result, result, table_offset);
+  slli(TMP, class_id, target::kWordSizeLog2);
+  add(result, result, TMP);
+  lx(result, Address(result, 0));
+}
+void Assembler::CompareClassId(Register object,
+                               intptr_t class_id,
+                               Register scratch) {
+  ASSERT(scratch != kNoRegister);
+  LoadClassId(scratch, object);
+  CompareImmediate(scratch, class_id);
+}
+// Note: input and output registers must be different.
+void Assembler::LoadClassIdMayBeSmi(Register result, Register object) {
+  ASSERT(result != object);
+  ASSERT(result != TMP2);
+  ASSERT(object != TMP2);
+  li(result, kSmiCid);
+  Label done;
+  BranchIfSmi(object, &done, kNearJump);
+  LoadClassId(result, object);
+  Bind(&done);
+}
+void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) {
+  LoadClassIdMayBeSmi(result, object);
+  SmiTag(result);
+}
+void Assembler::EnsureHasClassIdInDEBUG(intptr_t cid,
+                                        Register src,
+                                        Register scratch,
+                                        bool can_be_null) {
+#if defined(DEBUG)
+  Comment("Check that object in register has cid %" Pd "", cid);
+  Label matches;
+  LoadClassIdMayBeSmi(scratch, src);
+  CompareImmediate(scratch, cid);
+  BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  if (can_be_null) {
+    CompareImmediate(scratch, kNullCid);
+    BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  }
+  trap();
+  Bind(&matches);
+#endif
+}
+
+void Assembler::EnterFrame(intptr_t frame_size) {
+  // N.B. The ordering here is important. We must never write beyond SP or
+  // it can be clobbered by a signal handler.
+  subi(SP, SP, frame_size + 2 * target::kWordSize);
+  sx(RA, Address(SP, frame_size + 1 * target::kWordSize));
+  sx(FP, Address(SP, frame_size + 0 * target::kWordSize));
+  addi(FP, SP, frame_size + 0 * target::kWordSize);
+}
+void Assembler::LeaveFrame() {
+  // N.B. The ordering here is important. We must never read beyond SP or
+  // it may have already been clobbered by a signal handler.
+  mv(SP, FP);
+  lx(FP, Address(SP, 0 * target::kWordSize));
+  lx(RA, Address(SP, 1 * target::kWordSize));
+  addi(SP, SP, 2 * target::kWordSize);
+}
+
+void Assembler::TransitionGeneratedToNative(Register destination,
+                                            Register new_exit_frame,
+                                            Register new_exit_through_ffi,
+                                            bool enter_safepoint) {
+  // Save exit frame information to enable stack walking.
+  sx(new_exit_frame,
+     Address(THR, target::Thread::top_exit_frame_info_offset()));
+
+  sx(new_exit_through_ffi,
+     Address(THR, target::Thread::exit_through_ffi_offset()));
+  Register tmp = new_exit_through_ffi;
+
+  // Mark that the thread is executing native code.
+  sx(destination, Address(THR, target::Thread::vm_tag_offset()));
+  li(tmp, target::Thread::native_execution_state());
+  sx(tmp, Address(THR, target::Thread::execution_state_offset()));
+
+  if (enter_safepoint) {
+    EnterFullSafepoint(tmp);
+  }
+}
+
+void Assembler::TransitionNativeToGenerated(Register state,
+                                            bool exit_safepoint) {
+  if (exit_safepoint) {
+    ExitFullSafepoint(state);
+  } else {
+#if defined(DEBUG)
+    // Ensure we've already left the safepoint.
+    ASSERT(target::Thread::full_safepoint_state_acquired() != 0);
+    li(state, target::Thread::full_safepoint_state_acquired());
+    lx(RA, Address(THR, target::Thread::safepoint_state_offset()));
+    and_(RA, RA, state);
+    Label ok;
+    beqz(RA, &ok, Assembler::kNearJump);
+    Breakpoint();
+    Bind(&ok);
+#endif
+  }
+
+  // Mark that the thread is executing Dart code.
+  li(state, target::Thread::vm_tag_dart_id());
+  sx(state, Address(THR, target::Thread::vm_tag_offset()));
+  li(state, target::Thread::generated_execution_state());
+  sx(state, Address(THR, target::Thread::execution_state_offset()));
+
+  // Reset exit frame information in Isolate's mutator thread structure.
+  sx(ZR, Address(THR, target::Thread::top_exit_frame_info_offset()));
+  sx(ZR, Address(THR, target::Thread::exit_through_ffi_offset()));
+}
+
+void Assembler::EnterFullSafepoint(Register state) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced. This simplifies GenerateJitCallbackTrampolines.
+
+  Register addr = RA;
+  ASSERT(addr != state);
+
+  Label slow_path, done, retry;
+  if (FLAG_use_slow_path) {
+    j(&slow_path, Assembler::kNearJump);
+  }
+
+  addi(addr, THR, target::Thread::safepoint_state_offset());
+  Bind(&retry);
+  lr(state, Address(addr, 0));
+  subi(state, state, target::Thread::full_safepoint_state_unacquired());
+  bnez(state, &slow_path, Assembler::kNearJump);
+
+  li(state, target::Thread::full_safepoint_state_acquired());
+  sc(state, state, Address(addr, 0));
+  beqz(state, &done, Assembler::kNearJump);  // 0 means sc was successful.
+
+  if (!FLAG_use_slow_path) {
+    j(&retry, Assembler::kNearJump);
+  }
+
+  Bind(&slow_path);
+  lx(addr, Address(THR, target::Thread::enter_safepoint_stub_offset()));
+  lx(addr, FieldAddress(addr, target::Code::entry_point_offset()));
+  jalr(addr);
+
+  Bind(&done);
+}
+
+void Assembler::ExitFullSafepoint(Register state) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced, for consistency with EnterFullSafepoint.
+  Register addr = RA;
+  ASSERT(addr != state);
+
+  Label slow_path, done, retry;
+  if (FLAG_use_slow_path) {
+    j(&slow_path, Assembler::kNearJump);
+  }
+
+  addi(addr, THR, target::Thread::safepoint_state_offset());
+  Bind(&retry);
+  lr(state, Address(addr, 0));
+  subi(state, state, target::Thread::full_safepoint_state_acquired());
+  bnez(state, &slow_path, Assembler::kNearJump);
+
+  li(state, target::Thread::full_safepoint_state_unacquired());
+  sc(state, state, Address(addr, 0));
+  beqz(state, &done, Assembler::kNearJump);  // 0 means sc was successful.
+
+  if (!FLAG_use_slow_path) {
+    j(&retry, Assembler::kNearJump);
+  }
+
+  Bind(&slow_path);
+  lx(addr, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  lx(addr, FieldAddress(addr, target::Code::entry_point_offset()));
+  jalr(addr);
+
+  Bind(&done);
+}
+
+void Assembler::CheckCodePointer() {
+#ifdef DEBUG
+  if (!FLAG_check_code_pointer) {
+    return;
+  }
+  Comment("CheckCodePointer");
+  Label cid_ok, instructions_ok;
+  CompareClassId(CODE_REG, kCodeCid, TMP);
+  BranchIf(EQ, &cid_ok, kNearJump);
+  ebreak();
+  Bind(&cid_ok);
+
+  const intptr_t entry_offset =
+      CodeSize() + target::Instructions::HeaderSize() - kHeapObjectTag;
+  intx_t imm = -entry_offset;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  auipc(TMP, hi);
+  addi(TMP, TMP, lo);
+  lx(TMP2, FieldAddress(CODE_REG, target::Code::saved_instructions_offset()));
+  beq(TMP, TMP2, &instructions_ok, kNearJump);
+  ebreak();
+  Bind(&instructions_ok);
+#endif
+}
+
+void Assembler::RestoreCodePointer() {
+  lx(CODE_REG,
+     Address(FP, target::frame_layout.code_from_fp * target::kWordSize));
+  CheckCodePointer();
+}
+
+// Restores the values of the registers that are blocked to cache some values
+// e.g. BARRIER_MASK and NULL_REG.
+void Assembler::RestorePinnedRegisters() {
+  lx(WRITE_BARRIER_MASK,
+     Address(THR, target::Thread::write_barrier_mask_offset()));
+  lx(NULL_REG, Address(THR, target::Thread::object_null_offset()));
+}
+
+void Assembler::SetupGlobalPoolAndDispatchTable() {
+  ASSERT(FLAG_precompiled_mode);
+  lx(PP, Address(THR, target::Thread::global_object_pool_offset()));
+  subi(PP, PP, kHeapObjectTag);  // Pool in PP is untagged!
+  lx(DISPATCH_TABLE_REG,
+     Address(THR, target::Thread::dispatch_table_array_offset()));
+}
+
+void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
+  ASSERT(!constant_pool_allowed());
+
+  if (!IsITypeImm(frame_size + 4 * target::kWordSize)) {
+    EnterDartFrame(0, new_pp);
+    AddImmediate(SP, SP, -frame_size);
+    return;
+  }
+
+  // N.B. The ordering here is important. We must never write beyond SP or
+  // it can be clobbered by a signal handler.
+  if (FLAG_precompiled_mode) {
+    subi(SP, SP, frame_size + 2 * target::kWordSize);
+    sx(RA, Address(SP, frame_size + 1 * target::kWordSize));
+    sx(FP, Address(SP, frame_size + 0 * target::kWordSize));
+    addi(FP, SP, frame_size + 0 * target::kWordSize);
+  } else {
+    subi(SP, SP, frame_size + 4 * target::kWordSize);
+    sx(RA, Address(SP, frame_size + 3 * target::kWordSize));
+    sx(FP, Address(SP, frame_size + 2 * target::kWordSize));
+    sx(CODE_REG, Address(SP, frame_size + 1 * target::kWordSize));
+    addi(PP, PP, kHeapObjectTag);
+    sx(PP, Address(SP, frame_size + 0 * target::kWordSize));
+    addi(FP, SP, frame_size + 2 * target::kWordSize);
+    if (new_pp == kNoRegister) {
+      LoadPoolPointer();
+    } else {
+      mv(PP, new_pp);
+    }
+  }
+  set_constant_pool_allowed(true);
+}
+
+// On entry to a function compiled for OSR, the caller's frame pointer, the
+// stack locals, and any copied parameters are already in place.  The frame
+// pointer is already set up.  The PC marker is not correct for the
+// optimized function and there may be extra space for spill slots to
+// allocate. We must also set up the pool pointer for the function.
+void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
+  ASSERT(!constant_pool_allowed());
+  Comment("EnterOsrFrame");
+  RestoreCodePointer();
+  LoadPoolPointer();
+
+  if (extra_size > 0) {
+    AddImmediate(SP, -extra_size);
+  }
+}
+
+void Assembler::LeaveDartFrame(RestorePP restore_pp) {
+  // N.B. The ordering here is important. We must never read beyond SP or
+  // it may have already been clobbered by a signal handler.
+  if (!FLAG_precompiled_mode) {
+    if (restore_pp == kRestoreCallerPP) {
+      lx(PP, Address(FP, target::frame_layout.saved_caller_pp_from_fp *
+                             target::kWordSize));
+      subi(PP, PP, kHeapObjectTag);
+    }
+  }
+  set_constant_pool_allowed(false);
+  mv(SP, FP);
+  lx(FP, Address(SP, 0 * target::kWordSize));
+  lx(RA, Address(SP, 1 * target::kWordSize));
+  addi(SP, SP, 2 * target::kWordSize);
+
+  // TODO(riscv): When we know the stack depth, we can avoid updating SP twice.
+}
+
+void Assembler::CallRuntime(const RuntimeEntry& entry,
+                            intptr_t argument_count) {
+  entry.Call(this, argument_count);
+}
+
+void Assembler::EnterCFrame(intptr_t frame_space) {
+  // N.B. The ordering here is important. We must never read beyond SP or
+  // it may have already been clobbered by a signal handler.
+  subi(SP, SP, frame_space + 2 * target::kWordSize);
+  sx(RA, Address(SP, frame_space + 1 * target::kWordSize));
+  sx(FP, Address(SP, frame_space + 0 * target::kWordSize));
+  addi(FP, SP, frame_space);
+}
+
+void Assembler::LeaveCFrame() {
+  // N.B. The ordering here is important. We must never read beyond SP or
+  // it may have already been clobbered by a signal handler.
+  mv(SP, FP);
+  lx(FP, Address(SP, 0 * target::kWordSize));
+  lx(RA, Address(SP, 1 * target::kWordSize));
+  addi(SP, SP, 2 * target::kWordSize);
+}
+
+// A0: Receiver
+// S5: ICData entry array
+// PP: Caller's PP (preserved)
+void Assembler::MonomorphicCheckedEntryJIT() {
+  has_monomorphic_entry_ = true;
+  const intptr_t saved_far_branch_level = far_branch_level();
+  set_far_branch_level(0);
+  const intptr_t start = CodeSize();
+
+  Label immediate, miss;
+  Bind(&miss);
+  lx(TMP, Address(THR, target::Thread::switchable_call_miss_entry_offset()));
+  jr(TMP);
+
+  Comment("MonomorphicCheckedEntry");
+  ASSERT_EQUAL(CodeSize() - start,
+               target::Instructions::kMonomorphicEntryOffsetJIT);
+
+  Register entries_reg = IC_DATA_REG;  // Contains ICData::entries().
+  const intptr_t cid_offset = target::Array::element_offset(0);
+  const intptr_t count_offset = target::Array::element_offset(1);
+  ASSERT(A1 != PP);
+  ASSERT(A1 != entries_reg);
+  ASSERT(A1 != CODE_REG);
+
+  lx(TMP, FieldAddress(entries_reg, cid_offset));
+  LoadTaggedClassIdMayBeSmi(A1, A0);
+  bne(TMP, A1, &miss, kNearJump);
+
+  lx(TMP, FieldAddress(entries_reg, count_offset));
+  addi(TMP, TMP, target::ToRawSmi(1));
+  sx(TMP, FieldAddress(entries_reg, count_offset));
+
+  li(ARGS_DESC_REG, 0);  // GC-safe for OptimizeInvokedFunction
+
+  // Fall through to unchecked entry.
+  ASSERT_EQUAL(CodeSize() - start,
+               target::Instructions::kPolymorphicEntryOffsetJIT);
+
+  set_far_branch_level(saved_far_branch_level);
+}
+
+// A0 receiver, S5 guarded cid as Smi.
+// Preserve S4 (ARGS_DESC_REG), not required today, but maybe later.
+// PP: Caller's PP (preserved)
+void Assembler::MonomorphicCheckedEntryAOT() {
+  has_monomorphic_entry_ = true;
+  intptr_t saved_far_branch_level = far_branch_level();
+  set_far_branch_level(0);
+
+  const intptr_t start = CodeSize();
+
+  Label immediate, miss;
+  Bind(&miss);
+  lx(TMP, Address(THR, target::Thread::switchable_call_miss_entry_offset()));
+  jr(TMP);
+
+  Comment("MonomorphicCheckedEntry");
+  ASSERT_EQUAL(CodeSize() - start,
+               target::Instructions::kMonomorphicEntryOffsetAOT);
+  LoadClassId(TMP, A0);
+  SmiTag(TMP);
+  bne(S5, TMP, &miss, kNearJump);
+
+  // Fall through to unchecked entry.
+  ASSERT_EQUAL(CodeSize() - start,
+               target::Instructions::kPolymorphicEntryOffsetAOT);
+
+  set_far_branch_level(saved_far_branch_level);
+}
+
+void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
+  has_monomorphic_entry_ = true;
+  while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
+    ebreak();
+  }
+  j(label);
+  while (CodeSize() < target::Instructions::kPolymorphicEntryOffsetJIT) {
+    ebreak();
+  }
+}
+
+#ifndef PRODUCT
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  ASSERT(cid > 0);
+
+  const intptr_t shared_table_offset =
+      target::IsolateGroup::shared_class_table_offset();
+  const intptr_t table_offset =
+      target::SharedClassTable::class_heap_stats_table_offset();
+  const intptr_t class_offset = target::ClassTable::ClassOffsetFor(cid);
+
+  LoadIsolateGroup(temp_reg);
+  lx(temp_reg, Address(temp_reg, shared_table_offset));
+  lx(temp_reg, Address(temp_reg, table_offset));
+  if (IsITypeImm(class_offset)) {
+    lbu(temp_reg, Address(temp_reg, class_offset));
+  } else {
+    AddImmediate(temp_reg, class_offset);
+    lbu(temp_reg, Address(temp_reg, 0));
+  }
+  bnez(temp_reg, trace);
+}
+#endif  // !PRODUCT
+
+void Assembler::TryAllocateObject(intptr_t cid,
+                                  intptr_t instance_size,
+                                  Label* failure,
+                                  JumpDistance distance,
+                                  Register instance_reg,
+                                  Register temp_reg) {
+  ASSERT(failure != NULL);
+  ASSERT(instance_size != 0);
+  ASSERT(instance_reg != temp_reg);
+  ASSERT(temp_reg != kNoRegister);
+  ASSERT(Utils::IsAligned(instance_size,
+                          target::ObjectAlignment::kObjectAlignment));
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size)) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    NOT_IN_PRODUCT(MaybeTraceAllocation(cid, temp_reg, failure));
+
+    lx(instance_reg, Address(THR, target::Thread::top_offset()));
+    lx(temp_reg, Address(THR, target::Thread::end_offset()));
+    // instance_reg: current top (next object start).
+    // temp_reg: heap end
+
+    // TODO(koda): Protect against unsigned overflow here.
+    AddImmediate(instance_reg, instance_size);
+    // instance_reg: potential top (next object start).
+    // fail if heap end unsigned less than or equal to new heap top.
+    bleu(temp_reg, instance_reg, failure, distance);
+
+    // Successfully allocated the object, now update temp to point to
+    // next object start and store the class in the class field of object.
+    sx(instance_reg, Address(THR, target::Thread::top_offset()));
+    // Move instance_reg back to the start of the object and tag it.
+    AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
+
+    const uword tags = target::MakeTagWordForNewSpaceObject(cid, instance_size);
+    LoadImmediate(temp_reg, tags);
+    StoreToOffset(temp_reg,
+                  FieldAddress(instance_reg, target::Object::tags_offset()));
+  } else {
+    j(failure, distance);
+  }
+}
+
+void Assembler::TryAllocateArray(intptr_t cid,
+                                 intptr_t instance_size,
+                                 Label* failure,
+                                 Register instance,
+                                 Register end_address,
+                                 Register temp1,
+                                 Register temp2) {
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size)) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    NOT_IN_PRODUCT(MaybeTraceAllocation(cid, temp1, failure));
+    // Potential new object start.
+    lx(instance, Address(THR, target::Thread::top_offset()));
+    AddImmediate(end_address, instance, instance_size);
+    bltu(end_address, instance, failure);  // Fail on unsigned overflow.
+
+    // Check if the allocation fits into the remaining space.
+    // instance: potential new object start.
+    // end_address: potential next object start.
+    lx(temp2, Address(THR, target::Thread::end_offset()));
+    bgeu(end_address, temp2, failure);
+
+    // Successfully allocated the object(s), now update top to point to
+    // next object start and initialize the object.
+    sx(end_address, Address(THR, target::Thread::top_offset()));
+    addi(instance, instance, kHeapObjectTag);
+    NOT_IN_PRODUCT(LoadImmediate(temp2, instance_size));
+
+    // Initialize the tags.
+    // instance: new object start as a tagged pointer.
+    const uword tags = target::MakeTagWordForNewSpaceObject(cid, instance_size);
+    LoadImmediate(temp2, tags);
+    sx(temp2, FieldAddress(instance, target::Object::tags_offset()));
+  } else {
+    j(failure);
+  }
+}
+
+void Assembler::GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target) {
+  // JAL only has a +/- 1MB range. AUIPC+JALR has a +/- 2GB range.
+  intx_t imm = offset_into_target;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  auipc(RA, hi);
+  jalr_fixed(RA, RA, lo);
+}
+
+void Assembler::GenerateUnRelocatedPcRelativeTailCall(
+    intptr_t offset_into_target) {
+  // J only has a +/- 1MB range. AUIPC+JR has a +/- 2GB range.
+  intx_t imm = offset_into_target;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  auipc(TMP, hi);
+  jalr_fixed(ZR, TMP, lo);
+}
+
+static OperandSize OperandSizeFor(intptr_t cid) {
+  switch (cid) {
+    case kArrayCid:
+    case kImmutableArrayCid:
+    case kTypeArgumentsCid:
+      return kObjectBytes;
+    case kOneByteStringCid:
+    case kExternalOneByteStringCid:
+      return kByte;
+    case kTwoByteStringCid:
+    case kExternalTwoByteStringCid:
+      return kTwoBytes;
+    case kTypedDataInt8ArrayCid:
+      return kByte;
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+      return kUnsignedByte;
+    case kTypedDataInt16ArrayCid:
+      return kTwoBytes;
+    case kTypedDataUint16ArrayCid:
+      return kUnsignedTwoBytes;
+    case kTypedDataInt32ArrayCid:
+      return kFourBytes;
+    case kTypedDataUint32ArrayCid:
+      return kUnsignedFourBytes;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      return kDWord;
+    case kTypedDataFloat32ArrayCid:
+      return kSWord;
+    case kTypedDataFloat64ArrayCid:
+      return kDWord;
+    case kTypedDataFloat32x4ArrayCid:
+    case kTypedDataInt32x4ArrayCid:
+    case kTypedDataFloat64x2ArrayCid:
+      return kQWord;
+    case kTypedDataInt8ArrayViewCid:
+      UNREACHABLE();
+      return kByte;
+    default:
+      UNREACHABLE();
+      return kByte;
+  }
+}
+
+Address Assembler::ElementAddressForIntIndex(bool is_external,
+                                             intptr_t cid,
+                                             intptr_t index_scale,
+                                             Register array,
+                                             intptr_t index) const {
+  const int64_t offset = index * index_scale + HeapDataOffset(is_external, cid);
+  ASSERT(Utils::IsInt(32, offset));
+  return Address(array, static_cast<int32_t>(offset));
+}
+void Assembler::ComputeElementAddressForIntIndex(Register address,
+                                                 bool is_external,
+                                                 intptr_t cid,
+                                                 intptr_t index_scale,
+                                                 Register array,
+                                                 intptr_t index) {
+  const int64_t offset = index * index_scale + HeapDataOffset(is_external, cid);
+  AddImmediate(address, array, offset);
+}
+
+Address Assembler::ElementAddressForRegIndex(bool is_external,
+                                             intptr_t cid,
+                                             intptr_t index_scale,
+                                             bool index_unboxed,
+                                             Register array,
+                                             Register index,
+                                             Register temp) {
+  return ElementAddressForRegIndexWithSize(is_external, cid,
+                                           OperandSizeFor(cid), index_scale,
+                                           index_unboxed, array, index, temp);
+}
+
+Address Assembler::ElementAddressForRegIndexWithSize(bool is_external,
+                                                     intptr_t cid,
+                                                     OperandSize size,
+                                                     intptr_t index_scale,
+                                                     bool index_unboxed,
+                                                     Register array,
+                                                     Register index,
+                                                     Register temp) {
+  // If unboxed, index is expected smi-tagged, (i.e, LSL 1) for all arrays.
+  const intptr_t boxing_shift = index_unboxed ? 0 : -kSmiTagShift;
+  const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) + boxing_shift;
+  const int32_t offset = HeapDataOffset(is_external, cid);
+  ASSERT(array != temp);
+  ASSERT(index != temp);
+  if (shift == 0) {
+    add(temp, array, index);
+  } else if (shift < 0) {
+    ASSERT(shift == -1);
+    srai(temp, index, 1);
+    add(temp, array, temp);
+  } else {
+    slli(temp, index, shift);
+    add(temp, array, temp);
+  }
+  return Address(temp, offset);
+}
+
+void Assembler::ComputeElementAddressForRegIndex(Register address,
+                                                 bool is_external,
+                                                 intptr_t cid,
+                                                 intptr_t index_scale,
+                                                 bool index_unboxed,
+                                                 Register array,
+                                                 Register index) {
+  // If unboxed, index is expected smi-tagged, (i.e, LSL 1) for all arrays.
+  const intptr_t boxing_shift = index_unboxed ? 0 : -kSmiTagShift;
+  const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) + boxing_shift;
+  const int32_t offset = HeapDataOffset(is_external, cid);
+  ASSERT(array != address);
+  ASSERT(index != address);
+  if (shift == 0) {
+    add(address, array, index);
+  } else if (shift < 0) {
+    ASSERT(shift == -1);
+    srai(address, index, 1);
+    add(address, array, address);
+  } else {
+    slli(address, index, shift);
+    add(address, array, address);
+  }
+  if (offset != 0) {
+    AddImmediate(address, address, offset);
+  }
+}
+
+void Assembler::LoadStaticFieldAddress(Register address,
+                                       Register field,
+                                       Register scratch) {
+  LoadCompressedSmiFieldFromOffset(
+      scratch, field, target::Field::host_offset_or_field_id_offset());
+  const intptr_t field_table_offset =
+      compiler::target::Thread::field_table_values_offset();
+  LoadMemoryValue(address, THR, static_cast<int32_t>(field_table_offset));
+  slli(scratch, scratch, target::kWordSizeLog2 - kSmiTagShift);
+  add(address, address, scratch);
+}
+
+void Assembler::LoadCompressedFieldAddressForRegOffset(
+    Register address,
+    Register instance,
+    Register offset_in_words_as_smi) {
+  slli(TMP, offset_in_words_as_smi,
+       target::kCompressedWordSizeLog2 - kSmiTagShift);
+  add(TMP, TMP, instance);
+  addi(address, TMP, -kHeapObjectTag);
+}
+
+void Assembler::LoadFieldAddressForRegOffset(Register address,
+                                             Register instance,
+                                             Register offset_in_words_as_smi) {
+  slli(TMP, offset_in_words_as_smi, target::kWordSizeLog2 - kSmiTagShift);
+  add(TMP, TMP, instance);
+  addi(address, TMP, -kHeapObjectTag);
+}
+
+// Note: the function never clobbers TMP, TMP2 scratch registers.
+void Assembler::LoadObjectHelper(Register dst,
+                                 const Object& object,
+                                 bool is_unique) {
+  ASSERT(IsOriginalObject(object));
+  // `is_unique == true` effectively means object has to be patchable.
+  // (even if the object is null)
+  if (!is_unique) {
+    if (IsSameObject(compiler::NullObject(), object)) {
+      mv(dst, NULL_REG);
+      return;
+    }
+    if (IsSameObject(CastHandle<Object>(compiler::TrueObject()), object)) {
+      addi(dst, NULL_REG, kTrueOffsetFromNull);
+      return;
+    }
+    if (IsSameObject(CastHandle<Object>(compiler::FalseObject()), object)) {
+      addi(dst, NULL_REG, kFalseOffsetFromNull);
+      return;
+    }
+    word offset = 0;
+    if (target::CanLoadFromThread(object, &offset)) {
+      lx(dst, Address(THR, offset));
+      return;
+    }
+    if (target::IsSmi(object)) {
+      intx_t raw_smi = target::ToRawSmi(object);
+      if (IsITypeImm(raw_smi)) {
+        li(dst, raw_smi);
+        return;
+      }
+      if (IsUTypeImm(raw_smi)) {
+        lui(dst, raw_smi);
+        return;
+      }
+    }
+  }
+  if (CanLoadFromObjectPool(object)) {
+    const intptr_t index =
+        is_unique ? object_pool_builder().AddObject(
+                        object, ObjectPoolBuilderEntry::kPatchable)
+                  : object_pool_builder().FindObject(
+                        object, ObjectPoolBuilderEntry::kNotPatchable);
+    LoadWordFromPoolIndex(dst, index);
+    return;
+  }
+  ASSERT(target::IsSmi(object));
+  LoadImmediate(dst, target::ToRawSmi(object));
+}
+
+// Note: leaf call sequence uses some abi callee save registers as scratch
+// so they should be manually preserved.
+void Assembler::EnterCallRuntimeFrame(intptr_t frame_size, bool is_leaf) {
+  // N.B. The ordering here is important. We must never write beyond SP or
+  // it can be clobbered by a signal handler.
+  if (FLAG_precompiled_mode) {
+    subi(SP, SP, 2 * target::kWordSize + frame_size);
+    sx(RA, Address(SP, 1 * target::kWordSize + frame_size));
+    sx(FP, Address(SP, 0 * target::kWordSize + frame_size));
+    addi(FP, SP, 0 * target::kWordSize + frame_size);
+  } else {
+    subi(SP, SP, 4 * target::kWordSize + frame_size);
+    sx(RA, Address(SP, 3 * target::kWordSize + frame_size));
+    sx(FP, Address(SP, 2 * target::kWordSize + frame_size));
+    sx(CODE_REG, Address(SP, 1 * target::kWordSize + frame_size));
+    addi(PP, PP, kHeapObjectTag);
+    sx(PP, Address(SP, 0 * target::kWordSize + frame_size));
+    addi(FP, SP, 2 * target::kWordSize + frame_size);
+  }
+
+  const RegisterSet kVolatileRegisterSet(kAbiVolatileCpuRegs,
+                                         kAbiVolatileFpuRegs);
+  PushRegisters(kVolatileRegisterSet);
+
+  if (!is_leaf) {  // Leaf calling sequence aligns the stack itself.
+    ReserveAlignedFrameSpace(0);
+  }
+}
+
+void Assembler::LeaveCallRuntimeFrame(bool is_leaf) {
+  const RegisterSet kVolatileRegisterSet(kAbiVolatileCpuRegs,
+                                         kAbiVolatileFpuRegs);
+
+  const intptr_t kPushedRegistersSize =
+      kVolatileRegisterSet.CpuRegisterCount() * target::kWordSize +
+      kVolatileRegisterSet.FpuRegisterCount() * kFpuRegisterSize +
+      (target::frame_layout.dart_fixed_frame_size - 2) *
+          target::kWordSize;  // From EnterStubFrame (excluding PC / FP)
+
+  subi(SP, FP, kPushedRegistersSize);
+
+  PopRegisters(kVolatileRegisterSet);
+
+  LeaveStubFrame();
+}
+
+void Assembler::CallRuntimeScope::Call(intptr_t argument_count) {
+  assembler_->CallRuntime(entry_, argument_count);
+}
+
+Assembler::CallRuntimeScope::~CallRuntimeScope() {
+  if (preserve_registers_) {
+    assembler_->LeaveCallRuntimeFrame(entry_.is_leaf());
+    if (restore_code_reg_) {
+      assembler_->PopRegister(CODE_REG);
+    }
+  }
+}
+
+Assembler::CallRuntimeScope::CallRuntimeScope(Assembler* assembler,
+                                              const RuntimeEntry& entry,
+                                              intptr_t frame_size,
+                                              bool preserve_registers,
+                                              const Address* caller)
+    : assembler_(assembler),
+      entry_(entry),
+      preserve_registers_(preserve_registers),
+      restore_code_reg_(caller != nullptr) {
+  if (preserve_registers_) {
+    if (caller != nullptr) {
+      assembler_->PushRegister(CODE_REG);
+      assembler_->lx(CODE_REG, *caller);
+    }
+    assembler_->EnterCallRuntimeFrame(frame_size, entry.is_leaf());
+  }
+}
+
+void Assembler::AddImmediateBranchOverflow(Register rd,
+                                           Register rs1,
+                                           intx_t imm,
+                                           Label* overflow) {
+  ASSERT(rd != TMP2);
+  if (rd == rs1) {
+    mv(TMP2, rs1);
+    AddImmediate(rd, rs1, imm);
+    if (imm > 0) {
+      blt(rd, TMP2, overflow);
+    } else if (imm < 0) {
+      bgt(rd, TMP2, overflow);
+    }
+  } else {
+    AddImmediate(rd, rs1, imm);
+    if (imm > 0) {
+      blt(rd, rs1, overflow);
+    } else if (imm < 0) {
+      bgt(rd, rs1, overflow);
+    }
+  }
+}
+void Assembler::SubtractImmediateBranchOverflow(Register rd,
+                                                Register rs1,
+                                                intx_t imm,
+                                                Label* overflow) {
+  // TODO(riscv): Incorrect for MIN_INTX_T!
+  AddImmediateBranchOverflow(rd, rs1, -imm, overflow);
+}
+void Assembler::MultiplyImmediateBranchOverflow(Register rd,
+                                                Register rs1,
+                                                intx_t imm,
+                                                Label* overflow) {
+  ASSERT(rd != TMP);
+  ASSERT(rd != TMP2);
+  ASSERT(rs1 != TMP);
+  ASSERT(rs1 != TMP2);
+
+  LoadImmediate(TMP2, imm);
+  // Macro-op fusion: when both products are needed, the recommended sequence
+  // is mulh first.
+  mulh(TMP, rs1, TMP2);
+  mul(rd, rs1, TMP2);
+  srai(TMP2, rd, XLEN - 1);
+  bne(TMP, TMP2, overflow);
+}
+void Assembler::AddBranchOverflow(Register rd,
+                                  Register rs1,
+                                  Register rs2,
+                                  Label* overflow) {
+  ASSERT(rd != TMP);
+  ASSERT(rd != TMP2);
+  ASSERT(rs1 != TMP);
+  ASSERT(rs1 != TMP2);
+  ASSERT(rs2 != TMP);
+  ASSERT(rs2 != TMP2);
+
+  if ((rd == rs1) && (rd == rs2)) {
+    ASSERT(rs1 == rs2);
+    mv(TMP, rs1);
+    add(rd, rs1, rs2);   // rs1, rs2 destroyed
+    xor_(TMP, TMP, rd);  // TMP negative if sign changed
+    bltz(TMP, overflow);
+  } else if (rs1 == rs2) {
+    ASSERT(rd != rs1);
+    ASSERT(rd != rs2);
+    add(rd, rs1, rs2);
+    xor_(TMP, rd, rs1);  // TMP negative if sign changed
+    bltz(TMP, overflow);
+  } else if (rd == rs1) {
+    ASSERT(rs1 != rs2);
+    slti(TMP, rs1, 0);
+    add(rd, rs1, rs2);  // rs1 destroyed
+    slt(TMP2, rd, rs2);
+    bne(TMP, TMP2, overflow);
+  } else if (rd == rs2) {
+    ASSERT(rs1 != rs2);
+    slti(TMP, rs2, 0);
+    add(rd, rs1, rs2);  // rs2 destroyed
+    slt(TMP2, rd, rs1);
+    bne(TMP, TMP2, overflow);
+  } else {
+    add(rd, rs1, rs2);
+    slti(TMP, rs2, 0);
+    slt(TMP2, rd, rs1);
+    bne(TMP, TMP2, overflow);
+  }
+}
+
+void Assembler::SubtractBranchOverflow(Register rd,
+                                       Register rs1,
+                                       Register rs2,
+                                       Label* overflow) {
+  ASSERT(rd != TMP);
+  ASSERT(rd != TMP2);
+  ASSERT(rs1 != TMP);
+  ASSERT(rs1 != TMP2);
+  ASSERT(rs2 != TMP);
+  ASSERT(rs2 != TMP2);
+
+  if ((rd == rs1) && (rd == rs2)) {
+    ASSERT(rs1 == rs2);
+    mv(TMP, rs1);
+    sub(rd, rs1, rs2);   // rs1, rs2 destroyed
+    xor_(TMP, TMP, rd);  // TMP negative if sign changed
+    bltz(TMP, overflow);
+  } else if (rs1 == rs2) {
+    ASSERT(rd != rs1);
+    ASSERT(rd != rs2);
+    sub(rd, rs1, rs2);
+    xor_(TMP, rd, rs1);  // TMP negative if sign changed
+    bltz(TMP, overflow);
+  } else if (rd == rs1) {
+    ASSERT(rs1 != rs2);
+    slti(TMP, rs1, 0);
+    sub(rd, rs1, rs2);  // rs1 destroyed
+    slt(TMP2, rd, rs2);
+    bne(TMP, TMP2, overflow);
+  } else if (rd == rs2) {
+    ASSERT(rs1 != rs2);
+    slti(TMP, rs2, 0);
+    sub(rd, rs1, rs2);  // rs2 destroyed
+    slt(TMP2, rd, rs1);
+    bne(TMP, TMP2, overflow);
+  } else {
+    sub(rd, rs1, rs2);
+    slti(TMP, rs2, 0);
+    slt(TMP2, rs1, rd);
+    bne(TMP, TMP2, overflow);
+  }
+}
+
+void Assembler::MultiplyBranchOverflow(Register rd,
+                                       Register rs1,
+                                       Register rs2,
+                                       Label* overflow) {
+  ASSERT(rd != TMP);
+  ASSERT(rd != TMP2);
+  ASSERT(rs1 != TMP);
+  ASSERT(rs1 != TMP2);
+  ASSERT(rs2 != TMP);
+  ASSERT(rs2 != TMP2);
+
+  // Macro-op fusion: when both products are needed, the recommended sequence
+  // is mulh first.
+  mulh(TMP, rs1, rs2);
+  mul(rd, rs1, rs2);
+  srai(TMP2, rd, XLEN - 1);
+  bne(TMP, TMP2, overflow);
+}
+
+}  // namespace compiler
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
new file mode 100644
index 0000000..c96fa8b
--- /dev/null
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -0,0 +1,1457 @@
+// 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.
+
+#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_RISCV_H_
+#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_RISCV_H_
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+#error "AOT runtime should not use compiler sources (including header files)"
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
+#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_
+#error Do not include assembler_riscv.h directly; use assembler.h instead.
+#endif
+
+#include <functional>
+
+#include "platform/assert.h"
+#include "platform/utils.h"
+#include "vm/class_id.h"
+#include "vm/compiler/assembler/assembler_base.h"
+#include "vm/constants.h"
+#include "vm/hash_map.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+// Forward declarations.
+class FlowGraphCompiler;
+class RuntimeEntry;
+class RegisterSet;
+
+namespace compiler {
+
+class Address {
+ public:
+  Address(Register base, intptr_t offset) : base_(base), offset_(offset) {}
+  explicit Address(Register base) : base_(base), offset_(0) {}
+
+  // Prevent implicit conversion of Register to intptr_t.
+  Address(Register base, Register index) = delete;
+
+  Register base() const { return base_; }
+  intptr_t offset() const { return offset_; }
+
+ private:
+  Register base_;
+  intptr_t offset_;
+};
+
+class FieldAddress : public Address {
+ public:
+  FieldAddress(Register base, intptr_t offset)
+      : Address(base, offset - kHeapObjectTag) {}
+
+  // Prevent implicit conversion of Register to intptr_t.
+  FieldAddress(Register base, Register index) = delete;
+};
+
+// All functions produce exactly one instruction.
+class MicroAssembler : public AssemblerBase {
+ public:
+  MicroAssembler(ObjectPoolBuilder* object_pool_builder,
+                 intptr_t far_branch_level,
+                 ExtensionSet extensions);
+  ~MicroAssembler();
+
+#if defined(TESTING)
+  void SetExtensions(ExtensionSet extensions) { extensions_ = extensions; }
+#endif
+  bool Supports(Extension extension) const {
+    return extensions_.Includes(extension);
+  }
+  bool Supports(ExtensionSet extensions) const {
+    return extensions_.IncludesAll(extensions);
+  }
+
+  intptr_t far_branch_level() const { return far_branch_level_; }
+  void set_far_branch_level(intptr_t level) { far_branch_level_ = level; }
+  void Bind(Label* label);
+
+  // ==== RV32I ====
+  void lui(Register rd, intptr_t imm);
+  void lui_fixed(Register rd, intptr_t imm);
+  void auipc(Register rd, intptr_t imm);
+
+  void jal(Register rd, Label* label, JumpDistance d = kFarJump);
+  void jal(Label* label, JumpDistance d = kFarJump) { jal(RA, label, d); }
+  void j(Label* label, JumpDistance d = kFarJump) { jal(ZR, label, d); }
+
+  void jalr(Register rd, Register rs1, intptr_t offset = 0);
+  void jalr_fixed(Register rd, Register rs1, intptr_t offset);
+  void jalr(Register rs1, intptr_t offset = 0) { jalr(RA, rs1, offset); }
+  void jr(Register rs1, intptr_t offset = 0) { jalr(ZR, rs1, offset); }
+  void ret() { jalr(ZR, RA, 0); }
+
+  void beq(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void bne(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void blt(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void bge(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void bgt(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump) {
+    blt(rs2, rs1, l, d);
+  }
+  void ble(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump) {
+    bge(rs2, rs1, l, d);
+  }
+  void bltu(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void bgeu(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump);
+  void bgtu(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump) {
+    bltu(rs2, rs1, l, d);
+  }
+  void bleu(Register rs1, Register rs2, Label* l, JumpDistance d = kFarJump) {
+    bgeu(rs2, rs1, l, d);
+  }
+
+  void lb(Register rd, Address addr);
+  void lh(Register rd, Address addr);
+  void lw(Register rd, Address addr);
+  void lbu(Register rd, Address addr);
+  void lhu(Register rd, Address addr);
+
+  void sb(Register rs2, Address addr);
+  void sh(Register rs2, Address addr);
+  void sw(Register rs2, Address addr);
+
+  void addi(Register rd, Register rs1, intptr_t imm);
+  void subi(Register rd, Register rs1, intptr_t imm) { addi(rd, rs1, -imm); }
+  void slti(Register rd, Register rs1, intptr_t imm);
+  void sltiu(Register rd, Register rs1, intptr_t imm);
+  void xori(Register rd, Register rs1, intptr_t imm);
+  void ori(Register rd, Register rs1, intptr_t imm);
+  void andi(Register rd, Register rs1, intptr_t imm);
+  void slli(Register rd, Register rs1, intptr_t shamt);
+  void srli(Register rd, Register rs1, intptr_t shamt);
+  void srai(Register rd, Register rs1, intptr_t shamt);
+
+  void add(Register rd, Register rs1, Register rs2);
+  void sub(Register rd, Register rs1, Register rs2);
+  void sll(Register rd, Register rs1, Register rs2);
+  void slt(Register rd, Register rs1, Register rs2);
+  void sltu(Register rd, Register rs1, Register rs2);
+  void xor_(Register rd, Register rs1, Register rs2);
+  void srl(Register rd, Register rs1, Register rs2);
+  void sra(Register rd, Register rs1, Register rs2);
+  void or_(Register rd, Register rs1, Register rs2);
+  void and_(Register rd, Register rs1, Register rs2);
+
+  void fence(HartEffects predecessor, HartEffects successor);
+  void fence() { fence(kAll, kAll); }
+  void fencei();
+  void ecall();
+  void ebreak();  // Causes SIGTRAP(5).
+
+  void csrrw(Register rd, uint32_t csr, Register rs1);
+  void csrrs(Register rd, uint32_t csr, Register rs1);
+  void csrrc(Register rd, uint32_t csr, Register rs1);
+  void csrr(Register rd, uint32_t csr) { csrrs(rd, csr, ZR); }
+  void csrw(uint32_t csr, Register rs) { csrrw(ZR, csr, rs); }
+  void csrs(uint32_t csr, Register rs) { csrrs(ZR, csr, rs); }
+  void csrc(uint32_t csr, Register rs) { csrrc(ZR, csr, rs); }
+  void csrrwi(Register rd, uint32_t csr, uint32_t imm);
+  void csrrsi(Register rd, uint32_t csr, uint32_t imm);
+  void csrrci(Register rd, uint32_t csr, uint32_t imm);
+  void csrwi(uint32_t csr, uint32_t imm) { csrrwi(ZR, csr, imm); }
+  void csrsi(uint32_t csr, uint32_t imm) { csrrsi(ZR, csr, imm); }
+  void csrci(uint32_t csr, uint32_t imm) { csrrci(ZR, csr, imm); }
+
+  void trap();  // Permanently reserved illegal instruction; causes SIGILL(4).
+
+  void nop() { addi(ZR, ZR, 0); }
+  void li(Register rd, intptr_t imm) { addi(rd, ZR, imm); }
+  void mv(Register rd, Register rs) { addi(rd, rs, 0); }
+  void not_(Register rd, Register rs) { xori(rd, rs, -1); }
+  void neg(Register rd, Register rs) { sub(rd, ZR, rs); }
+
+  void snez(Register rd, Register rs) { sltu(rd, ZR, rs); }
+  void seqz(Register rd, Register rs) { sltiu(rd, rs, 1); }
+  void sltz(Register rd, Register rs) { slt(rd, rs, ZR); }
+  void sgtz(Register rd, Register rs) { slt(rd, ZR, rs); }
+
+  void beqz(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    beq(rs, ZR, label, distance);
+  }
+  void bnez(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    bne(rs, ZR, label, distance);
+  }
+  void blez(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    bge(ZR, rs, label, distance);
+  }
+  void bgez(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    bge(rs, ZR, label, distance);
+  }
+  void bltz(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    blt(rs, ZR, label, distance);
+  }
+  void bgtz(Register rs, Label* label, JumpDistance distance = kFarJump) {
+    blt(ZR, rs, label, distance);
+  }
+
+  // ==== RV64I ====
+#if XLEN >= 64
+  void lwu(Register rd, Address addr);
+  void ld(Register rd, Address addr);
+
+  void sd(Register rs2, Address addr);
+
+  void addiw(Register rd, Register rs1, intptr_t imm);
+  void subiw(Register rd, Register rs1, intptr_t imm) { addiw(rd, rs1, -imm); }
+  void slliw(Register rd, Register rs1, intptr_t shamt);
+  void srliw(Register rd, Register rs1, intptr_t shamt);
+  void sraiw(Register rd, Register rs1, intptr_t shamt);
+
+  void addw(Register rd, Register rs1, Register rs2);
+  void subw(Register rd, Register rs1, Register rs2);
+  void sllw(Register rd, Register rs1, Register rs2);
+  void srlw(Register rd, Register rs1, Register rs2);
+  void sraw(Register rd, Register rs1, Register rs2);
+
+  void negw(Register rd, Register rs) { subw(rd, ZR, rs); }
+  void sextw(Register rd, Register rs) { addiw(rd, rs, 0); }
+#endif  // XLEN >= 64
+
+#if XLEN == 32
+  void lx(Register rd, Address addr) { lw(rd, addr); }
+  void sx(Register rs2, Address addr) { sw(rs2, addr); }
+#elif XLEN == 64
+  void lx(Register rd, Address addr) { ld(rd, addr); }
+  void sx(Register rs2, Address addr) { sd(rs2, addr); }
+#elif XLEN == 128
+  void lx(Register rd, Address addr) { lq(rd, addr); }
+  void sx(Register rs2, Address addr) { sq(rs2, addr); }
+#endif
+
+  // ==== RV32M ====
+  void mul(Register rd, Register rs1, Register rs2);
+  void mulh(Register rd, Register rs1, Register rs2);
+  void mulhsu(Register rd, Register rs1, Register rs2);
+  void mulhu(Register rd, Register rs1, Register rs2);
+  void div(Register rd, Register rs1, Register rs2);
+  void divu(Register rd, Register rs1, Register rs2);
+  void rem(Register rd, Register rs1, Register rs2);
+  void remu(Register rd, Register rs1, Register rs2);
+
+  // ==== RV64M ====
+#if XLEN >= 64
+  void mulw(Register rd, Register rs1, Register rs2);
+  void divw(Register rd, Register rs1, Register rs2);
+  void divuw(Register rd, Register rs1, Register rs2);
+  void remw(Register rd, Register rs1, Register rs2);
+  void remuw(Register rd, Register rs1, Register rs2);
+#endif  // XLEN >= 64
+
+  // ==== RV32A ====
+  void lrw(Register rd,
+           Address addr,
+           std::memory_order order = std::memory_order_relaxed);
+  void scw(Register rd,
+           Register rs2,
+           Address addr,
+           std::memory_order order = std::memory_order_relaxed);
+  void amoswapw(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+  void amoaddw(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoxorw(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoandw(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoorw(Register rd,
+              Register rs2,
+              Address addr,
+              std::memory_order order = std::memory_order_relaxed);
+  void amominw(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amomaxw(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amominuw(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+  void amomaxuw(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+
+  // ==== RV64A ====
+#if XLEN >= 64
+  void lrd(Register rd,
+           Address addr,
+           std::memory_order order = std::memory_order_relaxed);
+  void scd(Register rd,
+           Register rs2,
+           Address addr,
+           std::memory_order order = std::memory_order_relaxed);
+  void amoswapd(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+  void amoaddd(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoxord(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoandd(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amoord(Register rd,
+              Register rs2,
+              Address addr,
+              std::memory_order order = std::memory_order_relaxed);
+  void amomind(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amomaxd(Register rd,
+               Register rs2,
+               Address addr,
+               std::memory_order order = std::memory_order_relaxed);
+  void amominud(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+  void amomaxud(Register rd,
+                Register rs2,
+                Address addr,
+                std::memory_order order = std::memory_order_relaxed);
+#endif  // XLEN >= 64
+
+#if XLEN == 32
+  void lr(Register rd,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    lrw(rd, addr, order);
+  }
+  void sc(Register rd,
+          Register rs2,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    scw(rd, rs2, addr, order);
+  }
+#elif XLEN == 64
+  void lr(Register rd,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    lrd(rd, addr, order);
+  }
+  void sc(Register rd,
+          Register rs2,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    scd(rd, rs2, addr, order);
+  }
+#elif XLEN == 128
+  void lr(Register rd,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    lrq(rd, addr, order);
+  }
+  void sc(Register rd,
+          Register rs2,
+          Address addr,
+          std::memory_order order = std::memory_order_relaxed) {
+    scq(rd, rs2, addr, order);
+  }
+#endif
+
+  // ==== RV32F ====
+  void flw(FRegister rd, Address addr);
+  void fsw(FRegister rs2, Address addr);
+  // rd := (rs1 * rs2) + rs3
+  void fmadds(FRegister rd,
+              FRegister rs1,
+              FRegister rs2,
+              FRegister rs3,
+              RoundingMode rounding = RNE);
+  // rd := (rs1 * rs2) - rs3
+  void fmsubs(FRegister rd,
+              FRegister rs1,
+              FRegister rs2,
+              FRegister rs3,
+              RoundingMode rounding = RNE);
+  // rd := -(rs1 * rs2) + rs3
+  void fnmsubs(FRegister rd,
+               FRegister rs1,
+               FRegister rs2,
+               FRegister rs3,
+               RoundingMode rounding = RNE);
+  // rd := -(rs1 * rs2) - rs3
+  void fnmadds(FRegister rd,
+               FRegister rs1,
+               FRegister rs2,
+               FRegister rs3,
+               RoundingMode rounding = RNE);
+  void fadds(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fsubs(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fmuls(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fdivs(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fsqrts(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
+  void fsgnjs(FRegister rd, FRegister rs1, FRegister rs2);
+  void fsgnjns(FRegister rd, FRegister rs1, FRegister rs2);
+  void fsgnjxs(FRegister rd, FRegister rs1, FRegister rs2);
+  void fmins(FRegister rd, FRegister rs1, FRegister rs2);
+  void fmaxs(FRegister rd, FRegister rs1, FRegister rs2);
+  void feqs(Register rd, FRegister rs1, FRegister rs2);
+  void flts(Register rd, FRegister rs1, FRegister rs2);
+  void fles(Register rd, FRegister rs1, FRegister rs2);
+  void fclasss(Register rd, FRegister rs1);
+  // int32_t <- float
+  void fcvtws(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // uint32_t <- float
+  void fcvtwus(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // float <- int32_t
+  void fcvtsw(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+  // float <- uint32_t
+  void fcvtswu(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+
+  void fmvs(FRegister rd, FRegister rs) { fsgnjs(rd, rs, rs); }
+  void fabss(FRegister rd, FRegister rs) { fsgnjxs(rd, rs, rs); }
+  void fnegs(FRegister rd, FRegister rs) { fsgnjns(rd, rs, rs); }
+
+  // xlen <--bit_cast-- float
+  void fmvxw(Register rd, FRegister rs1);
+  // float <--bit_cast-- xlen
+  void fmvwx(FRegister rd, Register rs1);
+
+  // ==== RV64F ====
+#if XLEN >= 64
+  // int64_t <- double
+  void fcvtls(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // uint64_t <- double
+  void fcvtlus(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // double <- int64_t
+  void fcvtsl(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+  // double <- uint64_t
+  void fcvtslu(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+#endif  // XLEN >= 64
+
+  // ==== RV32D ====
+  void fld(FRegister rd, Address addr);
+  void fsd(FRegister rs2, Address addr);
+  // rd := (rs1 * rs2) + rs3
+  void fmaddd(FRegister rd,
+              FRegister rs1,
+              FRegister rs2,
+              FRegister rs3,
+              RoundingMode rounding = RNE);
+  // rd := (rs1 * rs2) - rs3
+  void fmsubd(FRegister rd,
+              FRegister rs1,
+              FRegister rs2,
+              FRegister rs3,
+              RoundingMode rounding = RNE);
+  // rd := -(rs1 * rs2) - rs3
+  void fnmsubd(FRegister rd,
+               FRegister rs1,
+               FRegister rs2,
+               FRegister rs3,
+               RoundingMode rounding = RNE);
+  // rd := -(rs1 * rs2) + rs3
+  void fnmaddd(FRegister rd,
+               FRegister rs1,
+               FRegister rs2,
+               FRegister rs3,
+               RoundingMode rounding = RNE);
+  void faddd(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fsubd(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fmuld(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fdivd(FRegister rd,
+             FRegister rs1,
+             FRegister rs2,
+             RoundingMode rounding = RNE);
+  void fsqrtd(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
+  void fsgnjd(FRegister rd, FRegister rs1, FRegister rs2);
+  void fsgnjnd(FRegister rd, FRegister rs1, FRegister rs2);
+  void fsgnjxd(FRegister rd, FRegister rs1, FRegister rs2);
+  void fmind(FRegister rd, FRegister rs1, FRegister rs2);
+  void fmaxd(FRegister rd, FRegister rs1, FRegister rs2);
+  void fcvtsd(FRegister rd, FRegister rs1, RoundingMode rounding = RNE);
+  void fcvtds(FRegister rd, FRegister rs1);
+  void feqd(Register rd, FRegister rs1, FRegister rs2);
+  void fltd(Register rd, FRegister rs1, FRegister rs2);
+  void fled(Register rd, FRegister rs1, FRegister rs2);
+  void fclassd(Register rd, FRegister rs1);
+  // int32_t <- double
+  void fcvtwd(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // uint32_t <- double
+  void fcvtwud(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // double <- int32_t
+  void fcvtdw(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+  // double <- uint32_t
+  void fcvtdwu(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+
+  void fmvd(FRegister rd, FRegister rs) { fsgnjd(rd, rs, rs); }
+  void fabsd(FRegister rd, FRegister rs) { fsgnjxd(rd, rs, rs); }
+  void fnegd(FRegister rd, FRegister rs) { fsgnjnd(rd, rs, rs); }
+
+  // ==== RV64D ====
+#if XLEN >= 64
+  // int64_t <- double
+  void fcvtld(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // uint64_t <- double
+  void fcvtlud(Register rd, FRegister rs1, RoundingMode rounding = RNE);
+  // xlen <--bit_cast-- double
+  void fmvxd(Register rd, FRegister rs1);
+  // double <- int64_t
+  void fcvtdl(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+  // double <- uint64_t
+  void fcvtdlu(FRegister rd, Register rs1, RoundingMode rounding = RNE);
+  // double <--bit_cast-- xlen
+  void fmvdx(FRegister rd, Register rs1);
+#endif  // XLEN >= 64
+
+  // ==== Dart Simulator Debugging ====
+  void SimulatorPrintObject(Register rs1);
+
+ private:
+  // ==== RV32/64C ====
+  void c_lwsp(Register rd, Address addr);
+#if XLEN == 32
+  void c_flwsp(FRegister rd, Address addr);
+#else
+  void c_ldsp(Register rd, Address addr);
+#endif
+  void c_fldsp(FRegister rd, Address addr);
+
+  void c_swsp(Register rs2, Address addr);
+#if XLEN == 32
+  void c_fswsp(FRegister rs2, Address addr);
+#else
+  void c_sdsp(Register rs2, Address addr);
+#endif
+  void c_fsdsp(FRegister rs2, Address addr);
+
+  void c_lw(Register rd, Address addr);
+  void c_ld(Register rd, Address addr);
+  void c_flw(FRegister rd, Address addr);
+  void c_fld(FRegister rd, Address addr);
+
+  void c_sw(Register rs2, Address addr);
+  void c_sd(Register rs2, Address addr);
+  void c_fsw(FRegister rs2, Address addr);
+  void c_fsd(FRegister rs2, Address addr);
+
+  void c_j(Label* label);
+#if XLEN == 32
+  void c_jal(Label* label);
+#endif
+  void c_jr(Register rs1);
+  void c_jalr(Register rs1);
+
+  void c_beqz(Register rs1p, Label* label);
+  void c_bnez(Register rs1p, Label* label);
+
+  void c_li(Register rd, intptr_t imm);
+  void c_lui(Register rd, uintptr_t imm);
+
+  void c_addi(Register rd, Register rs1, intptr_t imm);
+#if XLEN >= 64
+  void c_addiw(Register rd, Register rs1, intptr_t imm);
+#endif
+  void c_addi16sp(Register rd, Register rs1, intptr_t imm);
+  void c_addi4spn(Register rdp, Register rs1, intptr_t imm);
+
+  void c_slli(Register rd, Register rs1, intptr_t imm);
+  void c_srli(Register rd, Register rs1, intptr_t imm);
+  void c_srai(Register rd, Register rs1, intptr_t imm);
+  void c_andi(Register rd, Register rs1, intptr_t imm);
+
+  void c_mv(Register rd, Register rs2);
+
+  void c_add(Register rd, Register rs1, Register rs2);
+  void c_and(Register rd, Register rs1, Register rs2);
+  void c_or(Register rd, Register rs1, Register rs2);
+  void c_xor(Register rd, Register rs1, Register rs2);
+  void c_sub(Register rd, Register rs1, Register rs2);
+#if XLEN >= 64
+  void c_addw(Register rd, Register rs1, Register rs2);
+  void c_subw(Register rd, Register rs1, Register rs2);
+#endif
+
+  void c_nop();
+  void c_ebreak();
+
+ protected:
+  intptr_t UpdateCBOffset(intptr_t branch_position, intptr_t new_offset);
+  intptr_t UpdateCJOffset(intptr_t branch_position, intptr_t new_offset);
+  intptr_t UpdateBOffset(intptr_t branch_position, intptr_t new_offset);
+  intptr_t UpdateJOffset(intptr_t branch_position, intptr_t new_offset);
+  intptr_t UpdateFarOffset(intptr_t branch_position, intptr_t new_offset);
+
+  intptr_t Position() { return buffer_.Size(); }
+  void EmitBranch(Register rs1,
+                  Register rs2,
+                  Label* label,
+                  Funct3 func,
+                  JumpDistance distance);
+  void EmitJump(Register rd, Label* label, Opcode op, JumpDistance distance);
+  void EmitCBranch(Register rs1p, Label* label, COpcode op);
+  void EmitCJump(Label* label, COpcode op);
+
+  void EmitRType(Funct5 funct5,
+                 std::memory_order order,
+                 Register rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 Register rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 Register rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 Register rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 FRegister rs1,
+                 Funct3 funct3,
+                 FRegister rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 FRegister rs1,
+                 RoundingMode round,
+                 FRegister rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 Register rs1,
+                 RoundingMode round,
+                 FRegister rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 FRegister rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 FRegister rs1,
+                 Funct3 funct3,
+                 Register rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 FRegister rs2,
+                 FRegister rs1,
+                 RoundingMode round,
+                 Register rd,
+                 Opcode opcode);
+  void EmitRType(Funct7 funct7,
+                 intptr_t shamt,
+                 Register rs1,
+                 Funct3 funct3,
+                 Register rd,
+                 Opcode opcode);
+
+  void EmitR4Type(FRegister rs3,
+                  Funct2 funct2,
+                  FRegister rs2,
+                  FRegister rs1,
+                  RoundingMode round,
+                  FRegister rd,
+                  Opcode opcode);
+
+  void EmitIType(intptr_t imm,
+                 Register rs1,
+                 Funct3 funct3,
+                 Register rd,
+                 Opcode opcode);
+  void EmitIType(intptr_t imm,
+                 Register rs1,
+                 Funct3 funct3,
+                 FRegister rd,
+                 Opcode opcode);
+
+  void EmitSType(intptr_t imm,
+                 Register rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 Opcode opcode);
+  void EmitSType(intptr_t imm,
+                 FRegister rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 Opcode opcode);
+
+  void EmitBType(intptr_t imm,
+                 Register rs2,
+                 Register rs1,
+                 Funct3 funct3,
+                 Opcode opcode);
+
+  void EmitUType(intptr_t imm, Register rd, Opcode opcode);
+
+  void EmitJType(intptr_t imm, Register rd, Opcode opcode);
+
+  uint16_t Read16(intptr_t position) {
+    return buffer_.Load<uint16_t>(position);
+  }
+  void Write16(intptr_t position, uint16_t instruction) {
+    return buffer_.Store<uint16_t>(position, instruction);
+  }
+  void Emit16(uint16_t instruction) {
+    AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+    buffer_.Emit<uint16_t>(instruction);
+  }
+  uint32_t Read32(intptr_t position) {
+    return buffer_.Load<uint32_t>(position);
+  }
+  void Write32(intptr_t position, uint32_t instruction) {
+    return buffer_.Store<uint32_t>(position, instruction);
+  }
+
+ public:
+  void Emit32(uint32_t instruction) {
+    AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+    buffer_.Emit<uint32_t>(instruction);
+  }
+  void Emit64(uint64_t instruction) {
+    AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+    buffer_.Emit<uint64_t>(instruction);
+  }
+
+ protected:
+  ExtensionSet extensions_;
+  intptr_t far_branch_level_;
+};
+
+class Assembler : public MicroAssembler {
+ public:
+  explicit Assembler(ObjectPoolBuilder* object_pool_builder,
+                     intptr_t far_branch_level = 0);
+  ~Assembler() {}
+
+  void PushRegister(Register r);
+  void PopRegister(Register r);
+
+  void PushRegisterPair(Register r0, Register r1);
+  void PopRegisterPair(Register r0, Register r1);
+
+  void PushRegisters(const RegisterSet& registers);
+  void PopRegisters(const RegisterSet& registers);
+
+  // Push all registers which are callee-saved according to the ARM64 ABI.
+  void PushNativeCalleeSavedRegisters();
+
+  // Pop all registers which are callee-saved according to the ARM64 ABI.
+  void PopNativeCalleeSavedRegisters();
+
+  void ExtendValue(Register rd, Register rn, OperandSize sz) override;
+  void ExtendAndSmiTagValue(Register rd,
+                            Register rn,
+                            OperandSize sz = kWordBytes) override;
+
+  void Drop(intptr_t stack_elements) {
+    ASSERT(stack_elements >= 0);
+    if (stack_elements > 0) {
+      AddImmediate(SP, SP, stack_elements * target::kWordSize);
+    }
+  }
+
+  void Bind(Label* label) { MicroAssembler::Bind(label); }
+  // Unconditional jump to a given label.
+  void Jump(Label* label, JumpDistance distance = kFarJump) {
+    j(label, distance);
+  }
+  // Unconditional jump to a given address in memory. Clobbers TMP.
+  void Jump(const Address& address);
+
+  void LoadField(Register dst, const FieldAddress& address) override;
+  void LoadCompressedField(Register dst, const FieldAddress& address) override {
+    LoadCompressed(dst, address);
+  }
+  void LoadMemoryValue(Register dst, Register base, int32_t offset) {
+    LoadFromOffset(dst, base, offset, kWordBytes);
+  }
+  void StoreMemoryValue(Register src, Register base, int32_t offset) {
+    StoreToOffset(src, base, offset, kWordBytes);
+  }
+
+#if defined(USING_THREAD_SANITIZER)
+  void TsanLoadAcquire(Register addr);
+  void TsanStoreRelease(Register addr);
+#endif
+
+  void LoadAcquire(Register dst, Register address, int32_t offset = 0);
+
+  void LoadAcquireCompressed(Register dst,
+                             Register address,
+                             int32_t offset = 0);
+
+  void StoreRelease(Register src,
+                    Register address,
+                    int32_t offset = 0) override;
+
+  void StoreReleaseCompressed(Register src,
+                              Register address,
+                              int32_t offset = 0);
+
+  void CompareWithFieldValue(Register value, FieldAddress address) {
+    CompareWithMemoryValue(value, address);
+  }
+  void CompareWithCompressedFieldFromOffset(Register value,
+                                            Register base,
+                                            int32_t offset);
+
+  void CompareWithMemoryValue(Register value,
+                              Address address,
+                              OperandSize sz = kWordBytes);
+
+  void CompareFunctionTypeNullabilityWith(Register type, int8_t value) override;
+  void CompareTypeNullabilityWith(Register type, int8_t value) override;
+
+  // Debugging and bringup support.
+  void Breakpoint() override { trap(); }
+
+  void SetPrologueOffset() {
+    if (prologue_offset_ == -1) {
+      prologue_offset_ = CodeSize();
+    }
+  }
+
+  void ReserveAlignedFrameSpace(intptr_t frame_space);
+
+  // In debug mode, this generates code to check that:
+  //   FP + kExitLinkSlotFromEntryFp == SP
+  // or triggers breakpoint otherwise.
+  void EmitEntryFrameVerification();
+
+  // Instruction pattern from entrypoint is used in Dart frame prologs
+  // to set up the frame and save a PC which can be used to figure out the
+  // RawInstruction object corresponding to the code running in the frame.
+  static const intptr_t kEntryPointToPcMarkerOffset = 0;
+  static intptr_t EntryPointToPcMarkerOffset() {
+    return kEntryPointToPcMarkerOffset;
+  }
+
+  // On some other platforms, we draw a distinction between safe and unsafe
+  // smis.
+  static bool IsSafe(const Object& object) { return true; }
+  static bool IsSafeSmi(const Object& object) { return target::IsSmi(object); }
+
+  void CompareRegisters(Register rn, Register rm);
+  void CompareObjectRegisters(Register rn, Register rm);
+  void TestRegisters(Register rn, Register rm);
+
+  // Branches to the given label if the condition holds.
+  void BranchIf(Condition condition,
+                Label* label,
+                JumpDistance distance = kFarJump);
+  void BranchIfZero(Register rn,
+                    Label* label,
+                    JumpDistance distance = kFarJump);
+  void SetIf(Condition condition, Register rd);
+
+  void SmiUntag(Register reg) { SmiUntag(reg, reg); }
+  void SmiUntag(Register dst, Register src) { srai(dst, src, kSmiTagSize); }
+  void SmiTag(Register reg) override { SmiTag(reg, reg); }
+  void SmiTag(Register dst, Register src) { slli(dst, src, kSmiTagSize); }
+
+  void BranchIfNotSmi(Register reg,
+                      Label* label,
+                      JumpDistance distance = kFarJump);
+  void BranchIfSmi(Register reg,
+                   Label* label,
+                   JumpDistance distance = kFarJump);
+
+  void Jump(const Code& code,
+            Register pp,
+            ObjectPoolBuilderEntry::Patchability patchable =
+                ObjectPoolBuilderEntry::kNotPatchable);
+
+  void JumpAndLink(const Code& code,
+                   ObjectPoolBuilderEntry::Patchability patchable =
+                       ObjectPoolBuilderEntry::kNotPatchable,
+                   CodeEntryKind entry_kind = CodeEntryKind::kNormal);
+
+  void JumpAndLinkPatchable(const Code& code,
+                            CodeEntryKind entry_kind = CodeEntryKind::kNormal) {
+    JumpAndLink(code, ObjectPoolBuilderEntry::kPatchable, entry_kind);
+  }
+  void JumpAndLinkToRuntime();
+
+  // Emit a call that shares its object pool entries with other calls
+  // that have the same equivalence marker.
+  void JumpAndLinkWithEquivalence(
+      const Code& code,
+      const Object& equivalence,
+      CodeEntryKind entry_kind = CodeEntryKind::kNormal);
+
+  void Call(Address target);
+  void Call(const Code& code) { JumpAndLink(code); }
+
+  void CallCFunction(Address target) { Call(target); }
+
+  void AddImmediate(Register dest, intx_t imm) {
+    AddImmediate(dest, dest, imm);
+  }
+
+  // Macros accepting a pp Register argument may attempt to load values from
+  // the object pool when possible. Unless you are sure that the untagged object
+  // pool pointer is in another register, or that it is not available at all,
+  // PP should be passed for pp. `dest` can be TMP2, `rn` cannot. `dest` can be
+  // TMP.
+  void AddImmediate(Register dest,
+                    Register rn,
+                    intx_t imm,
+                    OperandSize sz = kWordBytes);
+  void AndImmediate(Register rd,
+                    Register rn,
+                    intx_t imm,
+                    OperandSize sz = kWordBytes);
+  void OrImmediate(Register rd,
+                   Register rn,
+                   intx_t imm,
+                   OperandSize sz = kWordBytes);
+  void XorImmediate(Register rd,
+                    Register rn,
+                    intx_t imm,
+                    OperandSize sz = kWordBytes);
+  void TestImmediate(Register rn, intx_t imm, OperandSize sz = kWordBytes);
+  void CompareImmediate(Register rn, intx_t imm, OperandSize sz = kWordBytes);
+
+  void LoadFromOffset(Register dest,
+                      const Address& address,
+                      OperandSize sz = kWordBytes) override;
+  void LoadFromOffset(Register dest,
+                      Register base,
+                      int32_t offset,
+                      OperandSize sz = kWordBytes);
+  void LoadFieldFromOffset(Register dest,
+                           Register base,
+                           int32_t offset,
+                           OperandSize sz = kWordBytes) override {
+    LoadFromOffset(dest, base, offset - kHeapObjectTag, sz);
+  }
+  void LoadCompressedFieldFromOffset(Register dest,
+                                     Register base,
+                                     int32_t offset) override {
+    LoadCompressedFromOffset(dest, base, offset - kHeapObjectTag);
+  }
+  void LoadCompressedSmiFieldFromOffset(Register dest,
+                                        Register base,
+                                        int32_t offset) {
+    LoadCompressedSmiFromOffset(dest, base, offset - kHeapObjectTag);
+  }
+  // For loading indexed payloads out of tagged objects like Arrays. If the
+  // payload objects are word-sized, use TIMES_HALF_WORD_SIZE if the contents of
+  // [index] is a Smi, otherwise TIMES_WORD_SIZE if unboxed.
+  void LoadIndexedPayload(Register dest,
+                          Register base,
+                          int32_t payload_offset,
+                          Register index,
+                          ScaleFactor scale,
+                          OperandSize sz = kWordBytes);
+  void LoadIndexedCompressed(Register dest,
+                             Register base,
+                             int32_t offset,
+                             Register index);
+  void LoadSFromOffset(FRegister dest, Register base, int32_t offset);
+  void LoadDFromOffset(FRegister dest, Register base, int32_t offset);
+  void LoadDFieldFromOffset(FRegister dest, Register base, int32_t offset) {
+    LoadDFromOffset(dest, base, offset - kHeapObjectTag);
+  }
+
+  void LoadFromStack(Register dst, intptr_t depth);
+  void StoreToStack(Register src, intptr_t depth);
+  void CompareToStack(Register src, intptr_t depth);
+
+  void StoreToOffset(Register src,
+                     const Address& address,
+                     OperandSize sz = kWordBytes) override;
+  void StoreToOffset(Register src,
+                     Register base,
+                     int32_t offset,
+                     OperandSize sz = kWordBytes);
+  void StoreFieldToOffset(Register src,
+                          Register base,
+                          int32_t offset,
+                          OperandSize sz = kWordBytes) {
+    StoreToOffset(src, base, offset - kHeapObjectTag, sz);
+  }
+  void StoreSToOffset(FRegister src, Register base, int32_t offset);
+  void StoreDToOffset(FRegister src, Register base, int32_t offset);
+  void StoreDFieldToOffset(FRegister src, Register base, int32_t offset) {
+    StoreDToOffset(src, base, offset - kHeapObjectTag);
+  }
+
+  void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset);
+  void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset);
+  void MoveUnboxedDouble(FpuRegister dst, FpuRegister src);
+
+  void LoadCompressed(Register dest, const Address& slot);
+  void LoadCompressedFromOffset(Register dest, Register base, int32_t offset);
+  void LoadCompressedSmi(Register dest, const Address& slot);
+  void LoadCompressedSmiFromOffset(Register dest,
+                                   Register base,
+                                   int32_t offset);
+
+  // Store into a heap object and apply the generational and incremental write
+  // barriers. All stores into heap objects must pass through this function or,
+  // if the value can be proven either Smi or old-and-premarked, its NoBarrier
+  // variants.
+  // Preserves object and value registers.
+  void StoreIntoObject(Register object,
+                       const Address& dest,
+                       Register value,
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi,
+                       MemoryOrder memory_order = kRelaxedNonAtomic) override;
+  void StoreCompressedIntoObject(
+      Register object,
+      const Address& dest,
+      Register value,
+      CanBeSmi can_value_be_smi = kValueCanBeSmi,
+      MemoryOrder memory_order = kRelaxedNonAtomic) override;
+  void StoreBarrier(Register object, Register value, CanBeSmi can_value_be_smi);
+  void StoreIntoArray(Register object,
+                      Register slot,
+                      Register value,
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi);
+  void StoreCompressedIntoArray(Register object,
+                                Register slot,
+                                Register value,
+                                CanBeSmi can_value_be_smi = kValueCanBeSmi);
+  void StoreIntoArrayBarrier(Register object,
+                             Register slot,
+                             Register value,
+                             CanBeSmi can_value_be_smi);
+
+  void StoreIntoObjectOffset(Register object,
+                             int32_t offset,
+                             Register value,
+                             CanBeSmi can_value_be_smi = kValueCanBeSmi,
+                             MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreCompressedIntoObjectOffset(
+      Register object,
+      int32_t offset,
+      Register value,
+      CanBeSmi can_value_be_smi = kValueCanBeSmi,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreIntoObjectNoBarrier(
+      Register object,
+      const Address& dest,
+      Register value,
+      MemoryOrder memory_order = kRelaxedNonAtomic) override;
+  void StoreCompressedIntoObjectNoBarrier(
+      Register object,
+      const Address& dest,
+      Register value,
+      MemoryOrder memory_order = kRelaxedNonAtomic) override;
+  void StoreIntoObjectOffsetNoBarrier(
+      Register object,
+      int32_t offset,
+      Register value,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreCompressedIntoObjectOffsetNoBarrier(
+      Register object,
+      int32_t offset,
+      Register value,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreIntoObjectNoBarrier(Register object,
+                                const Address& dest,
+                                const Object& value);
+  void StoreCompressedIntoObjectNoBarrier(
+      Register object,
+      const Address& dest,
+      const Object& value,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreIntoObjectOffsetNoBarrier(
+      Register object,
+      int32_t offset,
+      const Object& value,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+  void StoreCompressedIntoObjectOffsetNoBarrier(
+      Register object,
+      int32_t offset,
+      const Object& value,
+      MemoryOrder memory_order = kRelaxedNonAtomic);
+
+  // Stores a non-tagged value into a heap object.
+  void StoreInternalPointer(Register object,
+                            const Address& dest,
+                            Register value);
+
+  // Object pool, loading from pool, etc.
+  void LoadPoolPointer(Register pp = PP);
+
+  bool constant_pool_allowed() const { return constant_pool_allowed_; }
+  void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; }
+
+  intptr_t FindImmediate(int64_t imm);
+  bool CanLoadFromObjectPool(const Object& object) const;
+  void LoadNativeEntry(Register dst,
+                       const ExternalLabel* label,
+                       ObjectPoolBuilderEntry::Patchability patchable);
+  void LoadIsolate(Register dst);
+  void LoadIsolateGroup(Register dst);
+
+  // Note: the function never clobbers TMP, TMP2 scratch registers.
+  void LoadObject(Register dst, const Object& obj) {
+    LoadObjectHelper(dst, obj, false);
+  }
+  // Note: the function never clobbers TMP, TMP2 scratch registers.
+  void LoadUniqueObject(Register dst, const Object& obj) {
+    LoadObjectHelper(dst, obj, true);
+  }
+  // Note: the function never clobbers TMP, TMP2 scratch registers.
+  void LoadImmediate(Register reg, intx_t imm);
+
+  void LoadDImmediate(FRegister reg, double immd);
+
+  // Load word from pool from the given offset using encoding that
+  // InstructionPattern::DecodeLoadWordFromPool can decode.
+  //
+  // Note: the function never clobbers TMP, TMP2 scratch registers.
+  void LoadWordFromPoolIndex(Register dst, intptr_t index, Register pp = PP);
+
+  void PushObject(const Object& object) {
+    if (IsSameObject(compiler::NullObject(), object)) {
+      PushRegister(NULL_REG);
+    } else if (target::IsSmi(object) && (target::ToRawSmi(object) == 0)) {
+      PushRegister(ZR);
+    } else {
+      LoadObject(TMP, object);
+      PushRegister(TMP);
+    }
+  }
+  void PushImmediate(int64_t immediate) {
+    if (immediate == 0) {
+      PushRegister(ZR);
+    } else {
+      LoadImmediate(TMP, immediate);
+      PushRegister(TMP);
+    }
+  }
+  void CompareObject(Register reg, const Object& object);
+
+  void ExtractClassIdFromTags(Register result, Register tags);
+  void ExtractInstanceSizeFromTags(Register result, Register tags);
+
+  void LoadClassId(Register result, Register object);
+  void LoadClassById(Register result, Register class_id);
+  void CompareClassId(Register object,
+                      intptr_t class_id,
+                      Register scratch = kNoRegister);
+  // Note: input and output registers must be different.
+  void LoadClassIdMayBeSmi(Register result, Register object);
+  void LoadTaggedClassIdMayBeSmi(Register result, Register object);
+  void EnsureHasClassIdInDEBUG(intptr_t cid,
+                               Register src,
+                               Register scratch,
+                               bool can_be_null = false) override;
+
+  void EnterFrame(intptr_t frame_size);
+  void LeaveFrame();
+  void Ret() { ret(); }
+
+  // Emit code to transition between generated mode and native mode.
+  //
+  // These require and ensure that CSP and SP are equal and aligned and require
+  // a scratch register (in addition to TMP/TMP2).
+
+  void TransitionGeneratedToNative(Register destination_address,
+                                   Register new_exit_frame,
+                                   Register new_exit_through_ffi,
+                                   bool enter_safepoint);
+  void TransitionNativeToGenerated(Register scratch, bool exit_safepoint);
+  void EnterFullSafepoint(Register scratch);
+  void ExitFullSafepoint(Register scratch);
+
+  void CheckCodePointer();
+  void RestoreCodePointer();
+
+  // Restores the values of the registers that are blocked to cache some values
+  // e.g. BARRIER_MASK and NULL_REG.
+  void RestorePinnedRegisters();
+
+  void SetupGlobalPoolAndDispatchTable();
+
+  void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
+  void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
+  void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
+
+  void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
+
+  // Helper method for performing runtime calls from callers requiring manual
+  // register preservation is required (e.g. outside IL instructions marked
+  // as calling).
+  class CallRuntimeScope : public ValueObject {
+   public:
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     bool preserve_registers = true)
+        : CallRuntimeScope(assembler,
+                           entry,
+                           frame_size,
+                           preserve_registers,
+                           /*caller=*/nullptr) {}
+
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     Address caller,
+                     bool preserve_registers = true)
+        : CallRuntimeScope(assembler,
+                           entry,
+                           frame_size,
+                           preserve_registers,
+                           &caller) {}
+
+    void Call(intptr_t argument_count);
+
+    ~CallRuntimeScope();
+
+   private:
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     bool preserve_registers,
+                     const Address* caller);
+
+    Assembler* const assembler_;
+    const RuntimeEntry& entry_;
+    const bool preserve_registers_;
+    const bool restore_code_reg_;
+  };
+
+  // Set up a stub frame so that the stack traversal code can easily identify
+  // a stub frame.
+  void EnterStubFrame() { EnterDartFrame(0); }
+  void LeaveStubFrame() { LeaveDartFrame(); }
+
+  // Set up a frame for calling a C function.
+  // Automatically save the pinned registers in Dart which are not callee-
+  // saved in the native calling convention.
+  // Use together with CallCFunction.
+  void EnterCFrame(intptr_t frame_space);
+  void LeaveCFrame();
+
+  void MonomorphicCheckedEntryJIT();
+  void MonomorphicCheckedEntryAOT();
+  void BranchOnMonomorphicCheckedEntryJIT(Label* label);
+
+  // If allocation tracing for |cid| is enabled, will jump to |trace| label,
+  // which will allocate in the runtime where tracing occurs.
+  void MaybeTraceAllocation(intptr_t cid, Register temp_reg, Label* trace);
+
+  void TryAllocateObject(intptr_t cid,
+                         intptr_t instance_size,
+                         Label* failure,
+                         JumpDistance distance,
+                         Register instance_reg,
+                         Register temp_reg) override;
+
+  void TryAllocateArray(intptr_t cid,
+                        intptr_t instance_size,
+                        Label* failure,
+                        Register instance,
+                        Register end_address,
+                        Register temp1,
+                        Register temp2);
+
+  // This emits an PC-relative call of the form "bl <offset>".  The offset
+  // is not yet known and needs therefore relocation to the right place before
+  // the code can be used.
+  //
+  // The neccessary information for the "linker" (i.e. the relocation
+  // information) is stored in [UntaggedCode::static_calls_target_table_]: an
+  // entry of the form
+  //
+  //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
+  //
+  // will be used during relocation to fix the offset.
+  //
+  // The provided [offset_into_target] will be added to calculate the final
+  // destination.  It can be used e.g. for calling into the middle of a
+  // function.
+  void GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target = 0);
+
+  // This emits an PC-relative tail call of the form "b <offset>".
+  //
+  // See also above for the pc-relative call.
+  void GenerateUnRelocatedPcRelativeTailCall(intptr_t offset_into_target = 0);
+
+  Address ElementAddressForIntIndex(bool is_external,
+                                    intptr_t cid,
+                                    intptr_t index_scale,
+                                    Register array,
+                                    intptr_t index) const;
+  void ComputeElementAddressForIntIndex(Register address,
+                                        bool is_external,
+                                        intptr_t cid,
+                                        intptr_t index_scale,
+                                        Register array,
+                                        intptr_t index);
+  Address ElementAddressForRegIndex(bool is_external,
+                                    intptr_t cid,
+                                    intptr_t index_scale,
+                                    bool index_unboxed,
+                                    Register array,
+                                    Register index,
+                                    Register temp);
+
+  // Special version of ElementAddressForRegIndex for the case when cid and
+  // operand size for the target load don't match (e.g. when loading a few
+  // elements of the array with one load).
+  Address ElementAddressForRegIndexWithSize(bool is_external,
+                                            intptr_t cid,
+                                            OperandSize size,
+                                            intptr_t index_scale,
+                                            bool index_unboxed,
+                                            Register array,
+                                            Register index,
+                                            Register temp);
+
+  void ComputeElementAddressForRegIndex(Register address,
+                                        bool is_external,
+                                        intptr_t cid,
+                                        intptr_t index_scale,
+                                        bool index_unboxed,
+                                        Register array,
+                                        Register index);
+
+  void LoadStaticFieldAddress(Register address,
+                              Register field,
+                              Register scratch);
+
+  void LoadCompressedFieldAddressForRegOffset(Register address,
+                                              Register instance,
+                                              Register offset_in_words_as_smi);
+
+  void LoadFieldAddressForRegOffset(Register address,
+                                    Register instance,
+                                    Register offset_in_words_as_smi);
+
+  // Returns object data offset for address calculation; for heap objects also
+  // accounts for the tag.
+  static int32_t HeapDataOffset(bool is_external, intptr_t cid) {
+    return is_external
+               ? 0
+               : (target::Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  }
+
+  void AddImmediateBranchOverflow(Register rd,
+                                  Register rs1,
+                                  intx_t imm,
+                                  Label* overflow);
+  void SubtractImmediateBranchOverflow(Register rd,
+                                       Register rs1,
+                                       intx_t imm,
+                                       Label* overflow);
+  void MultiplyImmediateBranchOverflow(Register rd,
+                                       Register rs1,
+                                       intx_t imm,
+                                       Label* overflow);
+  void AddBranchOverflow(Register rd,
+                         Register rs1,
+                         Register rs2,
+                         Label* overflow);
+  void SubtractBranchOverflow(Register rd,
+                              Register rs1,
+                              Register rs2,
+                              Label* overflow);
+  void MultiplyBranchOverflow(Register rd,
+                              Register rs1,
+                              Register rs2,
+                              Label* overflow);
+
+ private:
+  bool constant_pool_allowed_;
+
+  enum DeferredCompareType {
+    kNone,
+    kCompareReg,
+    kCompareImm,
+    kTestReg,
+    kTestImm,
+  };
+  DeferredCompareType deferred_compare_ = kNone;
+  Register deferred_left_ = kNoRegister;
+  Register deferred_reg_ = kNoRegister;
+  intptr_t deferred_imm_ = 0;
+
+  // Note: the function never clobbers TMP, TMP2 scratch registers.
+  void LoadObjectHelper(Register dst, const Object& obj, bool is_unique);
+
+  enum BarrierFilterMode {
+    // Filter falls through into the barrier update code. Target label
+    // is a "after-store" label.
+    kJumpToNoUpdate,
+
+    // Filter falls through to the "after-store" code. Target label
+    // is barrier update code label.
+    kJumpToBarrier,
+  };
+
+  void StoreIntoObjectFilter(Register object,
+                             Register value,
+                             Label* label,
+                             CanBeSmi can_be_smi,
+                             BarrierFilterMode barrier_filter_mode);
+
+  // Note: leaf call sequence uses some abi callee save registers as scratch
+  // so they should be manually preserved.
+  void EnterCallRuntimeFrame(intptr_t frame_size, bool is_leaf);
+  void LeaveCallRuntimeFrame(bool is_leaf);
+
+  friend class dart::FlowGraphCompiler;
+  std::function<void(Register reg)> generate_invoke_write_barrier_wrapper_;
+  std::function<void()> generate_invoke_array_write_barrier_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(Assembler);
+};
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_RISCV_H_
diff --git a/runtime/vm/compiler/assembler/assembler_riscv_test.cc b/runtime/vm/compiler/assembler/assembler_riscv_test.cc
new file mode 100644
index 0000000..b596017
--- /dev/null
+++ b/runtime/vm/compiler/assembler/assembler_riscv_test.cc
@@ -0,0 +1,6513 @@
+// 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.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/cpu.h"
+#include "vm/os.h"
+#include "vm/unit_test.h"
+#include "vm/virtual_memory.h"
+
+namespace dart {
+namespace compiler {
+#define __ assembler->
+
+#if defined(PRODUCT)
+#define EXPECT_DISASSEMBLY(expected)
+#else
+#define EXPECT_DISASSEMBLY(expected)                                           \
+  EXPECT_STREQ(expected, test->RelativeDisassembly())
+#endif
+
+// Called from assembler_test.cc.
+// RA: return address.
+// A0: value.
+// A1: growable array.
+// A2: current thread.
+ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
+  __ PushRegister(RA);
+  __ PushNativeCalleeSavedRegisters();
+
+  __ mv(THR, A2);
+  __ lx(WRITE_BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+
+  __ StoreIntoObject(A1, FieldAddress(A1, GrowableObjectArray::data_offset()),
+                     A0);
+
+  __ PopNativeCalleeSavedRegisters();
+  __ PopRegister(RA);
+  __ ret();
+}
+
+static intx_t Call(intx_t entry,
+                   intx_t arg0 = 0,
+                   intx_t arg1 = 0,
+                   intx_t arg2 = 0,
+                   intx_t arg3 = 0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->Call(entry, arg0, arg1, arg2, arg3);
+#else
+  typedef intx_t (*F)(intx_t, intx_t, intx_t, intx_t);
+  return reinterpret_cast<F>(entry)(arg0, arg1, arg2, arg3);
+#endif
+}
+static float CallF(intx_t entry, intx_t arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0);
+#else
+  typedef float (*F)(intx_t);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static float CallF(intx_t entry, intx_t arg0, float arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0, arg1);
+#else
+  typedef float (*F)(intx_t, float);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+static float CallF(intx_t entry, double arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0);
+#else
+  typedef float (*F)(double);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static float CallF(intx_t entry, float arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0);
+#else
+  typedef float (*F)(float);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static float CallF(intx_t entry, float arg0, float arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0, arg1);
+#else
+  typedef float (*F)(float, float);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+static float CallF(intx_t entry, float arg0, float arg1, float arg2) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallF(entry, arg0, arg1, arg2);
+#else
+  typedef float (*F)(float, float, float);
+  return reinterpret_cast<F>(entry)(arg0, arg1, arg2);
+#endif
+}
+static intx_t CallI(intx_t entry, float arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallI(entry, arg0);
+#else
+  typedef intx_t (*F)(float);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static intx_t CallI(intx_t entry, float arg0, float arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallI(entry, arg0, arg1);
+#else
+  typedef intx_t (*F)(float, float);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+static double CallD(intx_t entry, intx_t arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0);
+#else
+  typedef double (*F)(intx_t);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static double CallD(intx_t entry, intx_t arg0, double arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0, arg1);
+#else
+  typedef double (*F)(intx_t, double);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+static double CallD(intx_t entry, float arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0);
+#else
+  typedef double (*F)(float);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static double CallD(intx_t entry, double arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0);
+#else
+  typedef double (*F)(double);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static double CallD(intx_t entry, double arg0, double arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0, arg1);
+#else
+  typedef double (*F)(double, double);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+static double CallD(intx_t entry, double arg0, double arg1, double arg2) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallD(entry, arg0, arg1, arg2);
+#else
+  typedef double (*F)(double, double, double);
+  return reinterpret_cast<F>(entry)(arg0, arg1, arg2);
+#endif
+}
+static intx_t CallI(intx_t entry, double arg0) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallI(entry, arg0);
+#else
+  typedef intx_t (*F)(double);
+  return reinterpret_cast<F>(entry)(arg0);
+#endif
+}
+static intx_t CallI(intx_t entry, double arg0, double arg1) {
+#if defined(USING_SIMULATOR)
+  return Simulator::Current()->CallI(entry, arg0, arg1);
+#else
+  typedef intx_t (*F)(double, double);
+  return reinterpret_cast<F>(entry)(arg0, arg1);
+#endif
+}
+
+ASSEMBLER_TEST_GENERATE(LoadUpperImmediate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  __ lui(A0, 42 << 16);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadUpperImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "002a0537 lui a0, 2752512\n"
+      "00008067 ret\n");
+  EXPECT_EQ(42 << 16, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(AddUpperImmediatePC, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  __ auipc(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddUpperImmediatePC, test) {
+  EXPECT_DISASSEMBLY(
+      "00000517 auipc a0, 0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(test->entry(), static_cast<uintx_t>(Call(test->entry())));
+}
+
+ASSEMBLER_TEST_GENERATE(JumpAndLink, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label1, label2;
+  __ jal(T4, &label1);  // Forward.
+  __ sub(A0, T0, T1);
+  __ ret();
+  __ trap();
+
+  __ Bind(&label2);
+  __ li(T1, 7);
+  __ jalr(ZR, T5);
+  __ trap();
+
+  __ Bind(&label1);
+  __ li(T0, 4);
+  __ jal(T5, &label2);  // Backward.
+  __ jalr(ZR, T4);
+  __ trap();
+}
+ASSEMBLER_TEST_RUN(JumpAndLink, test) {
+  EXPECT_DISASSEMBLY(
+      "01c00eef jal t4, +28\n"
+      "40628533 sub a0, t0, t1\n"
+      "00008067 ret\n"
+      "00000000 trap\n"
+      "00700313 li t1, 7\n"
+      "000f0067 jr t5\n"
+      "00000000 trap\n"
+      "00400293 li t0, 4\n"
+      "ff1fff6f jal t5, -16\n"
+      "000e8067 jr t4\n"
+      "00000000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Jump, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label1, label2;
+  __ j(&label1);  // Forward.
+  __ trap();
+  __ Bind(&label2);
+  __ li(T1, 7);
+  __ sub(A0, T0, T1);
+  __ ret();
+  __ Bind(&label1);
+  __ li(T0, 4);
+  __ j(&label2);  // Backward.
+  __ trap();
+}
+ASSEMBLER_TEST_RUN(Jump, test) {
+  EXPECT_DISASSEMBLY(
+      "0140006f j +20\n"
+      "00000000 trap\n"
+      "00700313 li t1, 7\n"
+      "40628533 sub a0, t0, t1\n"
+      "00008067 ret\n"
+      "00400293 li t0, 4\n"
+      "ff1ff06f j -16\n"
+      "00000000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(JumpAndLinkRegister, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  /* 00 */ __ jalr(T4, A1, 28);  // Forward.
+  /* 04 */ __ sub(A0, T0, T1);
+  /* 08 */ __ ret();
+  /* 12 */ __ trap();
+
+  /* 16 */ __ li(T1, 7);
+  /* 20 */ __ jalr(ZR, T5);
+  /* 24 */ __ trap();
+
+  /* 28 */ __ li(T0, 4);
+  /* 32 */ __ jalr(T5, A1, 16);  // Backward.
+  /* 36 */ __ jalr(ZR, T4);
+  /* 40 */ __ trap();
+}
+ASSEMBLER_TEST_RUN(JumpAndLinkRegister, test) {
+  EXPECT_DISASSEMBLY(
+      "01c58ee7 jalr t4, 28(a1)\n"
+      "40628533 sub a0, t0, t1\n"
+      "00008067 ret\n"
+      "00000000 trap\n"
+      "00700313 li t1, 7\n"
+      "000f0067 jr t5\n"
+      "00000000 trap\n"
+      "00400293 li t0, 4\n"
+      "01058f67 jalr t5, 16(a1)\n"
+      "000e8067 jr t4\n"
+      "00000000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry(), 0, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(JumpRegister, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  /* 00 */ __ jr(A1, 20);  // Forward.
+  /* 04 */ __ trap();
+  /* 08 */ __ li(T1, 7);
+  /* 12 */ __ sub(A0, T0, T1);
+  /* 16 */ __ ret();
+  /* 20 */ __ li(T0, 4);
+  /* 24 */ __ jr(A1, 8);  // Backward.
+  /* 28 */ __ trap();
+}
+ASSEMBLER_TEST_RUN(JumpRegister, test) {
+  EXPECT_DISASSEMBLY(
+      "01458067 jr 20(a1)\n"
+      "00000000 trap\n"
+      "00700313 li t1, 7\n"
+      "40628533 sub a0, t0, t1\n"
+      "00008067 ret\n"
+      "00400293 li t0, 4\n"
+      "00858067 jr 8(a1)\n"
+      "00000000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry(), 0, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchEqualForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ beq(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchEqualForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b50663 beq a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchEqualForwardFar, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ beq(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  for (intptr_t i = 0; i < (1 << 13); i++) {
+    __ ebreak();
+  }
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchEqualForwardFar, test) {
+  //  EXPECT_DISASSEMBLY(constant too big);
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchNotEqualForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bne(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchNotEqualForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b51663 bne a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchNotEqualForwardFar, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bne(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  for (intptr_t i = 0; i < (1 << 13); i++) {
+    __ ebreak();
+  }
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchNotEqualForwardFar, test) {
+  //  EXPECT_DISASSEMBLY(constant too big);
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessThanForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ blt(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessThanForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b54663 blt a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessThanForwardFar, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ blt(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  for (intptr_t i = 0; i < (1 << 13); i++) {
+    __ ebreak();
+  }
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessThanForwardFar, test) {
+  //  EXPECT_DISASSEMBLY(constant too big);
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ ble(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessOrEqualForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00a5d663 ble a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForwardFar, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ ble(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  for (intptr_t i = 0; i < (1 << 13); i++) {
+    __ ebreak();
+  }
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessOrEqualForwardFar, test) {
+  //  EXPECT_DISASSEMBLY(constant too big);
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterThanForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bgt(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterThanForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00a5c663 blt a1, a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bge(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterOrEqualForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b55663 ble a1, a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessThanUnsignedForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bltu(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessThanUnsignedForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b56663 bltu a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessOrEqualUnsignedForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bleu(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessOrEqualUnsignedForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00a5f663 bleu a0, a1, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(3, Call(test->entry(), 1, 0));
+  EXPECT_EQ(4, Call(test->entry(), 1, -1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(4, Call(test->entry(), 0, -1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 1));
+  EXPECT_EQ(3, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterThanUnsignedForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bgtu(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterThanUnsignedForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00a5e663 bltu a1, a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(3, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualUnsignedForward, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+
+  Label label;
+  __ bgeu(A0, A1, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterOrEqualUnsignedForward, test) {
+  EXPECT_DISASSEMBLY(
+      "00b57663 bleu a1, a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 1, 1));
+  EXPECT_EQ(4, Call(test->entry(), 1, 0));
+  EXPECT_EQ(3, Call(test->entry(), 1, -1));
+  EXPECT_EQ(3, Call(test->entry(), 0, 1));
+  EXPECT_EQ(4, Call(test->entry(), 0, 0));
+  EXPECT_EQ(3, Call(test->entry(), 0, -1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 1));
+  EXPECT_EQ(4, Call(test->entry(), -1, 0));
+  EXPECT_EQ(4, Call(test->entry(), -1, -1));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByte_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lb(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByte_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00050503 lb a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+  EXPECT_EQ(-51, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+  free(values);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByte_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lb(A0, Address(A0, 1));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByte_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00150503 lb a0, 1(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+
+  EXPECT_EQ(-17, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+  free(values);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByte_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lb(A0, Address(A0, -1));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByte_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "fff50503 lb a0, -1(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+
+  EXPECT_EQ(-85, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+  free(values);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lbu(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByteUnsigned_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00054503 lbu a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+
+  EXPECT_EQ(0xCD, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+  free(values);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lbu(A0, Address(A0, 1));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByteUnsigned_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00154503 lbu a0, 1(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+
+  EXPECT_EQ(0xEF, Call(test->entry(), reinterpret_cast<intx_t>((&values[1]))));
+  free(values);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lbu(A0, Address(A0, -1));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadByteUnsigned_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "fff54503 lbu a0, -1(a0)\n"
+      "00008067 ret\n");
+
+  uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t)));
+  values[0] = 0xAB;
+  values[1] = 0xCD;
+  values[2] = 0xEF;
+
+  EXPECT_EQ(0xAB, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadHalfword_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lh(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfword_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00051503 lh a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(-13054, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadHalfword_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lh(A0, Address(A0, 2));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfword_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00251503 lh a0, 2(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(-4349, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadHalfword_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lh(A0, Address(A0, -2));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfword_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "ffe51503 lh a0, -2(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(-21759, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lhu(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00055503 lhu a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(0xCD02, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lhu(A0, Address(A0, 2));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00255503 lhu a0, 2(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(0xEF03, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lhu(A0, Address(A0, -2));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "ffe55503 lhu a0, -2(a0)\n"
+      "00008067 ret\n");
+
+  uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t)));
+  values[0] = 0xAB01;
+  values[1] = 0xCD02;
+  values[2] = 0xEF03;
+
+  EXPECT_EQ(0xAB01, Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadWord_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lw(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00052503 lw a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(-855505915,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lw(A0, Address(A0, 4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00452503 lw a0, 4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(-285014521,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadWord_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lw(A0, Address(A0, -4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWord_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "ffc52503 lw a0, -4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(-1425997309,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreWord_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sw(A1, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00b52023 sw a1, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD020405);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0xCD020405, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(StoreWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sw(A1, Address(A0, 4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00b52223 sw a1, 4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF030607);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0xEF030607, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(StoreWord_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sw(A1, Address(A0, -4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreWord_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "feb52e23 sw a1, -4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB010203);
+  EXPECT_EQ(0xAB010203, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_0, assembler) {
+  __ lwu(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWordUnsigned_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00056503 lwu a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(0xCD020405,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lwu(A0, Address(A0, 4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWordUnsigned_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00456503 lwu a0, 4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(0xEF030607,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lwu(A0, Address(A0, -4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadWordUnsigned_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "ffc56503 lwu a0, -4(a0)\n"
+      "00008067 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(0xAB010203,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadDoubleWord_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ld(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadDoubleWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00053503 ld a0, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0xAB01020304050607;
+  values[1] = 0xCD02040505060708;
+  values[2] = 0xEF03060708090A0B;
+
+  EXPECT_EQ(-3674369926375274744,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ld(A0, Address(A0, 8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadDoubleWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00853503 ld a0, 8(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0xAB01020304050607;
+  values[1] = 0xCD02040505060708;
+  values[2] = 0xEF03060708090A0B;
+
+  EXPECT_EQ(-1224128046445295093,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ld(A0, Address(A0, -8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadDoubleWord_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "ff853503 ld a0, -8(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0xAB01020304050607;
+  values[1] = 0xCD02040505060708;
+  values[2] = 0xEF03060708090A0B;
+
+  EXPECT_EQ(-6124611806271568377,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreDoubleWord_0, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sd(A1, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreDoubleWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "00b53023 sd a1, 0(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD02040505060708);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0xCD02040505060708, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sd(A1, Address(A0, 8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreDoubleWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "00b53423 sd a1, 8(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF03060708090A0B);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0xEF03060708090A0B, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Neg, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sd(A1, Address(A0, -8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreDoubleWord_Neg, test) {
+  EXPECT_DISASSEMBLY(
+      "feb53c23 sd a1, -8(a0)\n"
+      "00008067 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB01020304050607);
+  EXPECT_EQ(0xAB01020304050607, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(AddImmediate1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ addi(A0, A0, 42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddImmediate1, test) {
+  EXPECT_DISASSEMBLY(
+      "02a50513 addi a0, a0, 42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 0));
+  EXPECT_EQ(40, Call(test->entry(), -2));
+  EXPECT_EQ(0, Call(test->entry(), -42));
+}
+
+ASSEMBLER_TEST_GENERATE(AddImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ addi(A0, A0, -42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "fd650513 addi a0, a0, -42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, Call(test->entry(), 0));
+  EXPECT_EQ(-44, Call(test->entry(), -2));
+  EXPECT_EQ(38, Call(test->entry(), 80));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanImmediate1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slti(A0, A0, 7);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanImmediate1, test) {
+  EXPECT_DISASSEMBLY(
+      "00752513 slti a0, a0, 7\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), 6));
+  EXPECT_EQ(0, Call(test->entry(), 7));
+  EXPECT_EQ(0, Call(test->entry(), 8));
+  EXPECT_EQ(1, Call(test->entry(), -6));
+  EXPECT_EQ(1, Call(test->entry(), -7));
+  EXPECT_EQ(1, Call(test->entry(), -8));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slti(A0, A0, -7);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "ff952513 slti a0, a0, -7\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 6));
+  EXPECT_EQ(0, Call(test->entry(), 7));
+  EXPECT_EQ(0, Call(test->entry(), 8));
+  EXPECT_EQ(0, Call(test->entry(), -6));
+  EXPECT_EQ(0, Call(test->entry(), -7));
+  EXPECT_EQ(1, Call(test->entry(), -8));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sltiu(A0, A0, 7);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned1, test) {
+  EXPECT_DISASSEMBLY(
+      "00753513 sltiu a0, a0, 7\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), 6));
+  EXPECT_EQ(0, Call(test->entry(), 7));
+  EXPECT_EQ(0, Call(test->entry(), 8));
+  EXPECT_EQ(0, Call(test->entry(), -6));
+  EXPECT_EQ(0, Call(test->entry(), -7));
+  EXPECT_EQ(0, Call(test->entry(), -8));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sltiu(A0, A0, -7);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned2, test) {
+  EXPECT_DISASSEMBLY(
+      "ff953513 sltiu a0, a0, -7\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), 6));
+  EXPECT_EQ(1, Call(test->entry(), 7));
+  EXPECT_EQ(1, Call(test->entry(), 8));
+  EXPECT_EQ(0, Call(test->entry(), -6));
+  EXPECT_EQ(0, Call(test->entry(), -7));
+  EXPECT_EQ(1, Call(test->entry(), -8));
+}
+
+ASSEMBLER_TEST_GENERATE(XorImmediate1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ xori(A0, A0, 42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(XorImmediate1, test) {
+  EXPECT_DISASSEMBLY(
+      "02a54513 xori a0, a0, 42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 0));
+  EXPECT_EQ(43, Call(test->entry(), 1));
+  EXPECT_EQ(32, Call(test->entry(), 10));
+  EXPECT_EQ(-43, Call(test->entry(), -1));
+  EXPECT_EQ(-36, Call(test->entry(), -10));
+}
+
+ASSEMBLER_TEST_GENERATE(XorImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ xori(A0, A0, -42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(XorImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "fd654513 xori a0, a0, -42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, Call(test->entry(), 0));
+  EXPECT_EQ(-41, Call(test->entry(), 1));
+  EXPECT_EQ(-36, Call(test->entry(), 10));
+  EXPECT_EQ(41, Call(test->entry(), -1));
+  EXPECT_EQ(32, Call(test->entry(), -10));
+}
+
+ASSEMBLER_TEST_GENERATE(OrImmediate1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ori(A0, A0, -6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(OrImmediate1, test) {
+  EXPECT_DISASSEMBLY(
+      "ffa56513 ori a0, a0, -6\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-6, Call(test->entry(), 0));
+  EXPECT_EQ(-5, Call(test->entry(), 1));
+  EXPECT_EQ(-5, Call(test->entry(), 11));
+  EXPECT_EQ(-1, Call(test->entry(), -1));
+  EXPECT_EQ(-1, Call(test->entry(), -11));
+}
+
+ASSEMBLER_TEST_GENERATE(OrImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ori(A0, A0, 6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(OrImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "00656513 ori a0, a0, 6\n"
+      "00008067 ret\n");
+  EXPECT_EQ(6, Call(test->entry(), 0));
+  EXPECT_EQ(7, Call(test->entry(), 1));
+  EXPECT_EQ(15, Call(test->entry(), 11));
+  EXPECT_EQ(-1, Call(test->entry(), -1));
+  EXPECT_EQ(-9, Call(test->entry(), -11));
+}
+
+ASSEMBLER_TEST_GENERATE(AndImmediate1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ andi(A0, A0, -6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AndImmediate1, test) {
+  EXPECT_DISASSEMBLY(
+      "ffa57513 andi a0, a0, -6\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(10, Call(test->entry(), 11));
+  EXPECT_EQ(-6, Call(test->entry(), -1));
+  EXPECT_EQ(-16, Call(test->entry(), -11));
+}
+
+ASSEMBLER_TEST_GENERATE(AndImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ andi(A0, A0, 6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AndImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "00657513 andi a0, a0, 6\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(2, Call(test->entry(), 11));
+  EXPECT_EQ(6, Call(test->entry(), -1));
+  EXPECT_EQ(4, Call(test->entry(), -11));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slli(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "00251513 slli a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(84, Call(test->entry(), 21));
+  EXPECT_EQ(4, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-4, Call(test->entry(), -1));
+  EXPECT_EQ(-84, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slli(A0, A0, XLEN - 1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate2, test) {
+#if XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "01f51513 slli a0, a0, 0x1f\n"
+      "00008067 ret\n");
+#elif XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "03f51513 slli a0, a0, 0x3f\n"
+      "00008067 ret\n");
+#endif
+  EXPECT_EQ(0, Call(test->entry(), 2));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), -1));
+  EXPECT_EQ(0, Call(test->entry(), -2));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srli(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "00255513 srli a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(5, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-1) >> 2),
+            Call(test->entry(), -1));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-21) >> 2),
+            Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srli(A0, A0, XLEN - 1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate2, test) {
+#if XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "01f55513 srli a0, a0, 0x1f\n"
+      "00008067 ret\n");
+#elif XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "03f55513 srli a0, a0, 0x3f\n"
+      "00008067 ret\n");
+#endif
+  EXPECT_EQ(0, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(1, Call(test->entry(), -1));
+  EXPECT_EQ(1, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srai(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "40255513 srai a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(5, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-1, Call(test->entry(), -1));
+  EXPECT_EQ(-6, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srai(A0, A0, XLEN - 1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate2, test) {
+#if XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "41f55513 srai a0, a0, 0x1f\n"  // CHECK
+      "00008067 ret\n");
+#elif XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "43f55513 srai a0, a0, 0x3f\n"  // CHECK
+      "00008067 ret\n");
+#endif
+  EXPECT_EQ(0, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-1, Call(test->entry(), -1));
+  EXPECT_EQ(-1, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(Add, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ add(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Add, test) {
+  EXPECT_DISASSEMBLY(
+      "00b50533 add a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(24, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-10, Call(test->entry(), 7, -17));
+  EXPECT_EQ(10, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, -17));
+  EXPECT_EQ(24, Call(test->entry(), 17, 7));
+  EXPECT_EQ(10, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(Subtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sub(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Subtract, test) {
+  EXPECT_DISASSEMBLY(
+      "40b50533 sub a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-10, Call(test->entry(), 7, 17));
+  EXPECT_EQ(24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(10, Call(test->entry(), -7, -17));
+  EXPECT_EQ(10, Call(test->entry(), 17, 7));
+  EXPECT_EQ(24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftLeftLogical, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sll(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftLeftLogical, test) {
+  EXPECT_DISASSEMBLY(
+      "00b51533 sll a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(2176, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-2176, Call(test->entry(), -17, 7));
+  EXPECT_EQ(34, Call(test->entry(), 17, 1));
+  EXPECT_EQ(-34, Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThan, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slt(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThan, test) {
+  EXPECT_DISASSEMBLY(
+      "00b52533 slt a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 7, 7));
+  EXPECT_EQ(0, Call(test->entry(), -7, -7));
+  EXPECT_EQ(1, Call(test->entry(), 7, 17));
+  EXPECT_EQ(0, Call(test->entry(), 7, -17));
+  EXPECT_EQ(1, Call(test->entry(), -7, 17));
+  EXPECT_EQ(0, Call(test->entry(), -7, -17));
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(0, Call(test->entry(), 17, -7));
+  EXPECT_EQ(1, Call(test->entry(), -17, 7));
+  EXPECT_EQ(1, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanUnsigned, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sltu(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanUnsigned, test) {
+  EXPECT_DISASSEMBLY(
+      "00b53533 sltu a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 7, 7));
+  EXPECT_EQ(0, Call(test->entry(), -7, -7));
+  EXPECT_EQ(1, Call(test->entry(), 7, 17));
+  EXPECT_EQ(1, Call(test->entry(), 7, -17));
+  EXPECT_EQ(0, Call(test->entry(), -7, 17));
+  EXPECT_EQ(0, Call(test->entry(), -7, -17));
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(1, Call(test->entry(), 17, -7));
+  EXPECT_EQ(0, Call(test->entry(), -17, 7));
+  EXPECT_EQ(1, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(Xor, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ xor_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Xor, test) {
+  EXPECT_DISASSEMBLY(
+      "00b54533 xor a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(22, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(22, Call(test->entry(), -7, -17));
+  EXPECT_EQ(22, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(22, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightLogical, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srl(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightLogical, test) {
+  EXPECT_DISASSEMBLY(
+      "00b55533 srl a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 7),
+            Call(test->entry(), -17, 7));
+  EXPECT_EQ(8, Call(test->entry(), 17, 1));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 1),
+            Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightArithmetic, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sra(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightArithmetic, test) {
+  EXPECT_DISASSEMBLY(
+      "40b55533 sra a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 7));
+  EXPECT_EQ(8, Call(test->entry(), 17, 1));
+  EXPECT_EQ(-9, Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(Or, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ or_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Or, test) {
+  EXPECT_DISASSEMBLY(
+      "00b56533 or a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(23, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-17, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-7, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-1, Call(test->entry(), -7, -17));
+  EXPECT_EQ(23, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-7, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-1, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(And, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ and_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(And, test) {
+  EXPECT_DISASSEMBLY(
+      "00b57533 and a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), 7, 17));
+  EXPECT_EQ(7, Call(test->entry(), 7, -17));
+  EXPECT_EQ(17, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-23, Call(test->entry(), -7, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 7));
+  EXPECT_EQ(17, Call(test->entry(), 17, -7));
+  EXPECT_EQ(7, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-23, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(Fence, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fence();
+  __ fence(kRead, kWrite);
+  __ fence(kInput, kOutput);
+  __ fence(kMemory, kMemory);
+  __ fence(kAll, kAll);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Fence, test) {
+  EXPECT_DISASSEMBLY(
+      "0ff0000f fence\n"
+      "0210000f fence r,w\n"
+      "0840000f fence i,o\n"
+      "0330000f fence rw,rw\n"
+      "0ff0000f fence\n"
+      "00008067 ret\n");
+  Call(test->entry());
+}
+
+ASSEMBLER_TEST_GENERATE(InstructionFence, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fencei();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(InstructionFence, test) {
+  EXPECT_DISASSEMBLY(
+      "0000100f fence.i\n"
+      "00008067 ret\n");
+  Call(test->entry());
+}
+
+ASSEMBLER_TEST_GENERATE(EnvironmentCall, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ecall();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(EnvironmentCall, test) {
+  EXPECT_DISASSEMBLY(
+      "00000073 ecall\n"
+      "00008067 ret\n");
+
+  // Not running: would trap.
+}
+
+ASSEMBLER_TEST_GENERATE(EnvironmentBreak, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ebreak();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(EnvironmentBreak, test) {
+  EXPECT_DISASSEMBLY(
+      "00100073 ebreak\n"
+      "00008067 ret\n");
+
+  // Not running: would trap.
+}
+
+ASSEMBLER_TEST_GENERATE(ControlStatusRegisters, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ csrrw(T0, 0x123, S1);
+  __ csrrs(T1, 0x123, S2);
+  __ csrrc(T2, 0x123, S3);
+  __ csrr(T3, 0x123);
+  __ csrw(0x123, S4);
+  __ csrs(0x123, S5);
+  __ csrc(0x123, S6);
+  __ csrrwi(T1, 0x123, 1);
+  __ csrrsi(T2, 0x123, 2);
+  __ csrrci(T3, 0x123, 3);
+  __ csrwi(0x123, 4);
+  __ csrsi(0x123, 5);
+  __ csrci(0x123, 6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ControlStatusRegisters, test) {
+  EXPECT_DISASSEMBLY(
+      "123492f3 csrrw t0, 0x123, thr\n"
+      "12392373 csrrs t1, 0x123, s2\n"
+      "1239b3f3 csrrc t2, 0x123, s3\n"
+      "12302e73 csrr t3, 0x123\n"
+      "123a1073 csrw 0x123, s4\n"
+      "123aa073 csrs 0x123, s5\n"
+      "123b3073 csrc 0x123, s6\n"
+      "1230d373 csrrwi t1, 0x123, 1\n"
+      "123163f3 csrrsi t2, 0x123, 2\n"
+      "1231fe73 csrrci t3, 0x123, 3\n"
+      "12325073 csrwi 0x123, 4\n"
+      "1232e073 csrsi 0x123, 5\n"
+      "12337073 csrci 0x123, 6\n"
+      "00008067 ret\n");
+
+  // Not running: would trap.
+}
+
+ASSEMBLER_TEST_GENERATE(Nop, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ nop();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Nop, test) {
+  EXPECT_DISASSEMBLY(
+      "00000013 nop\n"
+      "00008067 ret\n");
+  EXPECT_EQ(123, Call(test->entry(), 123));
+}
+
+ASSEMBLER_TEST_GENERATE(Move, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mv(A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Move, test) {
+  EXPECT_DISASSEMBLY(
+      "00058513 mv a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(36, Call(test->entry(), 42, 36));
+}
+
+ASSEMBLER_TEST_GENERATE(Not, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ not_(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Not, test) {
+  EXPECT_DISASSEMBLY(
+      "fff54513 not a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(~42, Call(test->entry(), 42));
+  EXPECT_EQ(~-42, Call(test->entry(), -42));
+}
+
+ASSEMBLER_TEST_GENERATE(Negate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ neg(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Negate, test) {
+  EXPECT_DISASSEMBLY(
+      "40a00533 neg a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, Call(test->entry(), 42));
+  EXPECT_EQ(42, Call(test->entry(), -42));
+}
+
+ASSEMBLER_TEST_GENERATE(SetNotEqualToZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ snez(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetNotEqualToZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00a03533 snez a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), -42));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(1, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(SetEqualToZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ seqz(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetEqualToZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00153513 seqz a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), -42));
+  EXPECT_EQ(1, Call(test->entry(), 0));
+  EXPECT_EQ(0, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(SetLessThanZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sltz(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetLessThanZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00052533 sltz a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), -42));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(0, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(SetGreaterThanZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sgtz(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SetGreaterThanZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00a02533 sgtz a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), -42));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(1, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchEqualZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ beqz(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00050663 beqz a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), -42));
+  EXPECT_EQ(4, Call(test->entry(), 0));
+  EXPECT_EQ(3, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchNotEqualZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ bnez(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchNotEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00051663 bnez a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), -42));
+  EXPECT_EQ(3, Call(test->entry(), 0));
+  EXPECT_EQ(4, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessOrEqualZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ blez(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessOrEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00a05663 blez a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), -42));
+  EXPECT_EQ(4, Call(test->entry(), 0));
+  EXPECT_EQ(3, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ bgez(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterOrEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00055663 bgez a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), -42));
+  EXPECT_EQ(4, Call(test->entry(), 0));
+  EXPECT_EQ(4, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchLessThanZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ bltz(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchLessThanZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00054663 bltz a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), -42));
+  EXPECT_EQ(3, Call(test->entry(), 0));
+  EXPECT_EQ(3, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(BranchGreaterThanZero, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label label;
+  __ bgtz(A0, &label);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BranchGreaterThanZero, test) {
+  EXPECT_DISASSEMBLY(
+      "00a04663 bgtz a0, +12\n"
+      "00300513 li a0, 3\n"
+      "00008067 ret\n"
+      "00400513 li a0, 4\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), -42));
+  EXPECT_EQ(3, Call(test->entry(), 0));
+  EXPECT_EQ(4, Call(test->entry(), 42));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(AddImmediateWord1, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ addiw(A0, A0, 42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddImmediateWord1, test) {
+  EXPECT_DISASSEMBLY(
+      "02a5051b addiw a0, a0, 42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 0));
+  EXPECT_EQ(40, Call(test->entry(), -2));
+  EXPECT_EQ(0, Call(test->entry(), -42));
+}
+
+ASSEMBLER_TEST_GENERATE(AddImmediateWord2, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ addiw(A0, A0, -42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddImmediateWord2, test) {
+  EXPECT_DISASSEMBLY(
+      "fd65051b addiw a0, a0, -42\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, Call(test->entry(), 0));
+  EXPECT_EQ(-44, Call(test->entry(), -2));
+  EXPECT_EQ(38, Call(test->entry(), 80));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediateWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ slliw(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediateWord, test) {
+  EXPECT_DISASSEMBLY(
+      "0025151b slliw a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(84, Call(test->entry(), 21));
+  EXPECT_EQ(4, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-4, Call(test->entry(), -1));
+  EXPECT_EQ(-84, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediateWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srliw(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediateWord, test) {
+  EXPECT_DISASSEMBLY(
+      "0025551b srliw a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(5, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-1) >> 2),
+            Call(test->entry(), -1));
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-21) >> 2),
+            Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediateWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sraiw(A0, A0, 2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediateWord, test) {
+  EXPECT_DISASSEMBLY(
+      "4025551b sraiw a0, a0, 0x2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(5, Call(test->entry(), 21));
+  EXPECT_EQ(0, Call(test->entry(), 1));
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-1, Call(test->entry(), -1));
+  EXPECT_EQ(-6, Call(test->entry(), -21));
+}
+
+ASSEMBLER_TEST_GENERATE(AddWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ addw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddWord, test) {
+  EXPECT_DISASSEMBLY(
+      "00b5053b addw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(24, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-10, Call(test->entry(), 7, -17));
+  EXPECT_EQ(10, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, -17));
+  EXPECT_EQ(24, Call(test->entry(), 17, 7));
+  EXPECT_EQ(10, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, -7));
+  EXPECT_EQ(3, Call(test->entry(), 0x200000002, 0x100000001));
+}
+
+ASSEMBLER_TEST_GENERATE(SubtractWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ subw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SubtractWord, test) {
+  EXPECT_DISASSEMBLY(
+      "40b5053b subw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-10, Call(test->entry(), 7, 17));
+  EXPECT_EQ(24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(10, Call(test->entry(), -7, -17));
+  EXPECT_EQ(10, Call(test->entry(), 17, 7));
+  EXPECT_EQ(24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, -7));
+  EXPECT_EQ(1, Call(test->entry(), 0x200000002, 0x100000001));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sllw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftLeftLogicalWord, test) {
+  EXPECT_DISASSEMBLY(
+      "00b5153b sllw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(2176, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-2176, Call(test->entry(), -17, 7));
+  EXPECT_EQ(34, Call(test->entry(), 17, 1));
+  EXPECT_EQ(-34, Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+  EXPECT_EQ(0x10, Call(test->entry(), 0x10000001, 4));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightLogicalWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ srlw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightLogicalWord, test) {
+  EXPECT_DISASSEMBLY(
+      "00b5553b srlw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 7),
+            Call(test->entry(), -17, 7));
+  EXPECT_EQ(8, Call(test->entry(), 17, 1));
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 1),
+            Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sraw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ShiftRightArithmeticWord, test) {
+  EXPECT_DISASSEMBLY(
+      "40b5553b sraw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 7));
+  EXPECT_EQ(8, Call(test->entry(), 17, 1));
+  EXPECT_EQ(-9, Call(test->entry(), -17, 1));
+  EXPECT_EQ(17, Call(test->entry(), 17, 0));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(NegateWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ negw(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(NegateWord, test) {
+  EXPECT_DISASSEMBLY(
+      "40a0053b negw a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(-42, Call(test->entry(), 42));
+  EXPECT_EQ(42, Call(test->entry(), -42));
+  EXPECT_EQ(1, Call(test->entry(), 0x10FFFFFFFF));
+}
+
+ASSEMBLER_TEST_GENERATE(SignExtendWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ sextw(A0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SignExtendWord, test) {
+  EXPECT_DISASSEMBLY(
+      "0005051b sext.w a0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(42, Call(test->entry(), 42));
+  EXPECT_EQ(-42, Call(test->entry(), -42));
+  EXPECT_EQ(-1, Call(test->entry(), 0x10FFFFFFFF));
+}
+#endif  // XLEN >= 64
+
+ASSEMBLER_TEST_GENERATE(Multiply, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mul(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Multiply, test) {
+  EXPECT_DISASSEMBLY(
+      "02b50533 mul a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(68, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-68, Call(test->entry(), -4, 17));
+  EXPECT_EQ(-68, Call(test->entry(), 4, -17));
+  EXPECT_EQ(68, Call(test->entry(), -4, -17));
+  EXPECT_EQ(68, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-68, Call(test->entry(), -17, 4));
+  EXPECT_EQ(-68, Call(test->entry(), 17, -4));
+  EXPECT_EQ(68, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyHigh, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mulh(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyHigh, test) {
+  EXPECT_DISASSEMBLY(
+      "02b51533 mulh a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-1, Call(test->entry(), -4, 17));
+  EXPECT_EQ(-1, Call(test->entry(), 4, -17));
+  EXPECT_EQ(0, Call(test->entry(), -4, -17));
+  EXPECT_EQ(0, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 4));
+  EXPECT_EQ(-1, Call(test->entry(), 17, -4));
+  EXPECT_EQ(0, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyHighSignedUnsigned, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mulhsu(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyHighSignedUnsigned, test) {
+  EXPECT_DISASSEMBLY(
+      "02b52533 mulhsu a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-1, Call(test->entry(), -4, 17));
+  EXPECT_EQ(3, Call(test->entry(), 4, -17));
+  EXPECT_EQ(-4, Call(test->entry(), -4, -17));
+  EXPECT_EQ(0, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 4));
+  EXPECT_EQ(16, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-17, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyHighUnsigned, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mulhu(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyHighUnsigned, test) {
+  EXPECT_DISASSEMBLY(
+      "02b53533 mulhu a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(16, Call(test->entry(), -4, 17));
+  EXPECT_EQ(3, Call(test->entry(), 4, -17));
+  EXPECT_EQ(-21, Call(test->entry(), -4, -17));
+  EXPECT_EQ(0, Call(test->entry(), 17, 4));
+  EXPECT_EQ(3, Call(test->entry(), -17, 4));
+  EXPECT_EQ(16, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-21, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(Divide, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ div(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Divide, test) {
+  EXPECT_DISASSEMBLY(
+      "02b54533 div a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(0, Call(test->entry(), -4, 17));
+  EXPECT_EQ(0, Call(test->entry(), 4, -17));
+  EXPECT_EQ(0, Call(test->entry(), -4, -17));
+  EXPECT_EQ(4, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-4, Call(test->entry(), -17, 4));
+  EXPECT_EQ(-4, Call(test->entry(), 17, -4));
+  EXPECT_EQ(4, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(DivideUnsigned, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ divu(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DivideUnsigned, test) {
+  EXPECT_DISASSEMBLY(
+      "02b55533 divu a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+#if XLEN == 32
+  EXPECT_EQ(252645134, Call(test->entry(), -4, 17));
+#else
+  EXPECT_EQ(1085102592571150094, Call(test->entry(), -4, 17));
+#endif
+  EXPECT_EQ(0, Call(test->entry(), 4, -17));
+  EXPECT_EQ(1, Call(test->entry(), -4, -17));
+  EXPECT_EQ(4, Call(test->entry(), 17, 4));
+#if XLEN == 32
+  EXPECT_EQ(1073741819, Call(test->entry(), -17, 4));
+#else
+  EXPECT_EQ(4611686018427387899, Call(test->entry(), -17, 4));
+#endif
+  EXPECT_EQ(0, Call(test->entry(), 17, -4));
+  EXPECT_EQ(0, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(Remainder, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ rem(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(Remainder, test) {
+  EXPECT_DISASSEMBLY(
+      "02b56533 rem a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-4, Call(test->entry(), -4, 17));
+  EXPECT_EQ(4, Call(test->entry(), 4, -17));
+  EXPECT_EQ(-4, Call(test->entry(), -4, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 4));
+  EXPECT_EQ(1, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(RemainderUnsigned, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ remu(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(RemainderUnsigned, test) {
+  EXPECT_DISASSEMBLY(
+      "02b57533 remu a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 4, 17));
+  EXPECT_EQ(14, Call(test->entry(), -4, 17));
+  EXPECT_EQ(4, Call(test->entry(), 4, -17));
+  EXPECT_EQ(13, Call(test->entry(), -4, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 4));
+  EXPECT_EQ(3, Call(test->entry(), -17, 4));
+  EXPECT_EQ(17, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-17, Call(test->entry(), -17, -4));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(MultiplyWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ mulw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyWord, test) {
+  EXPECT_DISASSEMBLY(
+      "02b5053b mulw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(68, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-68, Call(test->entry(), -4, 17));
+  EXPECT_EQ(-68, Call(test->entry(), 4, -17));
+  EXPECT_EQ(68, Call(test->entry(), -4, -17));
+  EXPECT_EQ(68, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-68, Call(test->entry(), -17, 4));
+  EXPECT_EQ(-68, Call(test->entry(), 17, -4));
+  EXPECT_EQ(68, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(DivideWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ divw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DivideWord, test) {
+  EXPECT_DISASSEMBLY(
+      "02b5453b divw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(0, Call(test->entry(), -4, 17));
+  EXPECT_EQ(0, Call(test->entry(), 4, -17));
+  EXPECT_EQ(0, Call(test->entry(), -4, -17));
+  EXPECT_EQ(4, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-4, Call(test->entry(), -17, 4));
+  EXPECT_EQ(-4, Call(test->entry(), 17, -4));
+  EXPECT_EQ(4, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(DivideUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ divuw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DivideUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "02b5553b divuw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 4, 17));
+  EXPECT_EQ(252645134, Call(test->entry(), -4, 17));
+  EXPECT_EQ(0, Call(test->entry(), 4, -17));
+  EXPECT_EQ(1, Call(test->entry(), -4, -17));
+  EXPECT_EQ(4, Call(test->entry(), 17, 4));
+  EXPECT_EQ(1073741819, Call(test->entry(), -17, 4));
+  EXPECT_EQ(0, Call(test->entry(), 17, -4));
+  EXPECT_EQ(0, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(RemainderWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ remw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(RemainderWord, test) {
+  EXPECT_DISASSEMBLY(
+      "02b5653b remw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 4, 17));
+  EXPECT_EQ(-4, Call(test->entry(), -4, 17));
+  EXPECT_EQ(4, Call(test->entry(), 4, -17));
+  EXPECT_EQ(-4, Call(test->entry(), -4, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, 4));
+  EXPECT_EQ(1, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-1, Call(test->entry(), -17, -4));
+}
+
+ASSEMBLER_TEST_GENERATE(RemainderUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ remuw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(RemainderUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "02b5753b remuw a0, a0, a1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), 4, 17));
+  EXPECT_EQ(14, Call(test->entry(), -4, 17));
+  EXPECT_EQ(4, Call(test->entry(), 4, -17));
+  EXPECT_EQ(13, Call(test->entry(), -4, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 4));
+  EXPECT_EQ(3, Call(test->entry(), -17, 4));
+  EXPECT_EQ(17, Call(test->entry(), 17, -4));
+  EXPECT_EQ(-17, Call(test->entry(), -17, -4));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalWord_Success, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lrw(T0, Address(A0));
+  __ addi(T0, T0, 1);
+  __ scw(A0, T0, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalWord_Success, test) {
+  EXPECT_DISASSEMBLY(
+      "100522af lr.w t0, (a0)\n"
+      "00128293 addi t0, t0, 1\n"
+      "1855252f sc.w a0, t0, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0, Call(test->entry(), reinterpret_cast<intx_t>(value)));
+  EXPECT_EQ(0b1101, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalWord_Failure, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ li(T0, 42);
+  __ scw(A0, T0, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalWord_Failure, test) {
+  EXPECT_DISASSEMBLY(
+      "02a00293 li t0, 42\n"
+      "1855252f sc.w a0, t0, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(false, 0 == Call(test->entry(), reinterpret_cast<intx_t>(value)));
+  EXPECT_EQ(0b1100, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoSwapWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoswapw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoSwapWord, test) {
+  EXPECT_DISASSEMBLY(
+      "08b5252f amoswap.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1010, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoAddWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoaddw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoAddWord, test) {
+  EXPECT_DISASSEMBLY(
+      "00b5252f amoadd.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 42;
+  EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(value), 10));
+  EXPECT_EQ(52, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoXorWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoxorw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoXorWord, test) {
+  EXPECT_DISASSEMBLY(
+      "20b5252f amoxor.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b0110, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoAndWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoandw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoAndWord, test) {
+  EXPECT_DISASSEMBLY(
+      "60b5252f amoand.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1000, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoOrWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoorw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoOrWord, test) {
+  EXPECT_DISASSEMBLY(
+      "40b5252f amoor.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1110, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMinWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amominw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMinWord, test) {
+  EXPECT_DISASSEMBLY(
+      "80b5252f amomin.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-11, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMaxWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amomaxw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMaxWord, test) {
+  EXPECT_DISASSEMBLY(
+      "a0b5252f amomax.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-4, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMinUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amominuw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMinUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0b5252f amominu.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = -7;
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-11, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amomaxuw(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMaxUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "e0b5252f amomaxu.w a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int32_t* value = reinterpret_cast<int32_t*>(malloc(sizeof(int32_t)));
+  *value = -7;
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(sign_extend(static_cast<uint32_t>(-7)),
+            Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-4, *value);
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalDoubleWord_Success,
+                        assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ lrd(T0, Address(A0));
+  __ addi(T0, T0, 1);
+  __ scd(A0, T0, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalDoubleWord_Success, test) {
+  EXPECT_DISASSEMBLY(
+      "100532af lr.d t0, (a0)\n"
+      "00128293 addi t0, t0, 1\n"
+      "1855352f sc.d a0, t0, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0, Call(test->entry(), reinterpret_cast<intx_t>(value)));
+  EXPECT_EQ(0b1101, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(LoadReserveStoreConditionalDoubleWord_Failure,
+                        assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ li(T0, 42);
+  __ scd(A0, T0, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadReserveStoreConditionalDoubleWord_Failure, test) {
+  EXPECT_DISASSEMBLY(
+      "02a00293 li t0, 42\n"
+      "1855352f sc.d a0, t0, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(false, 0 == Call(test->entry(), reinterpret_cast<intx_t>(value)));
+  EXPECT_EQ(0b1100, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoSwapDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoswapd(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoSwapDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "08b5352f amoswap.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1010, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoAddDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoaddd(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoAddDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "00b5352f amoadd.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 42;
+  EXPECT_EQ(42, Call(test->entry(), reinterpret_cast<intx_t>(value), 10));
+  EXPECT_EQ(52, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoXorDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoxord(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoXorDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "20b5352f amoxor.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b0110, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoAndDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoandd(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoAndDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "60b5352f amoand.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1000, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoOrDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amoord(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoOrDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "40b5352f amoor.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = 0b1100;
+  EXPECT_EQ(0b1100,
+            Call(test->entry(), reinterpret_cast<intx_t>(value), 0b1010));
+  EXPECT_EQ(0b1110, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMinDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amomind(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMinDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "80b5352f amomin.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-11, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMaxDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amomaxd(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMaxDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "a0b5352f amomax.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-4, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMinUnsignedDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amominud(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMinUnsignedDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0b5352f amominu.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-11, *value);
+}
+
+ASSEMBLER_TEST_GENERATE(AmoMaxUnsignedDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ amomaxud(A0, A1, Address(A0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AmoMaxUnsignedDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "e0b5352f amomaxu.d a0, a1, (a0)\n"
+      "00008067 ret\n");
+
+  int64_t* value = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
+  *value = -7;
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -11));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -7));
+  EXPECT_EQ(-7, *value);
+  EXPECT_EQ(-7, Call(test->entry(), reinterpret_cast<intx_t>(value), -4));
+  EXPECT_EQ(-4, *value);
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(LoadSingleFloat, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ flw(FA0, Address(A0, 1 * sizeof(float)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadSingleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "00452507 flw fa0, 4(a0)\n"
+      "00008067 ret\n");
+
+  float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
+  data[0] = 1.7f;
+  data[1] = 2.8f;
+  data[2] = 3.9f;
+  EXPECT_EQ(data[1], CallF(test->entry(), reinterpret_cast<intx_t>(data)));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreSingleFloat, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsw(FA0, Address(A0, 1 * sizeof(float)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreSingleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "00a52227 fsw fa0, 4(a0)\n"
+      "00008067 ret\n");
+
+  float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
+  data[0] = 1.7f;
+  data[1] = 2.8f;
+  data[2] = 3.9f;
+  CallF(test->entry(), reinterpret_cast<intx_t>(data), 4.2f);
+  EXPECT_EQ(4.2f, data[1]);
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMultiplyAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmadds(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMultiplyAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "60b50543 fmadd.s fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(22.0, CallF(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(-8.0, CallF(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(8.0, CallF(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(26.0, CallF(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(-16.0, CallF(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(16.0, CallF(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMultiplySubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmsubs(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMultiplySubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "60b50547 fmsub.s fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(8.0, CallF(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(-22.0, CallF(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(22.0, CallF(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(16.0, CallF(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(-26.0, CallF(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(26.0, CallF(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleNegateMultiplySubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnmsubs(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleNegateMultiplySubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "60b5054b fnmsub.s fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(22.0, CallF(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(22.0, CallF(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(26.0, CallF(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(26.0, CallF(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleNegateMultiplyAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnmadds(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleNegateMultiplyAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "60b5054f fnmadd.s fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-22.0, CallF(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(8.0, CallF(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(8.0, CallF(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(-8.0, CallF(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(-26.0, CallF(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(16.0, CallF(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(16.0, CallF(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(-16.0, CallF(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fadds(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "00b50553 fadd.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(8.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(2.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-2.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(-8.0f, CallF(test->entry(), -3.0f, -5.0f));
+
+  EXPECT_EQ(10.0f, CallF(test->entry(), 7.0f, 3.0f));
+  EXPECT_EQ(-4.0f, CallF(test->entry(), -7.0f, 3.0f));
+  EXPECT_EQ(4.0f, CallF(test->entry(), 7.0f, -3.0f));
+  EXPECT_EQ(-10.0f, CallF(test->entry(), -7.0f, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleSubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsubs(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleSubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "08b50553 fsub.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-2.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(-8.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(8.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(2.0f, CallF(test->entry(), -3.0f, -5.0f));
+
+  EXPECT_EQ(4.0f, CallF(test->entry(), 7.0f, 3.0f));
+  EXPECT_EQ(-10.0f, CallF(test->entry(), -7.0f, 3.0f));
+  EXPECT_EQ(10.0f, CallF(test->entry(), 7.0f, -3.0f));
+  EXPECT_EQ(-4.0f, CallF(test->entry(), -7.0f, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMultiply, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmuls(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMultiply, test) {
+  EXPECT_DISASSEMBLY(
+      "10b50553 fmul.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(15.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(-15.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-15.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(15.0f, CallF(test->entry(), -3.0f, -5.0f));
+
+  EXPECT_EQ(21.0f, CallF(test->entry(), 7.0f, 3.0f));
+  EXPECT_EQ(-21.0f, CallF(test->entry(), -7.0f, 3.0f));
+  EXPECT_EQ(-21.0f, CallF(test->entry(), 7.0f, -3.0f));
+  EXPECT_EQ(21.0f, CallF(test->entry(), -7.0f, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleDivide, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fdivs(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleDivide, test) {
+  EXPECT_DISASSEMBLY(
+      "18b50553 fdiv.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(2.0f, CallF(test->entry(), 10.0f, 5.0f));
+  EXPECT_EQ(-2.0f, CallF(test->entry(), -10.0f, 5.0f));
+  EXPECT_EQ(-2.0f, CallF(test->entry(), 10.0f, -5.0f));
+  EXPECT_EQ(2.0f, CallF(test->entry(), -10.0f, -5.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleSquareRoot, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsqrts(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleSquareRoot, test) {
+  EXPECT_DISASSEMBLY(
+      "58050553 fsqrt.s fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), 0.0f));
+  EXPECT_EQ(1.0f, CallF(test->entry(), 1.0f));
+  EXPECT_EQ(2.0f, CallF(test->entry(), 4.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 9.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjs(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "20b50553 fsgnj.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -5.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleNegatedSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjns(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleNegatedSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "20b51553 fsgnjn.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, -5.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleXorSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjxs(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleXorSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "20b52553 fsgnjx.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, -5.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMin, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmins(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMin, test) {
+  EXPECT_DISASSEMBLY(
+      "28b50553 fmin.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1.0f, CallF(test->entry(), 3.0f, 1.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(-1.0f, CallF(test->entry(), 3.0f, -1.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), 3.0f, -3.0f));
+  EXPECT_EQ(-5.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 1.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 3.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -1.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
+  EXPECT_EQ(-5.0f, CallF(test->entry(), -3.0f, -5.0f));
+
+  float qNAN = std::numeric_limits<float>::quiet_NaN();
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, qNAN));
+  EXPECT_EQ(3.0f, CallF(test->entry(), qNAN, 3.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, qNAN));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), qNAN, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMax, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmaxs(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMax, test) {
+  EXPECT_DISASSEMBLY(
+      "28b51553 fmax.s fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 1.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, 3.0f));
+  EXPECT_EQ(5.0f, CallF(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -1.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -3.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(1.0f, CallF(test->entry(), -3.0f, 1.0f));
+  EXPECT_EQ(3.0f, CallF(test->entry(), -3.0f, 3.0f));
+  EXPECT_EQ(5.0f, CallF(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(-1.0f, CallF(test->entry(), -3.0f, -1.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -3.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, -5.0f));
+
+  float qNAN = std::numeric_limits<float>::quiet_NaN();
+  EXPECT_EQ(3.0f, CallF(test->entry(), 3.0f, qNAN));
+  EXPECT_EQ(3.0f, CallF(test->entry(), qNAN, 3.0f));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), -3.0f, qNAN));
+  EXPECT_EQ(-3.0f, CallF(test->entry(), qNAN, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleEqual, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ feqs(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleEqual, test) {
+  EXPECT_DISASSEMBLY(
+      "a0b52553 feq.s a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0f, 3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, 1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, 3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, -1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
+
+  float qNAN = std::numeric_limits<float>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleLessThan, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ flts(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleLessThan, test) {
+  EXPECT_DISASSEMBLY(
+      "a0b51553 flt.s a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, 3.0f));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
+
+  float qNAN = std::numeric_limits<float>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleLessOrEqual, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fles(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleLessOrEqual, test) {
+  EXPECT_DISASSEMBLY(
+      "a0b50553 fle.s a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, 1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0f, 3.0f));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0f, 5.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -1.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, -5.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 3.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, 5.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, -1.0f));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0f, -3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, -5.0f));
+
+  float qNAN = std::numeric_limits<float>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0f, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0f));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleClassify, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fclasss(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleClassify, test) {
+  EXPECT_DISASSEMBLY(
+      "e0051553 fclass.s a0, fa0\n"
+      "00008067 ret\n");
+  // Neg infinity
+  EXPECT_EQ(1 << 0,
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+  // Neg normal
+  EXPECT_EQ(1 << 1, CallI(test->entry(), -1.0f));
+  // Neg subnormal
+  EXPECT_EQ(1 << 2,
+            CallI(test->entry(), -std::numeric_limits<float>::min() / 2.0f));
+  // Neg zero
+  EXPECT_EQ(1 << 3, CallI(test->entry(), -0.0f));
+  // Pos zero
+  EXPECT_EQ(1 << 4, CallI(test->entry(), 0.0f));
+  // Pos subnormal
+  EXPECT_EQ(1 << 5,
+            CallI(test->entry(), std::numeric_limits<float>::min() / 2.0f));
+  // Pos normal
+  EXPECT_EQ(1 << 6, CallI(test->entry(), 1.0f));
+  // Pos infinity
+  EXPECT_EQ(1 << 7,
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  // Signaling NaN
+  EXPECT_EQ(1 << 8,
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+  // Queit NaN
+  EXPECT_EQ(1 << 9,
+            CallI(test->entry(), std::numeric_limits<float>::quiet_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0050553 fcvt.w.s a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, CallI(test->entry(), static_cast<float>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), static_cast<float>(kMinInt32)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<float>(kMaxInt32)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<float>(kMaxUint32)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), static_cast<float>(kMinInt64)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<float>(kMaxInt64)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<float>(kMaxUint64)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RNE, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0, RNE);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord_RNE, test) {
+  EXPECT_DISASSEMBLY(
+      "c0050553 fcvt.w.s a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0f));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6f));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RTZ, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0, RTZ);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord_RTZ, test) {
+  EXPECT_DISASSEMBLY(
+      "c0051553 fcvt.w.s a0, fa0, rtz\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-43, CallI(test->entry(), -43.6f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.5f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.6f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0f));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.6f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.6f));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RDN, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0, RDN);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord_RDN, test) {
+  EXPECT_DISASSEMBLY(
+      "c0052553 fcvt.w.s a0, fa0, rdn\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.4f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.5f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.4f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0f));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.6f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.6f));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RUP, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0, RUP);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord_RUP, test) {
+  EXPECT_DISASSEMBLY(
+      "c0053553 fcvt.w.s a0, fa0, rup\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-43, CallI(test->entry(), -43.6f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.5f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.6f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0f));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.4f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.5f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6f));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToWord_RMM, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtws(A0, FA0, RMM);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToWord_RMM, test) {
+  EXPECT_DISASSEMBLY(
+      "c0054553 fcvt.w.s a0, fa0, rmm\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6f));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4f));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6f));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.5f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4f));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0f));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0f));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0f));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.5f));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0f));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5f));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6f));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtwus(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0150553 fcvt.wu.s a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), static_cast<float>(kMinInt32)));
+  // float loss of precision
+  EXPECT_EQ(-2147483648, CallI(test->entry(), static_cast<float>(kMaxInt32)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<float>(kMaxUint32)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), static_cast<float>(kMinInt64)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<float>(kMaxInt64)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<float>(kMaxUint64)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertWordToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtsw(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertWordToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "d0050553 fcvt.s.w fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42.0f, CallF(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<float>(kMinInt32),
+            CallF(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<float>(kMaxInt32),
+            CallF(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(-1.0f, CallF(test->entry(), sign_extend(kMaxUint32)));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertUnsignedWordToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtswu(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertUnsignedWordToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "d0150553 fcvt.s.wu fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(
+      static_cast<float>(static_cast<uint32_t>(static_cast<int32_t>(-42))),
+      CallF(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint32_t>(kMinInt32)),
+            CallF(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<float>(kMaxInt32),
+            CallF(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<float>(kMaxUint32),
+            CallF(test->entry(), sign_extend(kMaxUint32)));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleMove, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvs(FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleMove, test) {
+  EXPECT_DISASSEMBLY(
+      "20b58553 fmv.s fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(36.0f, CallF(test->entry(), 42.0f, 36.0f));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), -std::numeric_limits<float>::infinity(),
+                  std::numeric_limits<float>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleAbsoluteValue, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fabss(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleAbsoluteValue, test) {
+  EXPECT_DISASSEMBLY(
+      "20a52553 fabs.s fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), 0.0f));
+  EXPECT_EQ(0.0f, CallF(test->entry(), -0.0f));
+  EXPECT_EQ(42.0f, CallF(test->entry(), 42.0f));
+  EXPECT_EQ(42.0f, CallF(test->entry(), -42.0f));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), -std::numeric_limits<float>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleNegate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnegs(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleNegate, test) {
+  EXPECT_DISASSEMBLY(
+      "20a51553 fneg.s fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-0.0f, CallF(test->entry(), 0.0f));
+  EXPECT_EQ(0.0f, CallF(test->entry(), -0.0f));
+  EXPECT_EQ(-42.0f, CallF(test->entry(), 42.0f));
+  EXPECT_EQ(42.0f, CallF(test->entry(), -42.0f));
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), -std::numeric_limits<float>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(BitCastSingleToInteger, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvxw(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BitCastSingleToInteger, test) {
+  EXPECT_DISASSEMBLY(
+      "e0050553 fmv.x.w a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(bit_cast<int32_t>(0.0f), CallI(test->entry(), 0.0f));
+  EXPECT_EQ(bit_cast<int32_t>(-0.0f), CallI(test->entry(), -0.0f));
+  EXPECT_EQ(bit_cast<int32_t>(42.0f), CallI(test->entry(), 42.0f));
+  EXPECT_EQ(bit_cast<int32_t>(-42.0f), CallI(test->entry(), -42.0f));
+  EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()),
+            CallI(test->entry(), std::numeric_limits<float>::quiet_NaN()));
+  EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::signaling_NaN()),
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+  EXPECT_EQ(bit_cast<int32_t>(std::numeric_limits<float>::infinity()),
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(bit_cast<int32_t>(-std::numeric_limits<float>::infinity()),
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(BitCastIntegerToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvwx(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BitCastIntegerToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "f0050553 fmv.w.x fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(0.0f))));
+  EXPECT_EQ(-0.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(-0.0f))));
+  EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(bit_cast<int32_t>(42.0f))));
+  EXPECT_EQ(-42.0f,
+            CallF(test->entry(), sign_extend(bit_cast<int32_t>(-42.0f))));
+  EXPECT_EQ(true, isnan(CallF(test->entry(),
+                              sign_extend(bit_cast<int32_t>(
+                                  std::numeric_limits<float>::quiet_NaN())))));
+  EXPECT_EQ(true,
+            isnan(CallF(test->entry(),
+                        sign_extend(bit_cast<int32_t>(
+                            std::numeric_limits<float>::signaling_NaN())))));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), sign_extend(bit_cast<int32_t>(
+                                     std::numeric_limits<float>::infinity()))));
+  EXPECT_EQ(
+      -std::numeric_limits<float>::infinity(),
+      CallF(test->entry(), sign_extend(bit_cast<int32_t>(
+                               -std::numeric_limits<float>::infinity()))));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(ConvertSingleToDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtls(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0250553 fcvt.l.s a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, CallI(test->entry(), static_cast<float>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
+  EXPECT_EQ(static_cast<int64_t>(kMinInt32),
+            CallI(test->entry(), static_cast<float>(kMinInt32)));
+  // float loses precision:
+  EXPECT_EQ(static_cast<int64_t>(kMaxInt32) + 1,
+            CallI(test->entry(), static_cast<float>(kMaxInt32)));
+  EXPECT_EQ(static_cast<int64_t>(kMaxUint32) + 1,
+            CallI(test->entry(), static_cast<float>(kMaxUint32)));
+  EXPECT_EQ(kMinInt64, CallI(test->entry(), static_cast<float>(kMinInt64)));
+  EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<float>(kMaxInt64)));
+  EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<float>(kMaxUint64)));
+  EXPECT_EQ(kMinInt64,
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(kMaxInt64,
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(kMaxInt64,
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertSingleToUnsignedDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtlus(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertSingleToUnsignedDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c0350553 fcvt.lu.s a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<float>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<float>(42)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), static_cast<float>(kMinInt32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt32) + 1),
+            CallI(test->entry(), static_cast<float>(kMaxInt32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint32) + 1),
+            CallI(test->entry(), static_cast<float>(kMaxUint32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), static_cast<float>(kMinInt64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt64) + 1),
+            CallI(test->entry(), static_cast<float>(kMaxInt64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), static_cast<float>(kMaxUint64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), -std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), std::numeric_limits<float>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleWordToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtsl(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleWordToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "d0250553 fcvt.s.l fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
+  EXPECT_EQ(-42.0f, CallF(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(static_cast<float>(kMinInt32),
+            CallF(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<float>(kMaxInt32),
+            CallF(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<float>(sign_extend(kMaxUint32)),
+            CallF(test->entry(), sign_extend(kMaxUint32)));
+  EXPECT_EQ(static_cast<float>(kMinInt64),
+            CallF(test->entry(), sign_extend(kMinInt64)));
+  EXPECT_EQ(static_cast<float>(kMaxInt64),
+            CallF(test->entry(), sign_extend(kMaxInt64)));
+  EXPECT_EQ(static_cast<float>(sign_extend(kMaxUint64)),
+            CallF(test->entry(), sign_extend(kMaxUint64)));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertUnsignedDoubleWordToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtslu(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertUnsignedDoubleWordToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "d0350553 fcvt.s.lu fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0f, CallF(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(-42))),
+            CallF(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMinInt32))),
+            CallF(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxInt32))),
+            CallF(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxUint32))),
+            CallF(test->entry(), sign_extend(kMaxUint32)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMinInt64))),
+            CallF(test->entry(), sign_extend(kMinInt64)));
+  EXPECT_EQ(static_cast<float>(static_cast<uint64_t>(sign_extend(kMaxInt64))),
+            CallF(test->entry(), sign_extend(kMaxInt64)));
+  EXPECT_EQ(static_cast<float>(kMaxUint64),
+            CallF(test->entry(), sign_extend(kMaxUint64)));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(LoadDoubleFloat, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fld(FA0, Address(A0, 1 * sizeof(double)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadDoubleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "00853507 fld fa0, 8(a0)\n"
+      "00008067 ret\n");
+
+  double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
+  data[0] = 1.7;
+  data[1] = 2.8;
+  data[2] = 3.9;
+  EXPECT_EQ(data[1], CallD(test->entry(), reinterpret_cast<intx_t>(data)));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreDoubleFloat, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsd(FA0, Address(A0, 1 * sizeof(double)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(StoreDoubleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "00a53427 fsd fa0, 8(a0)\n"
+      "00008067 ret\n");
+
+  double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
+  data[0] = 1.7;
+  data[1] = 2.8;
+  data[2] = 3.9;
+  CallD(test->entry(), reinterpret_cast<intx_t>(data), 4.2);
+  EXPECT_EQ(4.2, data[1]);
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMultiplyAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmaddd(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMultiplyAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "62b50543 fmadd.d fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(22.0, CallD(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(26.0, CallD(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(-16.0, CallD(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(16.0, CallD(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMultiplySubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmsubd(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMultiplySubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "62b50547 fmsub.d fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(-22.0, CallD(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(22.0, CallD(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(16.0, CallD(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(-26.0, CallD(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(26.0, CallD(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleNegateMultiplySubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnmsubd(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleNegateMultiplySubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "62b5054b fnmsub.d fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(22.0, CallD(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(22.0, CallD(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(26.0, CallD(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(26.0, CallD(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleNegateMultiplyAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnmaddd(FA0, FA0, FA1, FA2);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleNegateMultiplyAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "62b5054f fnmadd.d fa0, fa0, fa1, fa2\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-22.0, CallD(test->entry(), 3.0, 5.0, 7.0));
+  EXPECT_EQ(8.0, CallD(test->entry(), -3.0, 5.0, 7.0));
+  EXPECT_EQ(8.0, CallD(test->entry(), 3.0, -5.0, 7.0));
+  EXPECT_EQ(-8.0, CallD(test->entry(), 3.0, 5.0, -7.0));
+
+  EXPECT_EQ(-26.0, CallD(test->entry(), 7.0, 3.0, 5.0));
+  EXPECT_EQ(16.0, CallD(test->entry(), -7.0, 3.0, 5.0));
+  EXPECT_EQ(16.0, CallD(test->entry(), 7.0, -3.0, 5.0));
+  EXPECT_EQ(-16.0, CallD(test->entry(), 7.0, 3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleAdd, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ faddd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "02b50553 fadd.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(8.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(2.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-2.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, -5.0));
+
+  EXPECT_EQ(10.0, CallD(test->entry(), 7.0, 3.0));
+  EXPECT_EQ(-4.0, CallD(test->entry(), -7.0, 3.0));
+  EXPECT_EQ(4.0, CallD(test->entry(), 7.0, -3.0));
+  EXPECT_EQ(-10.0, CallD(test->entry(), -7.0, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleSubtract, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsubd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleSubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "0ab50553 fsub.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-2.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(-8.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(8.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(2.0, CallD(test->entry(), -3.0, -5.0));
+
+  EXPECT_EQ(4.0, CallD(test->entry(), 7.0, 3.0));
+  EXPECT_EQ(-10.0, CallD(test->entry(), -7.0, 3.0));
+  EXPECT_EQ(10.0, CallD(test->entry(), 7.0, -3.0));
+  EXPECT_EQ(-4.0, CallD(test->entry(), -7.0, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMultiply, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmuld(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMultiply, test) {
+  EXPECT_DISASSEMBLY(
+      "12b50553 fmul.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(15.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(-15.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-15.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(15.0, CallD(test->entry(), -3.0, -5.0));
+
+  EXPECT_EQ(21.0, CallD(test->entry(), 7.0, 3.0));
+  EXPECT_EQ(-21.0, CallD(test->entry(), -7.0, 3.0));
+  EXPECT_EQ(-21.0, CallD(test->entry(), 7.0, -3.0));
+  EXPECT_EQ(21.0, CallD(test->entry(), -7.0, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleDivide, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fdivd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleDivide, test) {
+  EXPECT_DISASSEMBLY(
+      "1ab50553 fdiv.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(2.0, CallD(test->entry(), 10.0, 5.0));
+  EXPECT_EQ(-2.0, CallD(test->entry(), -10.0, 5.0));
+  EXPECT_EQ(-2.0, CallD(test->entry(), 10.0, -5.0));
+  EXPECT_EQ(2.0, CallD(test->entry(), -10.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleSquareRoot, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsqrtd(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleSquareRoot, test) {
+  EXPECT_DISASSEMBLY(
+      "5a050553 fsqrt.d fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), 0.0));
+  EXPECT_EQ(1.0, CallD(test->entry(), 1.0));
+  EXPECT_EQ(2.0, CallD(test->entry(), 4.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 9.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "22b50553 fsgnj.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleNegatedSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjnd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleNegatedSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "22b51553 fsgnjn.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), -3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleXorSignInject, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fsgnjxd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleXorSignInject, test) {
+  EXPECT_DISASSEMBLY(
+      "22b52553 fsgnjx.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), -3.0, -5.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMin, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmind(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMin, test) {
+  EXPECT_DISASSEMBLY(
+      "2ab50553 fmin.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(1.0, CallD(test->entry(), 3.0, 1.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(-1.0, CallD(test->entry(), 3.0, -1.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), 3.0, -3.0));
+  EXPECT_EQ(-5.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 1.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 3.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -1.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
+  EXPECT_EQ(-5.0, CallD(test->entry(), -3.0, -5.0));
+
+  double qNAN = std::numeric_limits<double>::quiet_NaN();
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, qNAN));
+  EXPECT_EQ(3.0, CallD(test->entry(), qNAN, 3.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, qNAN));
+  EXPECT_EQ(-3.0, CallD(test->entry(), qNAN, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMax, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmaxd(FA0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMax, test) {
+  EXPECT_DISASSEMBLY(
+      "2ab51553 fmax.d fa0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 1.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, 3.0));
+  EXPECT_EQ(5.0, CallD(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -1.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -3.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(1.0, CallD(test->entry(), -3.0, 1.0));
+  EXPECT_EQ(3.0, CallD(test->entry(), -3.0, 3.0));
+  EXPECT_EQ(5.0, CallD(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(-1.0, CallD(test->entry(), -3.0, -1.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -3.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, -5.0));
+
+  double qNAN = std::numeric_limits<double>::quiet_NaN();
+  EXPECT_EQ(3.0, CallD(test->entry(), 3.0, qNAN));
+  EXPECT_EQ(3.0, CallD(test->entry(), qNAN, 3.0));
+  EXPECT_EQ(-3.0, CallD(test->entry(), -3.0, qNAN));
+  EXPECT_EQ(-3.0, CallD(test->entry(), qNAN, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleToSingle, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtsd(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleToSingle, test) {
+  EXPECT_DISASSEMBLY(
+      "40150553 fcvt.s.d fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0f, CallF(test->entry(), 0.0));
+  EXPECT_EQ(42.0f, CallF(test->entry(), 42.0));
+  EXPECT_EQ(-42.0f, CallF(test->entry(), -42.0));
+  EXPECT_EQ(true, isnan(CallF(test->entry(),
+                              std::numeric_limits<double>::quiet_NaN())));
+  EXPECT_EQ(true, isnan(CallF(test->entry(),
+                              std::numeric_limits<double>::signaling_NaN())));
+  EXPECT_EQ(std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(),
+            CallF(test->entry(), -std::numeric_limits<double>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(SingleToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtds(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SingleToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "42050553 fcvt.d.s fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), 0.0f));
+  EXPECT_EQ(42.0, CallD(test->entry(), 42.0f));
+  EXPECT_EQ(-42.0, CallD(test->entry(), -42.0f));
+  EXPECT_EQ(true, isnan(CallD(test->entry(),
+                              std::numeric_limits<float>::quiet_NaN())));
+  EXPECT_EQ(true, isnan(CallD(test->entry(),
+                              std::numeric_limits<float>::signaling_NaN())));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), std::numeric_limits<float>::infinity()));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), -std::numeric_limits<float>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(NaNBoxing, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(NaNBoxing, test) {
+  EXPECT_DISASSEMBLY("00008067 ret\n");
+  EXPECT_EQ(true, isnan(CallD(test->entry(), 42.0f)));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleEqual, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ feqd(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleEqual, test) {
+  EXPECT_DISASSEMBLY(
+      "a2b52553 feq.d a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0, 3.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, 1.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, 3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, -1.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
+
+  double qNAN = std::numeric_limits<double>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleLessThan, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fltd(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleLessThan, test) {
+  EXPECT_DISASSEMBLY(
+      "a2b51553 flt.d a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, 3.0));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
+
+  double qNAN = std::numeric_limits<double>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleLessOrEqual, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fled(A0, FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleLessOrEqual, test) {
+  EXPECT_DISASSEMBLY(
+      "a2b50553 fle.d a0, fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, 1.0));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0, 3.0));
+  EXPECT_EQ(1, CallI(test->entry(), 3.0, 5.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -1.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, -5.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 1.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 3.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, 5.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, -1.0));
+  EXPECT_EQ(1, CallI(test->entry(), -3.0, -3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, -5.0));
+
+  double qNAN = std::numeric_limits<double>::quiet_NaN();
+  EXPECT_EQ(0, CallI(test->entry(), 3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, 3.0));
+  EXPECT_EQ(0, CallI(test->entry(), -3.0, qNAN));
+  EXPECT_EQ(0, CallI(test->entry(), qNAN, -3.0));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleClassify, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fclassd(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleClassify, test) {
+  EXPECT_DISASSEMBLY(
+      "e2051553 fclass.d a0, fa0\n"
+      "00008067 ret\n");
+  // Neg infinity
+  EXPECT_EQ(1 << 0,
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+  // Neg normal
+  EXPECT_EQ(1 << 1, CallI(test->entry(), -1.0));
+  // Neg subnormal
+  EXPECT_EQ(1 << 2,
+            CallI(test->entry(), -std::numeric_limits<double>::min() / 2.0));
+  // Neg zero
+  EXPECT_EQ(1 << 3, CallI(test->entry(), -0.0));
+  // Pos zero
+  EXPECT_EQ(1 << 4, CallI(test->entry(), 0.0));
+  // Pos subnormal
+  EXPECT_EQ(1 << 5,
+            CallI(test->entry(), std::numeric_limits<double>::min() / 2.0));
+  // Pos normal
+  EXPECT_EQ(1 << 6, CallI(test->entry(), 1.0));
+  // Pos infinity
+  EXPECT_EQ(1 << 7,
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  // Signaling NaN
+  EXPECT_EQ(1 << 8,
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+  // Queit NaN
+  EXPECT_EQ(1 << 9,
+            CallI(test->entry(), std::numeric_limits<double>::quiet_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtwd(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c2050553 fcvt.w.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, CallI(test->entry(), static_cast<double>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), static_cast<double>(kMinInt32)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxInt32)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxUint32)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), static_cast<double>(kMinInt64)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxInt64)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxUint64)));
+  EXPECT_EQ(sign_extend(kMinInt32),
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToUnsignedWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtwud(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToUnsignedWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c2150553 fcvt.wu.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), static_cast<double>(kMinInt32)));
+  EXPECT_EQ(sign_extend(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxInt32)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<double>(kMaxUint32)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), static_cast<double>(kMinInt64)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<double>(kMaxInt64)));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), static_cast<double>(kMaxUint64)));
+  EXPECT_EQ(sign_extend(0),
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(sign_extend(kMaxUint32),
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertWordToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtdw(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertWordToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "d2050553 fcvt.d.w fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42.0, CallD(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<double>(kMinInt32),
+            CallD(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<double>(kMaxInt32),
+            CallD(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(-1.0, CallD(test->entry(), sign_extend(kMaxUint32)));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertUnsignedWordToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtdwu(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertUnsignedWordToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "d2150553 fcvt.d.wu fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(
+      static_cast<double>(static_cast<uint32_t>(static_cast<int32_t>(-42))),
+      CallD(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint32_t>(kMinInt32)),
+            CallD(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<double>(kMaxInt32),
+            CallD(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<double>(kMaxUint32),
+            CallD(test->entry(), sign_extend(kMaxUint32)));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleMove, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvd(FA0, FA1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleMove, test) {
+  EXPECT_DISASSEMBLY(
+      "22b58553 fmv.d fa0, fa1\n"
+      "00008067 ret\n");
+  EXPECT_EQ(36.0, CallD(test->entry(), 42.0, 36.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), -std::numeric_limits<double>::infinity(),
+                  std::numeric_limits<double>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleAbsoluteValue, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fabsd(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleAbsoluteValue, test) {
+  EXPECT_DISASSEMBLY(
+      "22a52553 fabs.d fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), 0.0));
+  EXPECT_EQ(0.0, CallD(test->entry(), -0.0));
+  EXPECT_EQ(42.0, CallD(test->entry(), 42.0));
+  EXPECT_EQ(42.0, CallD(test->entry(), -42.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), -std::numeric_limits<double>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(DoubleNegate, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fnegd(FA0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(DoubleNegate, test) {
+  EXPECT_DISASSEMBLY(
+      "22a51553 fneg.d fa0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-0.0, CallD(test->entry(), 0.0));
+  EXPECT_EQ(0.0, CallD(test->entry(), -0.0));
+  EXPECT_EQ(-42.0, CallD(test->entry(), 42.0));
+  EXPECT_EQ(42.0, CallD(test->entry(), -42.0));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(), -std::numeric_limits<double>::infinity()));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c2250553 fcvt.l.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-42, CallI(test->entry(), static_cast<double>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
+  EXPECT_EQ(static_cast<int64_t>(kMinInt32),
+            CallI(test->entry(), static_cast<double>(kMinInt32)));
+  EXPECT_EQ(static_cast<int64_t>(kMaxInt32),
+            CallI(test->entry(), static_cast<double>(kMaxInt32)));
+  EXPECT_EQ(static_cast<int64_t>(kMaxUint32),
+            CallI(test->entry(), static_cast<double>(kMaxUint32)));
+  EXPECT_EQ(kMinInt64, CallI(test->entry(), static_cast<double>(kMinInt64)));
+  EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<double>(kMaxInt64)));
+  EXPECT_EQ(kMaxInt64, CallI(test->entry(), static_cast<double>(kMaxUint64)));
+  EXPECT_EQ(kMinInt64,
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(kMaxInt64,
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(kMaxInt64,
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RNE, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0, RNE);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RNE, test) {
+  EXPECT_DISASSEMBLY(
+      "c2250553 fcvt.l.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RTZ, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0, RTZ);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RTZ, test) {
+  EXPECT_DISASSEMBLY(
+      "c2251553 fcvt.l.d a0, fa0, rtz\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-43, CallI(test->entry(), -43.6));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.5));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.6));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5));
+  EXPECT_EQ(42, CallI(test->entry(), 42.6));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4));
+  EXPECT_EQ(43, CallI(test->entry(), 43.5));
+  EXPECT_EQ(43, CallI(test->entry(), 43.6));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RDN, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0, RDN);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RDN, test) {
+  EXPECT_DISASSEMBLY(
+      "c2252553 fcvt.l.d a0, fa0, rdn\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.4));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.5));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.4));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4));
+  EXPECT_EQ(42, CallI(test->entry(), 42.5));
+  EXPECT_EQ(42, CallI(test->entry(), 42.6));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4));
+  EXPECT_EQ(43, CallI(test->entry(), 43.5));
+  EXPECT_EQ(43, CallI(test->entry(), 43.6));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RUP, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0, RUP);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RUP, test) {
+  EXPECT_DISASSEMBLY(
+      "c2253553 fcvt.l.d a0, fa0, rup\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-43, CallI(test->entry(), -43.6));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.5));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.6));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.5));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0));
+  EXPECT_EQ(43, CallI(test->entry(), 42.4));
+  EXPECT_EQ(43, CallI(test->entry(), 42.5));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToDoubleWord_RMM, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtld(A0, FA0, RMM);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToDoubleWord_RMM, test) {
+  EXPECT_DISASSEMBLY(
+      "c2254553 fcvt.l.d a0, fa0, rmm\n"
+      "00008067 ret\n");
+  EXPECT_EQ(-44, CallI(test->entry(), -43.6));
+  EXPECT_EQ(-44, CallI(test->entry(), -43.5));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.4));
+  EXPECT_EQ(-43, CallI(test->entry(), -43.0));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.6));
+  EXPECT_EQ(-43, CallI(test->entry(), -42.5));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.4));
+  EXPECT_EQ(-42, CallI(test->entry(), -42.0));
+  EXPECT_EQ(0, CallI(test->entry(), -0.0));
+  EXPECT_EQ(0, CallI(test->entry(), +0.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.0));
+  EXPECT_EQ(42, CallI(test->entry(), 42.4));
+  EXPECT_EQ(43, CallI(test->entry(), 42.5));
+  EXPECT_EQ(43, CallI(test->entry(), 42.6));
+  EXPECT_EQ(43, CallI(test->entry(), 43.0));
+  EXPECT_EQ(43, CallI(test->entry(), 43.4));
+  EXPECT_EQ(44, CallI(test->entry(), 43.5));
+  EXPECT_EQ(44, CallI(test->entry(), 43.6));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleToUnsignedDoubleWord, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtlud(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleToUnsignedDoubleWord, test) {
+  EXPECT_DISASSEMBLY(
+      "c2350553 fcvt.lu.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(-42)));
+  EXPECT_EQ(0, CallI(test->entry(), static_cast<double>(0)));
+  EXPECT_EQ(42, CallI(test->entry(), static_cast<double>(42)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), static_cast<double>(kMinInt32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt32)),
+            CallI(test->entry(), static_cast<double>(kMaxInt32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint32)),
+            CallI(test->entry(), static_cast<double>(kMaxUint32)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), static_cast<double>(kMinInt64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxInt64) + 1),
+            CallI(test->entry(), static_cast<double>(kMaxInt64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), static_cast<double>(kMaxUint64)));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(0)),
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(static_cast<int64_t>(static_cast<uint64_t>(kMaxUint64)),
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+}
+
+ASSEMBLER_TEST_GENERATE(BitCastDoubleToInteger, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvxd(A0, FA0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BitCastDoubleToInteger, test) {
+  EXPECT_DISASSEMBLY(
+      "e2050553 fmv.x.d a0, fa0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(bit_cast<int64_t>(0.0), CallI(test->entry(), 0.0));
+  EXPECT_EQ(bit_cast<int64_t>(-0.0), CallI(test->entry(), -0.0));
+  EXPECT_EQ(bit_cast<int64_t>(42.0), CallI(test->entry(), 42.0));
+  EXPECT_EQ(bit_cast<int64_t>(-42.0), CallI(test->entry(), -42.0));
+  EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::quiet_NaN()),
+            CallI(test->entry(), std::numeric_limits<double>::quiet_NaN()));
+  EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::signaling_NaN()),
+            CallI(test->entry(), std::numeric_limits<double>::signaling_NaN()));
+  EXPECT_EQ(bit_cast<int64_t>(std::numeric_limits<double>::infinity()),
+            CallI(test->entry(), std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(bit_cast<int64_t>(-std::numeric_limits<double>::infinity()),
+            CallI(test->entry(), -std::numeric_limits<double>::infinity()));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertDoubleWordToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtdl(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertDoubleWordToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "d2250553 fcvt.d.l fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
+  EXPECT_EQ(-42.0, CallD(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(static_cast<double>(kMinInt32),
+            CallD(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<double>(kMaxInt32),
+            CallD(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<double>(sign_extend(kMaxUint32)),
+            CallD(test->entry(), sign_extend(kMaxUint32)));
+  EXPECT_EQ(static_cast<double>(kMinInt64),
+            CallD(test->entry(), sign_extend(kMinInt64)));
+  EXPECT_EQ(static_cast<double>(kMaxInt64),
+            CallD(test->entry(), sign_extend(kMaxInt64)));
+  EXPECT_EQ(static_cast<double>(sign_extend(kMaxUint64)),
+            CallD(test->entry(), sign_extend(kMaxUint64)));
+}
+
+ASSEMBLER_TEST_GENERATE(ConvertUnsignedDoubleWordToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fcvtdlu(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(ConvertUnsignedDoubleWordToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "d2350553 fcvt.d.lu fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), sign_extend(0)));
+  EXPECT_EQ(42.0, CallD(test->entry(), sign_extend(42)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(-42))),
+            CallD(test->entry(), sign_extend(-42)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMinInt32))),
+            CallD(test->entry(), sign_extend(kMinInt32)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxInt32))),
+            CallD(test->entry(), sign_extend(kMaxInt32)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxUint32))),
+            CallD(test->entry(), sign_extend(kMaxUint32)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMinInt64))),
+            CallD(test->entry(), sign_extend(kMinInt64)));
+  EXPECT_EQ(static_cast<double>(static_cast<uint64_t>(sign_extend(kMaxInt64))),
+            CallD(test->entry(), sign_extend(kMaxInt64)));
+  EXPECT_EQ(static_cast<double>(kMaxUint64),
+            CallD(test->entry(), sign_extend(kMaxUint64)));
+}
+
+ASSEMBLER_TEST_GENERATE(BitCastIntegerToDouble, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  __ fmvdx(FA0, A0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(BitCastIntegerToDouble, test) {
+  EXPECT_DISASSEMBLY(
+      "f2050553 fmv.d.x fa0, a0\n"
+      "00008067 ret\n");
+  EXPECT_EQ(0.0, CallD(test->entry(), bit_cast<int64_t>(0.0)));
+  EXPECT_EQ(-0.0, CallD(test->entry(), bit_cast<int64_t>(-0.0)));
+  EXPECT_EQ(42.0, CallD(test->entry(), bit_cast<int64_t>(42.0)));
+  EXPECT_EQ(-42.0, CallD(test->entry(), bit_cast<int64_t>(-42.0)));
+  EXPECT_EQ(true, isnan(CallD(test->entry(),
+                              bit_cast<int64_t>(
+                                  std::numeric_limits<double>::quiet_NaN()))));
+  EXPECT_EQ(true,
+            isnan(CallD(test->entry(),
+                        bit_cast<int64_t>(
+                            std::numeric_limits<double>::signaling_NaN()))));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            CallD(test->entry(),
+                  bit_cast<int64_t>(std::numeric_limits<double>::infinity())));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            CallD(test->entry(),
+                  bit_cast<int64_t>(-std::numeric_limits<double>::infinity())));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(Fibonacci, assembler) {
+  FLAG_use_compressed_instructions = false;
+  __ SetExtensions(RV_G);
+  Label fib, base, done;
+  __ Bind(&fib);
+  __ subi(SP, SP, sizeof(uintx_t) * 4);
+  __ sx(RA, Address(SP, 3 * sizeof(uintx_t)));
+  __ sx(A0, Address(SP, 2 * sizeof(uintx_t)));
+  __ subi(A0, A0, 1);
+  __ blez(A0, &base);
+
+  __ jal(&fib);
+  __ sx(A0, Address(SP, 1 * sizeof(uintx_t)));
+  __ lx(A0, Address(SP, 2 * sizeof(uintx_t)));
+  __ subi(A0, A0, 2);
+  __ jal(&fib);
+  __ lx(A1, Address(SP, 1 * sizeof(uintx_t)));
+  __ add(A0, A0, A1);
+  __ j(&done);
+
+  __ Bind(&base);
+  __ li(A0, 1);
+
+  __ Bind(&done);
+  __ lx(RA, Address(SP, 3 * sizeof(uintx_t)));
+  __ addi(SP, SP, sizeof(uintx_t) * 4);
+  __ ret();
+  __ trap();
+}
+ASSEMBLER_TEST_RUN(Fibonacci, test) {
+#if XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "ff010113 addi sp, sp, -16\n"
+      "00112623 sw ra, 12(sp)\n"
+      "00a12423 sw a0, 8(sp)\n"
+      "fff50513 addi a0, a0, -1\n"
+      "02a05263 blez a0, +36\n"
+      "fedff0ef jal -20\n"
+      "00a12223 sw a0, 4(sp)\n"
+      "00812503 lw a0, 8(sp)\n"
+      "ffe50513 addi a0, a0, -2\n"
+      "fddff0ef jal -36\n"
+      "00412583 lw a1, 4(sp)\n"
+      "00b50533 add a0, a0, a1\n"
+      "0080006f j +8\n"
+      "00100513 li a0, 1\n"
+      "00c12083 lw ra, 12(sp)\n"
+      "01010113 addi sp, sp, 16\n"
+      "00008067 ret\n"
+      "00000000 trap\n");
+#elif XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "fe010113 addi sp, sp, -32\n"
+      "00113c23 sd ra, 24(sp)\n"
+      "00a13823 sd a0, 16(sp)\n"
+      "fff50513 addi a0, a0, -1\n"
+      "02a05263 blez a0, +36\n"
+      "fedff0ef jal -20\n"
+      "00a13423 sd a0, 8(sp)\n"
+      "01013503 ld a0, 16(sp)\n"
+      "ffe50513 addi a0, a0, -2\n"
+      "fddff0ef jal -36\n"
+      "00813583 ld a1, 8(sp)\n"
+      "00b50533 add a0, a0, a1\n"
+      "0080006f j +8\n"
+      "00100513 li a0, 1\n"
+      "01813083 ld ra, 24(sp)\n"
+      "02010113 addi sp, sp, 32\n"
+      "00008067 ret\n"
+      "00000000 trap\n");
+#else
+#error Unimplemented
+#endif
+  EXPECT_EQ(1, Call(test->entry(), 0));
+  EXPECT_EQ(1, Call(test->entry(), 1));
+  EXPECT_EQ(2, Call(test->entry(), 2));
+  EXPECT_EQ(3, Call(test->entry(), 3));
+  EXPECT_EQ(5, Call(test->entry(), 4));
+  EXPECT_EQ(8, Call(test->entry(), 5));
+  EXPECT_EQ(13, Call(test->entry(), 6));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreWordSP_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  __ subi(SP, SP, 256);
+  __ sw(A1, Address(SP, 0));
+  __ lw(A0, Address(SP, 0));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreWordSP_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    c02e sw a1, 0(sp)\n"
+      "    4502 lw a0, 0(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(sign_extend(0xAB010203), Call(test->entry(), 0, 0xAB010203));
+  EXPECT_EQ(sign_extend(0xCD020405), Call(test->entry(), 0, 0xCD020405));
+  EXPECT_EQ(sign_extend(0xEF030607), Call(test->entry(), 0, 0xEF030607));
+}
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreWordSP_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  __ subi(SP, SP, 256);
+  __ sw(A1, Address(SP, 4));
+  __ lw(A0, Address(SP, 4));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreWordSP_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    c22e sw a1, 4(sp)\n"
+      "    4512 lw a0, 4(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(sign_extend(0xAB010203), Call(test->entry(), 0, 0xAB010203));
+  EXPECT_EQ(sign_extend(0xCD020405), Call(test->entry(), 0, 0xCD020405));
+  EXPECT_EQ(sign_extend(0xEF030607), Call(test->entry(), 0, 0xEF030607));
+}
+
+#if XLEN == 32
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreSingleFloatSP_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ fsw(FA1, Address(SP, 0));
+  __ flw(FA0, Address(SP, 0));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreSingleFloatSP_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    e02e fsw fa1, 0(sp)\n"
+      "    6502 flw fa0, 0(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(1.7f, CallF(test->entry(), 0.0f, 1.7f));
+  EXPECT_EQ(2.8f, CallF(test->entry(), 0.0f, 2.8f));
+  EXPECT_EQ(3.9f, CallF(test->entry(), 0.0f, 3.9f));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreSingleFloatSP_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ fsw(FA1, Address(SP, 4));
+  __ flw(FA0, Address(SP, 4));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreSingleFloatSP_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    e22e fsw fa1, 4(sp)\n"
+      "    6512 flw fa0, 4(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(1.7f, CallF(test->entry(), 0.0f, 1.7f));
+  EXPECT_EQ(2.8f, CallF(test->entry(), 0.0f, 2.8f));
+  EXPECT_EQ(3.9f, CallF(test->entry(), 0.0f, 3.9f));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleFloatSP_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ fsd(FA1, Address(SP, 0));
+  __ fld(FA0, Address(SP, 0));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleFloatSP_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    a02e fsd fa1, 0(sp)\n"
+      "    2502 fld fa0, 0(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(1.7, CallD(test->entry(), 0.0, 1.7));
+  EXPECT_EQ(2.8, CallD(test->entry(), 0.0, 2.8));
+  EXPECT_EQ(3.9, CallD(test->entry(), 0.0, 3.9));
+}
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleFloatSP_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ fsd(FA1, Address(SP, 8));
+  __ fld(FA0, Address(SP, 8));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleFloatSP_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    a42e fsd fa1, 8(sp)\n"
+      "    2522 fld fa0, 8(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ(1.7, CallD(test->entry(), 0.0, 1.7));
+  EXPECT_EQ(2.8, CallD(test->entry(), 0.0, 2.8));
+  EXPECT_EQ(3.9, CallD(test->entry(), 0.0, 3.9));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleWordSP_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ sd(A1, Address(SP, 0));
+  __ ld(A0, Address(SP, 0));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleWordSP_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    e02e sd a1, 0(sp)\n"
+      "    6502 ld a0, 0(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ((intx_t)0xAB01020304050607,
+            Call(test->entry(), 0, 0xAB01020304050607));
+  EXPECT_EQ((intx_t)0xCD02040505060708,
+            Call(test->entry(), 0, 0xCD02040505060708));
+  EXPECT_EQ((intx_t)0xEF03060708090A0B,
+            Call(test->entry(), 0, 0xEF03060708090A0B));
+}
+ASSEMBLER_TEST_GENERATE(CompressedLoadStoreDoubleWordSP_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subi(SP, SP, 256);
+  __ sd(A1, Address(SP, 8));
+  __ ld(A0, Address(SP, 8));
+  __ addi(SP, SP, 256);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadStoreDoubleWordSP_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    7111 addi sp, sp, -256\n"
+      "    e42e sd a1, 8(sp)\n"
+      "    6522 ld a0, 8(sp)\n"
+      "    6111 addi sp, sp, 256\n"
+      "    8082 ret\n");
+
+  EXPECT_EQ((intx_t)0xAB01020304050607,
+            Call(test->entry(), 0, 0xAB01020304050607));
+  EXPECT_EQ((intx_t)0xCD02040505060708,
+            Call(test->entry(), 0, 0xCD02040505060708));
+  EXPECT_EQ((intx_t)0xEF03060708090A0B,
+            Call(test->entry(), 0, 0xEF03060708090A0B));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadWord_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ lw(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    4108 lw a0, 0(a0)\n"
+      "    8082 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(-855505915,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(CompressedLoadWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ lw(A0, Address(A0, 4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    4148 lw a0, 4(a0)\n"
+      "    8082 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0xAB010203;
+  values[1] = 0xCD020405;
+  values[2] = 0xEF030607;
+
+  EXPECT_EQ(-285014521,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedStoreWord_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ sw(A1, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    c10c sw a1, 0(a0)\n"
+      "    8082 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD020405);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0xCD020405, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(CompressedStoreWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ sw(A1, Address(A0, 4));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    c14c sw a1, 4(a0)\n"
+      "    8082 ret\n");
+
+  uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF030607);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0xEF030607, values[2]);
+}
+
+#if XLEN == 32
+ASSEMBLER_TEST_GENERATE(CompressedLoadSingleFloat, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ flw(FA0, Address(A0, 1 * sizeof(float)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadSingleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "    6148 flw fa0, 4(a0)\n"
+      "    8082 ret\n");
+
+  float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
+  data[0] = 1.7f;
+  data[1] = 2.8f;
+  data[2] = 3.9f;
+  EXPECT_EQ(data[1], CallF(test->entry(), reinterpret_cast<intx_t>(data)));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedStoreSingleFloat, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ fsw(FA0, Address(A0, 1 * sizeof(float)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreSingleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "    e148 fsw fa0, 4(a0)\n"
+      "    8082 ret\n");
+
+  float* data = reinterpret_cast<float*>(malloc(3 * sizeof(float)));
+  data[0] = 1.7f;
+  data[1] = 2.8f;
+  data[2] = 3.9f;
+  CallF(test->entry(), reinterpret_cast<intx_t>(data), 4.2f);
+  EXPECT_EQ(4.2f, data[1]);
+}
+#endif
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(CompressedLoadDoubleWord_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ ld(A0, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadDoubleWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    6108 ld a0, 0(a0)\n"
+      "    8082 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0xAB01020304050607;
+  values[1] = 0xCD02040505060708;
+  values[2] = 0xEF03060708090A0B;
+
+  EXPECT_EQ(-3674369926375274744,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+ASSEMBLER_TEST_GENERATE(CompressedLoadDoubleWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ ld(A0, Address(A0, 8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadDoubleWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    6508 ld a0, 8(a0)\n"
+      "    8082 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0xAB01020304050607;
+  values[1] = 0xCD02040505060708;
+  values[2] = 0xEF03060708090A0B;
+
+  EXPECT_EQ(-1224128046445295093,
+            Call(test->entry(), reinterpret_cast<intx_t>(&values[1])));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedStoreDoubleWord_0, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ sd(A1, Address(A0, 0));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreDoubleWord_0, test) {
+  EXPECT_DISASSEMBLY(
+      "    e10c sd a1, 0(a0)\n"
+      "    8082 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD02040505060708);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0xCD02040505060708, values[1]);
+  EXPECT_EQ(0u, values[2]);
+}
+ASSEMBLER_TEST_GENERATE(CompressedStoreDoubleWord_Pos, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ sd(A1, Address(A0, 8));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreDoubleWord_Pos, test) {
+  EXPECT_DISASSEMBLY(
+      "    e50c sd a1, 8(a0)\n"
+      "    8082 ret\n");
+
+  uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t)));
+  values[0] = 0;
+  values[1] = 0;
+  values[2] = 0;
+
+  Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF03060708090A0B);
+  EXPECT_EQ(0u, values[0]);
+  EXPECT_EQ(0u, values[1]);
+  EXPECT_EQ(0xEF03060708090A0B, values[2]);
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadDoubleFloat, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ fld(FA0, Address(A0, 1 * sizeof(double)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadDoubleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "    2508 fld fa0, 8(a0)\n"
+      "    8082 ret\n");
+
+  double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
+  data[0] = 1.7;
+  data[1] = 2.8;
+  data[2] = 3.9;
+  EXPECT_EQ(data[1], CallD(test->entry(), reinterpret_cast<intx_t>(data)));
+  free(data);
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedStoreDoubleFloat, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ fsd(FA0, Address(A0, 1 * sizeof(double)));
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedStoreDoubleFloat, test) {
+  EXPECT_DISASSEMBLY(
+      "    a508 fsd fa0, 8(a0)\n"
+      "    8082 ret\n");
+
+  double* data = reinterpret_cast<double*>(malloc(3 * sizeof(double)));
+  data[0] = 1.7;
+  data[1] = 2.8;
+  data[2] = 3.9;
+  CallD(test->entry(), reinterpret_cast<intx_t>(data), 4.2);
+  EXPECT_EQ(4.2, data[1]);
+}
+#endif
+
+#if XLEN == 32
+ASSEMBLER_TEST_GENERATE(CompressedJumpAndLink, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  Label label1, label2;
+  __ mv(T3, RA);
+  __ jal(&label1, Assembler::kNearJump);  // Forward.
+  __ sub(A0, T0, T1);
+  __ mv(RA, T3);
+  __ ret();
+  __ trap();
+
+  __ Bind(&label2);
+  __ mv(T5, RA);
+  __ li(T1, 7);
+  __ jr(T5);
+  __ trap();
+
+  __ Bind(&label1);
+  __ mv(T4, RA);
+  __ li(T0, 4);
+  __ jal(&label2, Assembler::kNearJump);  // Backward.
+  __ mv(RA, T4);
+  __ jr(T4);
+  __ trap();
+}
+ASSEMBLER_TEST_RUN(CompressedJumpAndLink, test) {
+  EXPECT_DISASSEMBLY(
+      "    8e06 mv t3, ra\n"
+      "    2811 jal +20\n"
+      "40628533 sub a0, t0, t1\n"
+      "    80f2 mv ra, t3\n"
+      "    8082 ret\n"
+      "    0000 trap\n"
+      "    8f06 mv t5, ra\n"
+      "    431d li t1, 7\n"
+      "    8f02 jr t5\n"
+      "    0000 trap\n"
+      "    8e86 mv t4, ra\n"
+      "    4291 li t0, 4\n"
+      "    3fd5 jal -12\n"
+      "    80f6 mv ra, t4\n"
+      "    8e82 jr t4\n"
+      "    0000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry()));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(CompressedJump, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label label1, label2;
+  __ j(&label1, Assembler::kNearJump);  // Forward.
+  __ trap();
+  __ Bind(&label2);
+  __ li(T1, 7);
+  __ sub(A0, T0, T1);
+  __ ret();
+  __ Bind(&label1);
+  __ li(T0, 4);
+  __ j(&label2, Assembler::kNearJump);  // Backward.
+  __ trap();
+}
+ASSEMBLER_TEST_RUN(CompressedJump, test) {
+  EXPECT_DISASSEMBLY(
+      "    a031 j +12\n"
+      "    0000 trap\n"
+      "    431d li t1, 7\n"
+      "40628533 sub a0, t0, t1\n"
+      "    8082 ret\n"
+      "    4291 li t0, 4\n"
+      "    bfdd j -10\n"
+      "    0000 trap\n");
+  EXPECT_EQ(-3, Call(test->entry()));
+}
+
+static int CompressedJumpAndLinkRegister_label1 = 0;
+static int CompressedJumpAndLinkRegister_label2 = 0;
+ASSEMBLER_TEST_GENERATE(CompressedJumpAndLinkRegister, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label label1, label2;
+  __ mv(T3, RA);
+  __ jalr(A1);  // Forward.
+  __ sub(A0, T0, T1);
+  __ jr(T3);
+  __ trap();
+
+  __ Bind(&label2);
+  __ mv(T5, RA);
+  __ li(T1, 7);
+  __ jr(T5);
+  __ trap();
+
+  __ Bind(&label1);
+  __ mv(T4, RA);
+  __ li(T0, 4);
+  __ jalr(A2);  // Backward.
+  __ jr(T4);
+  __ trap();
+
+  CompressedJumpAndLinkRegister_label1 = label1.Position();
+  CompressedJumpAndLinkRegister_label2 = label2.Position();
+}
+ASSEMBLER_TEST_RUN(CompressedJumpAndLinkRegister, test) {
+  EXPECT_DISASSEMBLY(
+      "    8e06 mv t3, ra\n"
+      "    9582 jalr a1\n"
+      "40628533 sub a0, t0, t1\n"
+      "    8e02 jr t3\n"
+      "    0000 trap\n"
+      "    8f06 mv t5, ra\n"
+      "    431d li t1, 7\n"
+      "    8f02 jr t5\n"
+      "    0000 trap\n"
+      "    8e86 mv t4, ra\n"
+      "    4291 li t0, 4\n"
+      "    9602 jalr a2\n"
+      "    8e82 jr t4\n"
+      "    0000 trap\n");
+  EXPECT_EQ(-3,
+            Call(test->entry(), 0,
+                 static_cast<intx_t>(test->entry() +
+                                     CompressedJumpAndLinkRegister_label1),
+                 static_cast<intx_t>(test->entry() +
+                                     CompressedJumpAndLinkRegister_label2)));
+}
+
+static int CompressedJumpRegister_label = 0;
+ASSEMBLER_TEST_GENERATE(CompressedJumpRegister, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label label;
+  __ jr(A1);
+  __ trap();
+  __ Bind(&label);
+  __ li(A0, 42);
+  __ ret();
+  CompressedJumpRegister_label = label.Position();
+}
+ASSEMBLER_TEST_RUN(CompressedJumpRegister, test) {
+  EXPECT_DISASSEMBLY(
+      "    8582 jr a1\n"
+      "    0000 trap\n"
+      "02a00513 li a0, 42\n"
+      "    8082 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 0,
+                     static_cast<intx_t>(test->entry() +
+                                         CompressedJumpRegister_label)));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedBranchEqualZero, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label label;
+  __ beqz(A0, &label, Assembler::kNearJump);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedBranchEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "    c119 beqz a0, +6\n"
+      "    450d li a0, 3\n"
+      "    8082 ret\n"
+      "    4511 li a0, 4\n"
+      "    8082 ret\n");
+  EXPECT_EQ(3, Call(test->entry(), -42));
+  EXPECT_EQ(4, Call(test->entry(), 0));
+  EXPECT_EQ(3, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedBranchNotEqualZero, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label label;
+  __ bnez(A0, &label, Assembler::kNearJump);
+  __ li(A0, 3);
+  __ ret();
+  __ Bind(&label);
+  __ li(A0, 4);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedBranchNotEqualZero, test) {
+  EXPECT_DISASSEMBLY(
+      "    e119 bnez a0, +6\n"
+      "    450d li a0, 3\n"
+      "    8082 ret\n"
+      "    4511 li a0, 4\n"
+      "    8082 ret\n");
+  EXPECT_EQ(4, Call(test->entry(), -42));
+  EXPECT_EQ(3, Call(test->entry(), 0));
+  EXPECT_EQ(4, Call(test->entry(), 42));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ li(A0, -7);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    5565 li a0, -7\n"
+      "    8082 ret\n");
+  EXPECT_EQ(-7, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedLoadUpperImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ lui(A0, 7 << 12);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedLoadUpperImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    651d lui a0, 28672\n"
+      "    8082 ret\n");
+  EXPECT_EQ(7 << 12, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAddImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ addi(A0, A0, 19);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAddImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    054d addi a0, a0, 19\n"
+      "    8082 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 23));
+}
+
+#if XLEN == 64
+ASSEMBLER_TEST_GENERATE(CompressedAddImmediateWord, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ addiw(A0, A0, 19);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAddImmediateWord, test) {
+  EXPECT_DISASSEMBLY(
+      "    254d addiw a0, a0, 19\n"
+      "    8082 ret\n");
+  EXPECT_EQ(19, Call(test->entry(), 0xFFFFFFFF00000000));
+  EXPECT_EQ(-237, Call(test->entry(), 0x00000000FFFFFF00));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(CompressedAddImmediateSP16, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ addi(SP, SP, -128);
+  __ addi(SP, SP, +128);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAddImmediateSP16, test) {
+  EXPECT_DISASSEMBLY(
+      "    7119 addi sp, sp, -128\n"
+      "    6109 addi sp, sp, 128\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAddImmediateSP4N, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ addi(A1, SP, 36);
+  __ sub(A0, A1, SP);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAddImmediateSP4N, test) {
+  EXPECT_DISASSEMBLY(
+      "    104c addi a1, sp, 36\n"
+      "40258533 sub a0, a1, sp\n"
+      "    8082 ret\n");
+  EXPECT_EQ(36, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedShiftLeftLogicalImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ slli(A0, A0, 3);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedShiftLeftLogicalImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    050e slli a0, a0, 3\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(336, Call(test->entry(), 42));
+  EXPECT_EQ(15872, Call(test->entry(), 1984));
+  EXPECT_EQ(-336, Call(test->entry(), -42));
+  EXPECT_EQ(-15872, Call(test->entry(), -1984));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedShiftRightLogicalImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ srli(A0, A0, 3);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedShiftRightLogicalImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    810d srli a0, a0, 3\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(5, Call(test->entry(), 42));
+  EXPECT_EQ(248, Call(test->entry(), 1984));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-42) >> 3),
+            Call(test->entry(), -42));
+  EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-1984) >> 3),
+            Call(test->entry(), -1984));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedShiftRightArithmeticImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ srai(A0, A0, 3);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedShiftRightArithmeticImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    850d srai a0, a0, 3\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(5, Call(test->entry(), 42));
+  EXPECT_EQ(248, Call(test->entry(), 1984));
+  EXPECT_EQ(-6, Call(test->entry(), -42));
+  EXPECT_EQ(-248, Call(test->entry(), -1984));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAndImmediate, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ andi(A0, A0, 6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAndImmediate, test) {
+  EXPECT_DISASSEMBLY(
+      "    8919 andi a0, a0, 6\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(2, Call(test->entry(), 43));
+  EXPECT_EQ(0, Call(test->entry(), 1984));
+  EXPECT_EQ(6, Call(test->entry(), -42));
+  EXPECT_EQ(0, Call(test->entry(), -1984));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAndImmediate2, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ andi(A0, A0, -6);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAndImmediate2, test) {
+  EXPECT_DISASSEMBLY(
+      "    9969 andi a0, a0, -6\n"
+      "    8082 ret\n");
+  EXPECT_EQ(0, Call(test->entry(), 0));
+  EXPECT_EQ(42, Call(test->entry(), 43));
+  EXPECT_EQ(1984, Call(test->entry(), 1984));
+  EXPECT_EQ(-46, Call(test->entry(), -42));
+  EXPECT_EQ(-1984, Call(test->entry(), -1984));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedMove, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ mv(A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedMove, test) {
+  EXPECT_DISASSEMBLY(
+      "    852e mv a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(42, Call(test->entry(), 0, 42));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAdd, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ add(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAdd, test) {
+  EXPECT_DISASSEMBLY(
+      "    952e add a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(24, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-10, Call(test->entry(), 7, -17));
+  EXPECT_EQ(10, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, -17));
+  EXPECT_EQ(24, Call(test->entry(), 17, 7));
+  EXPECT_EQ(10, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedAnd, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ and_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAnd, test) {
+  EXPECT_DISASSEMBLY(
+      "    8d6d and a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(1, Call(test->entry(), 7, 17));
+  EXPECT_EQ(7, Call(test->entry(), 7, -17));
+  EXPECT_EQ(17, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-23, Call(test->entry(), -7, -17));
+  EXPECT_EQ(1, Call(test->entry(), 17, 7));
+  EXPECT_EQ(17, Call(test->entry(), 17, -7));
+  EXPECT_EQ(7, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-23, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedOr, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ or_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedOr, test) {
+  EXPECT_DISASSEMBLY(
+      "    8d4d or a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(23, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-17, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-7, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-1, Call(test->entry(), -7, -17));
+  EXPECT_EQ(23, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-7, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-17, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-1, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedXor, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ xor_(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedXor, test) {
+  EXPECT_DISASSEMBLY(
+      "    8d2d xor a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(22, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(22, Call(test->entry(), -7, -17));
+  EXPECT_EQ(22, Call(test->entry(), 17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(22, Call(test->entry(), -17, -7));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedSubtract, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ sub(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedSubtract, test) {
+  EXPECT_DISASSEMBLY(
+      "    8d0d sub a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(-10, Call(test->entry(), 7, 17));
+  EXPECT_EQ(24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(10, Call(test->entry(), -7, -17));
+  EXPECT_EQ(10, Call(test->entry(), 17, 7));
+  EXPECT_EQ(24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, -7));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(CompressedAddWord, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ addw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedAddWord, test) {
+  EXPECT_DISASSEMBLY(
+      "    9d2d addw a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(24, Call(test->entry(), 7, 17));
+  EXPECT_EQ(-10, Call(test->entry(), 7, -17));
+  EXPECT_EQ(10, Call(test->entry(), -7, 17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, -17));
+  EXPECT_EQ(24, Call(test->entry(), 17, 7));
+  EXPECT_EQ(10, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, -7));
+  EXPECT_EQ(3, Call(test->entry(), 0x200000002, 0x100000001));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedSubtractWord, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ subw(A0, A0, A1);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedSubtractWord, test) {
+  EXPECT_DISASSEMBLY(
+      "    9d0d subw a0, a0, a1\n"
+      "    8082 ret\n");
+  EXPECT_EQ(-10, Call(test->entry(), 7, 17));
+  EXPECT_EQ(24, Call(test->entry(), 7, -17));
+  EXPECT_EQ(-24, Call(test->entry(), -7, 17));
+  EXPECT_EQ(10, Call(test->entry(), -7, -17));
+  EXPECT_EQ(10, Call(test->entry(), 17, 7));
+  EXPECT_EQ(24, Call(test->entry(), 17, -7));
+  EXPECT_EQ(-24, Call(test->entry(), -17, 7));
+  EXPECT_EQ(-10, Call(test->entry(), -17, -7));
+  EXPECT_EQ(1, Call(test->entry(), 0x200000002, 0x100000001));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(CompressedNop, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ nop();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedNop, test) {
+  EXPECT_DISASSEMBLY(
+      "    0001 nop\n"
+      "    8082 ret\n");
+  EXPECT_EQ(123, Call(test->entry(), 123));
+}
+
+ASSEMBLER_TEST_GENERATE(CompressedEnvironmentBreak, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ ebreak();
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(CompressedEnvironmentBreak, test) {
+  EXPECT_DISASSEMBLY(
+      "    9002 ebreak\n"
+      "    8082 ret\n");
+
+  // Not running: would trap.
+}
+
+ASSEMBLER_TEST_GENERATE(LoadImmediate_MaxInt32, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ LoadImmediate(A0, kMaxInt32);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadImmediate_MaxInt32, test) {
+#if XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "80000537 lui a0, -2147483648\n"
+      "    157d addi a0, a0, -1\n"
+      "    8082 ret\n");
+#elif XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "80000537 lui a0, -2147483648\n"
+      "    357d addiw a0, a0, -1\n"
+      "    8082 ret\n");
+#endif
+  EXPECT_EQ(kMaxInt32, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadImmediate_MinInt32, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ LoadImmediate(A0, kMinInt32);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadImmediate_MinInt32, test) {
+  EXPECT_DISASSEMBLY(
+      "80000537 lui a0, -2147483648\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMinInt32, Call(test->entry()));
+}
+
+#if XLEN >= 64
+ASSEMBLER_TEST_GENERATE(LoadImmediate_MinInt64, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ LoadImmediate(A0, kMinInt64);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadImmediate_MinInt64, test) {
+  EXPECT_DISASSEMBLY(
+      "f8000537 lui a0, -134217728\n"
+      "    0532 slli a0, a0, 12\n"
+      "    0532 slli a0, a0, 12\n"
+      "    0532 slli a0, a0, 12\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMinInt64, Call(test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(LoadImmediate_Large, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  __ LoadImmediate(A0, 0xABCDABCDABCDABCD);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(LoadImmediate_Large, test) {
+  EXPECT_DISASSEMBLY(
+      "fabce537 lui a0, -88285184\n"
+      "abd5051b addiw a0, a0, -1347\n"
+      "    0532 slli a0, a0, 12\n"
+      "dac50513 addi a0, a0, -596\n"
+      "    0532 slli a0, a0, 12\n"
+      "cdb50513 addi a0, a0, -805\n"
+      "    0532 slli a0, a0, 12\n"
+      "bcd50513 addi a0, a0, -1075\n"
+      "    8082 ret\n");
+  EXPECT_EQ(static_cast<int64_t>(0xABCDABCDABCDABCD), Call(test->entry()));
+}
+#endif
+
+ASSEMBLER_TEST_GENERATE(AddImmediateBranchOverflow, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label overflow;
+
+  __ AddImmediateBranchOverflow(A0, A0, 2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddImmediateBranchOverflow, test) {
+  EXPECT_DISASSEMBLY(
+      "    872a mv tmp2, a0\n"
+      "    0509 addi a0, a0, 2\n"
+      "00e54363 blt a0, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX - 3));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX - 2));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX - 1));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX));
+}
+
+ASSEMBLER_TEST_GENERATE(AddBranchOverflow_NonDestructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label overflow;
+
+  __ AddBranchOverflow(A0, A1, A2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(AddBranchOverflow_NonDestructive, test) {
+  EXPECT_DISASSEMBLY(
+      "00c58533 add a0, a1, a2\n"
+      "00062693 slti tmp, a2, 0\n"
+      "00b52733 slt tmp2, a0, a1\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), 42, kMaxIntX, -1));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 0));
+  EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, 1));
+
+  EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, -1));
+  EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 42, kMinIntX, 1));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 0));
+}
+ASSEMBLER_TEST_GENERATE(AddBranchOverflow_Destructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label overflow;
+
+  __ AddBranchOverflow(A0, A1, A0, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(AddBranchOverflow_Destructive, test) {
+  EXPECT_DISASSEMBLY(
+      "00052693 slti tmp, a0, 0\n"
+      "    952e add a0, a0, a1\n"
+      "00b52733 slt tmp2, a0, a1\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX, -1));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 0));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX, 1));
+
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX, -1));
+  EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX, 1));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(SubtractImmediateBranchOverflow, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label overflow;
+
+  __ SubtractImmediateBranchOverflow(A0, A0, 2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SubtractImmediateBranchOverflow, test) {
+  EXPECT_DISASSEMBLY(
+      "    872a mv tmp2, a0\n"
+      "    1579 addi a0, a0, -2\n"
+      "00a74363 blt tmp2, a0, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX + 3));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX + 2));
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX + 1));
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX));
+}
+
+ASSEMBLER_TEST_GENERATE(SubtractBranchOverflow_NonDestructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  Label overflow;
+  __ SubtractBranchOverflow(A0, A1, A2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SubtractBranchOverflow_NonDestructive, test) {
+  EXPECT_DISASSEMBLY(
+      "40c58533 sub a0, a1, a2\n"
+      "00062693 slti tmp, a2, 0\n"
+      "00a5a733 slt tmp2, a1, a0\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), 42, kMaxIntX, 1));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 0));
+  EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, -1));
+
+  EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, 1));
+  EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 42, kMinIntX, -1));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(SubtractBranchOverflow_Destructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  Label overflow;
+  __ SubtractBranchOverflow(A0, A0, A1, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(SubtractBranchOverflow_Destructive, test) {
+  EXPECT_DISASSEMBLY(
+      "00052693 slti tmp, a0, 0\n"
+      "    8d0d sub a0, a0, a1\n"
+      "00b52733 slt tmp2, a0, a1\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), kMaxIntX, 1));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 0));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX, -1));
+
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX, 1));
+  EXPECT_EQ(kMinIntX + 1, Call(test->entry(), kMinIntX, -1));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 0));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyImmediateBranchOverflow, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+  Label overflow;
+
+  __ MultiplyImmediateBranchOverflow(A0, A0, 2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 0);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyImmediateBranchOverflow, test) {
+#if XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "    4709 li tmp2, 2\n"
+      "02e516b3 mulh tmp, a0, tmp2\n"
+      "02e50533 mul a0, a0, tmp2\n"
+      "43f55713 srai tmp2, a0, 0x3f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+#elif XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "    4709 li tmp2, 2\n"
+      "02e516b3 mulh tmp, a0, tmp2\n"
+      "02e50533 mul a0, a0, tmp2\n"
+      "41f55713 srai tmp2, a0, 0x1f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "    4501 li a0, 0\n"
+      "    8082 ret\n");
+#endif
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX));
+  EXPECT_EQ(-2, Call(test->entry(), -1));
+  EXPECT_EQ(2, Call(test->entry(), 1));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX / 2));
+  EXPECT_EQ(kMaxIntX - 1, Call(test->entry(), (kMaxIntX - 1) / 2));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyBranchOverflow_NonDestructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  Label overflow;
+  __ MultiplyBranchOverflow(A0, A1, A2, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyBranchOverflow_NonDestructive, test) {
+#if XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "02c596b3 mulh tmp, a1, a2\n"
+      "02c58533 mul a0, a1, a2\n"
+      "43f55713 srai tmp2, a0, 0x3f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "02a00513 li a0, 42\n"
+      "    8082 ret\n");
+#elif XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "02c596b3 mulh tmp, a1, a2\n"
+      "02c58533 mul a0, a1, a2\n"
+      "41f55713 srai tmp2, a0, 0x1f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "02a00513 li a0, 42\n"
+      "    8082 ret\n");
+#endif
+  EXPECT_EQ(42, Call(test->entry(), 42, kMaxIntX, -2));
+  EXPECT_EQ(-kMaxIntX, Call(test->entry(), 42, kMaxIntX, -1));
+  EXPECT_EQ(0, Call(test->entry(), 42, kMaxIntX, 0));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), 42, kMaxIntX, 1));
+  EXPECT_EQ(42, Call(test->entry(), 42, kMaxIntX, 2));
+
+  EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, -2));
+  EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, -1));
+  EXPECT_EQ(0, Call(test->entry(), 42, kMinIntX, 0));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 1));
+  EXPECT_EQ(42, Call(test->entry(), 42, kMinIntX, 2));
+}
+
+ASSEMBLER_TEST_GENERATE(MultiplyBranchOverflow_Destructive, assembler) {
+  FLAG_use_compressed_instructions = true;
+  __ SetExtensions(RV_GC);
+
+  Label overflow;
+  __ MultiplyBranchOverflow(A0, A0, A1, &overflow);
+  __ ret();
+  __ Bind(&overflow);
+  __ li(A0, 42);
+  __ ret();
+}
+ASSEMBLER_TEST_RUN(MultiplyBranchOverflow_Destructive, test) {
+#if XLEN == 64
+  EXPECT_DISASSEMBLY(
+      "02b516b3 mulh tmp, a0, a1\n"
+      "02b50533 mul a0, a0, a1\n"
+      "43f55713 srai tmp2, a0, 0x3f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "02a00513 li a0, 42\n"
+      "    8082 ret\n");
+#elif XLEN == 32
+  EXPECT_DISASSEMBLY(
+      "02b516b3 mulh tmp, a0, a1\n"
+      "02b50533 mul a0, a0, a1\n"
+      "41f55713 srai tmp2, a0, 0x1f\n"
+      "00e69363 bne tmp, tmp2, +6\n"
+      "    8082 ret\n"
+      "02a00513 li a0, 42\n"
+      "    8082 ret\n");
+#endif
+  EXPECT_EQ(42, Call(test->entry(), kMaxIntX, -2));
+  EXPECT_EQ(-kMaxIntX, Call(test->entry(), kMaxIntX, -1));
+  EXPECT_EQ(0, Call(test->entry(), kMaxIntX, 0));
+  EXPECT_EQ(kMaxIntX, Call(test->entry(), kMaxIntX, 1));
+  EXPECT_EQ(42, Call(test->entry(), kMaxIntX, 2));
+
+  EXPECT_EQ(42, Call(test->entry(), kMinIntX, -2));
+  EXPECT_EQ(42, Call(test->entry(), kMinIntX, -1));
+  EXPECT_EQ(0, Call(test->entry(), kMinIntX, 0));
+  EXPECT_EQ(kMinIntX, Call(test->entry(), kMinIntX, 1));
+  EXPECT_EQ(42, Call(test->entry(), kMinIntX, 2));
+}
+
+#define TEST_ENCODING(type, name)                                              \
+  VM_UNIT_TEST_CASE(Encoding##name) {                                          \
+    for (intptr_t v = -(1 << 21); v <= (1 << 21); v++) {                       \
+      type value = static_cast<type>(v);                                       \
+      if (!Is##name(value)) continue;                                          \
+      int32_t encoded = Encode##name(value);                                   \
+      type decoded = Decode##name(encoded);                                    \
+      EXPECT_EQ(value, decoded);                                               \
+    }                                                                          \
+  }
+
+TEST_ENCODING(Register, Rd)
+TEST_ENCODING(Register, Rs1)
+TEST_ENCODING(Register, Rs2)
+TEST_ENCODING(FRegister, FRd)
+TEST_ENCODING(FRegister, FRs1)
+TEST_ENCODING(FRegister, FRs2)
+TEST_ENCODING(FRegister, FRs3)
+TEST_ENCODING(Funct2, Funct2)
+TEST_ENCODING(Funct3, Funct3)
+TEST_ENCODING(Funct5, Funct5)
+TEST_ENCODING(Funct7, Funct7)
+TEST_ENCODING(Funct12, Funct12)
+TEST_ENCODING(RoundingMode, RoundingMode)
+TEST_ENCODING(intptr_t, BTypeImm)
+TEST_ENCODING(intptr_t, JTypeImm)
+TEST_ENCODING(intptr_t, ITypeImm)
+TEST_ENCODING(intptr_t, STypeImm)
+TEST_ENCODING(intptr_t, UTypeImm)
+
+TEST_ENCODING(Register, CRd)
+TEST_ENCODING(Register, CRs1)
+TEST_ENCODING(Register, CRs2)
+TEST_ENCODING(Register, CRdp)
+TEST_ENCODING(Register, CRs1p)
+TEST_ENCODING(Register, CRs2p)
+TEST_ENCODING(FRegister, CFRd)
+TEST_ENCODING(FRegister, CFRs1)
+TEST_ENCODING(FRegister, CFRs2)
+TEST_ENCODING(FRegister, CFRdp)
+TEST_ENCODING(FRegister, CFRs1p)
+TEST_ENCODING(FRegister, CFRs2p)
+TEST_ENCODING(intptr_t, CSPLoad4Imm)
+TEST_ENCODING(intptr_t, CSPLoad8Imm)
+TEST_ENCODING(intptr_t, CSPStore4Imm)
+TEST_ENCODING(intptr_t, CSPStore8Imm)
+TEST_ENCODING(intptr_t, CMem4Imm)
+TEST_ENCODING(intptr_t, CMem8Imm)
+TEST_ENCODING(intptr_t, CJImm)
+TEST_ENCODING(intptr_t, CBImm)
+TEST_ENCODING(intptr_t, CIImm)
+TEST_ENCODING(intptr_t, CUImm)
+TEST_ENCODING(intptr_t, CI16Imm)
+TEST_ENCODING(intptr_t, CI4SPNImm)
+
+#undef TEST_ENCODING
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 0c396e7..4e36eff 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -20,10 +20,10 @@
 namespace compiler {
 
 Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches)
+                     intptr_t far_branch_level)
     : AssemblerBase(object_pool_builder), constant_pool_allowed_(false) {
   // Far branching mode is only needed and implemented for ARM.
-  ASSERT(!use_far_branches);
+  ASSERT(far_branch_level == 0);
 
   generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
     call(Address(THR,
@@ -184,7 +184,7 @@
   }
 }
 
-void Assembler::ExitFullSafepoint() {
+void Assembler::ExitFullSafepoint(bool ignore_unwind_in_progress) {
   // We generate the same number of instructions whether or not the slow-path is
   // forced, for consistency with EnterFullSafepoint.
   Label done, slow_path;
@@ -209,7 +209,14 @@
   }
 
   Bind(&slow_path);
-  movq(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  if (ignore_unwind_in_progress) {
+    movq(TMP,
+         Address(THR,
+                 target::Thread::
+                     exit_safepoint_ignore_unwind_in_progress_stub_offset()));
+  } else {
+    movq(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
+  }
   movq(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
 
   // Use call instead of CallCFunction to avoid having to clean up shadow space
@@ -220,10 +227,13 @@
   Bind(&done);
 }
 
-void Assembler::TransitionNativeToGenerated(bool leave_safepoint) {
+void Assembler::TransitionNativeToGenerated(bool leave_safepoint,
+                                            bool ignore_unwind_in_progress) {
   if (leave_safepoint) {
-    ExitFullSafepoint();
+    ExitFullSafepoint(ignore_unwind_in_progress);
   } else {
+    // flag only makes sense if we are leaving safepoint
+    ASSERT(!ignore_unwind_in_progress);
 #if defined(DEBUG)
     // Ensure we've already left the safepoint.
     movq(TMP, Address(THR, target::Thread::safepoint_state_offset()));
@@ -1379,6 +1389,17 @@
   }
 }
 
+void Assembler::LoadDImmediate(FpuRegister dst, double immediate) {
+  int64_t bits = bit_cast<int64_t>(immediate);
+  if (bits == 0) {
+    xorps(dst, dst);
+  } else {
+    intptr_t index = FindImmediate(bits);
+    LoadUnboxedDouble(
+        dst, PP, target::ObjectPool::element_offset(index) - kHeapObjectTag);
+  }
+}
+
 void Assembler::LoadCompressed(Register dest, const Address& slot) {
 #if !defined(DART_COMPRESSED_POINTERS)
   movq(dest, slot);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 5312859..52af843 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -295,7 +295,7 @@
 class Assembler : public AssemblerBase {
  public:
   explicit Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches = false);
+                     intptr_t far_branch_level = 0);
 
   ~Assembler() {}
 
@@ -319,12 +319,13 @@
   void setcc(Condition condition, ByteRegister dst);
 
   void EnterFullSafepoint();
-  void ExitFullSafepoint();
+  void ExitFullSafepoint(bool ignore_unwind_in_progress);
   void TransitionGeneratedToNative(Register destination_address,
                                    Register new_exit_frame,
                                    Register new_exit_through_ffi,
                                    bool enter_safepoint);
-  void TransitionNativeToGenerated(bool leave_safepoint);
+  void TransitionNativeToGenerated(bool leave_safepoint,
+                                   bool ignore_unwind_in_progress = false);
 
 // Register-register, register-address and address-register instructions.
 #define RR(width, name, ...)                                                   \
@@ -747,6 +748,7 @@
   void LoadImmediate(Register reg, int32_t immediate) {
     LoadImmediate(reg, Immediate(immediate));
   }
+  void LoadDImmediate(FpuRegister dst, double immediate);
 
   void LoadIsolate(Register dst);
   void LoadIsolateGroup(Register dst);
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 1dded0f..761a858 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -3384,7 +3384,7 @@
   EXPECT_FLOAT_EQ(-1.0, res, 0.000001f);
   EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
       "movups xmm10,[rax]\n"
-      "movq r11,[thr+0x2b0]\n"
+      "movq r11,[thr+0x...]\n"
       "xorpd xmm10,[r11]\n"
       "movaps xmm0,xmm10\n"
       "pop thr\n"
@@ -3413,7 +3413,7 @@
   EXPECT_FLOAT_EQ(1.0, res, 0.000001f);
   EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
       "movups xmm10,[rax]\n"
-      "movq r11,[thr+0x2b8]\n"
+      "movq r11,[thr+0x...]\n"
       "movups xmm0,[r11]\n"
       "andpd xmm0,xmm10\n"
       "pop thr\n"
@@ -4066,7 +4066,7 @@
       "movl rax,0x4144cccd\n"
       "movd xmm0,rax\n"
       "shufps xmm0,xmm0 [0]\n"
-      "movq r11,[thr+0x2c8]\n"
+      "movq r11,[thr+0x...]\n"
       "xorps xmm0,[r11]\n"
       "shufps xmm0,xmm0 [aa]\n"
       "pop thr\n"
@@ -4103,7 +4103,7 @@
       "movl rax,-0x3e8b3333\n"
       "movd xmm0,rax\n"
       "shufps xmm0,xmm0 [0]\n"
-      "movq r11,[thr+0x2d0]\n"
+      "movq r11,[thr+0x...]\n"
       "andps xmm0,[r11]\n"
       "shufps xmm0,xmm0 [aa]\n"
       "pop thr\n"
@@ -4138,7 +4138,7 @@
       "movl rax,0x4144cccd\n"
       "movd xmm0,rax\n"
       "shufps xmm0,xmm0 [0]\n"
-      "movq r11,[thr+0x2d8]\n"
+      "movq r11,[thr+0x...]\n"
       "andps xmm0,[r11]\n"
       "shufps xmm0,xmm0 [ff]\n"
       "pop thr\n"
@@ -4288,7 +4288,7 @@
   EXPECT_EQ(static_cast<uword>(0x0), res);
   EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
       "movups xmm9,[rax]\n"
-      "movq r11,[thr+0x2c0]\n"
+      "movq r11,[thr+0x...]\n"
       "movups xmm0,[r11]\n"
       "xorps xmm0,xmm9\n"
       "push rax\n"
@@ -5464,7 +5464,7 @@
       "movq r12,[rdi+0x8]\n"
       "movq thr,rsi\n"
       "movq pp,[r12+0x27]\n"
-      "movq r11,[thr+0x2b8]\n"
+      "movq r11,[thr+0x...]\n"
       "andpd xmm0,[r11]\n"
       "pop thr\n"
       "pop pp\n"
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index 2777ccd..58b3430 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -114,7 +114,30 @@
   if (overflowed_) {
     return;
   }
-  intptr_t len = strlen(human_buffer);
+  intptr_t len;
+
+  // TODO(compiler): Update assembler tests for other architectures so there is
+  // coverage of encodings, not just mnemonics.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+  len = strlen(hex_buffer);
+  if (remaining_ < len + 100) {
+    *buffer_++ = '.';
+    *buffer_++ = '.';
+    *buffer_++ = '.';
+    *buffer_++ = '\n';
+    *buffer_++ = '\0';
+    overflowed_ = true;
+    return;
+  }
+  memmove(buffer_, hex_buffer, len);
+  buffer_ += len;
+  remaining_ -= len;
+  *buffer_++ = ' ';
+  remaining_--;
+  *buffer_ = '\0';
+#endif
+
+  len = strlen(human_buffer);
   if (remaining_ < len + 100) {
     *buffer_++ = '.';
     *buffer_++ = '.';
diff --git a/runtime/vm/compiler/assembler/disassembler_riscv.cc b/runtime/vm/compiler/assembler/disassembler_riscv.cc
new file mode 100644
index 0000000..9a3ae1b
--- /dev/null
+++ b/runtime/vm/compiler/assembler/disassembler_riscv.cc
@@ -0,0 +1,1595 @@
+// 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.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_RISCV.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/assembler/disassembler.h"
+
+#include "platform/assert.h"
+#include "vm/instructions.h"
+
+namespace dart {
+
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+
+// We deviate from objdump in two places:
+//  - branches display displacements instead of targets so our output is
+//    position independent for tests.
+//  - auipc/lui display the decoded value instead of the encoded value
+class RISCVDisassembler {
+ public:
+  explicit RISCVDisassembler(char* buffer,
+                             size_t buffer_size,
+                             ExtensionSet extensions)
+      : extensions_(extensions),
+        buffer_(buffer),
+        buffer_size_(buffer_size),
+        buffer_pos_(0) {}
+
+  bool Supports(Extension extension) const {
+    return extensions_.Includes(extension);
+  }
+  bool Supports(ExtensionSet extensions) const {
+    return extensions_.IncludesAll(extensions);
+  }
+
+  intptr_t Disassemble(uword pc) {
+    uint16_t parcel = *reinterpret_cast<uint16_t*>(pc);
+    if (Supports(RV_C) && IsCInstruction(parcel)) {
+      CInstr instr(parcel);
+      DisassembleInstruction(instr);
+      return instr.length();
+    } else {
+      uint32_t parcel = *reinterpret_cast<uint32_t*>(pc);
+      Instr instr(parcel);
+      DisassembleInstruction(instr);
+      return instr.length();
+    }
+  }
+
+ private:
+  void DisassembleInstruction(Instr instr);
+  void DisassembleInstruction(CInstr instr);
+  void DisassembleLUI(Instr instr);
+  void DisassembleAUIPC(Instr instr);
+  void DisassembleJAL(Instr instr);
+  void DisassembleJALR(Instr instr);
+  void DisassembleBRANCH(Instr instr);
+  void DisassembleLOAD(Instr instr);
+  void DisassembleSTORE(Instr instr);
+  void DisassembleOPIMM(Instr instr);
+  void DisassembleOPIMM32(Instr instr);
+  void DisassembleOP(Instr instr);
+  void DisassembleOP_0(Instr instr);
+  void DisassembleOP_SUB(Instr instr);
+  void DisassembleOP_MULDIV(Instr instr);
+  void DisassembleOP32(Instr instr);
+  void DisassembleOP32_0(Instr instr);
+  void DisassembleOP32_SUB(Instr instr);
+  void DisassembleOP32_MULDIV(Instr instr);
+  void DisassembleMISCMEM(Instr instr);
+  void DisassembleSYSTEM(Instr instr);
+  void DisassembleAMO(Instr instr);
+  void DisassembleAMO32(Instr instr);
+  void DisassembleAMO64(Instr instr);
+  void DisassembleLOADFP(Instr instr);
+  void DisassembleSTOREFP(Instr instr);
+  void DisassembleFMADD(Instr instr);
+  void DisassembleFMSUB(Instr instr);
+  void DisassembleFNMADD(Instr instr);
+  void DisassembleFNMSUB(Instr instr);
+  void DisassembleOPFP(Instr instr);
+
+  void UnknownInstruction(Instr instr);
+  void UnknownInstruction(CInstr instr);
+
+  void Print(const char* format, Instr instr, ExtensionSet extension);
+  void Print(const char* format, CInstr instr, ExtensionSet extension);
+  const char* PrintOption(const char* format, Instr instr);
+  const char* PrintOption(const char* format, CInstr instr);
+
+  void Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
+    va_list args;
+    va_start(args, format);
+    intptr_t len = Utils::VSNPrint(buffer_ + buffer_pos_,
+                                   buffer_size_ - buffer_pos_, format, args);
+    va_end(args);
+    buffer_pos_ += len;
+    buffer_[buffer_pos_] = '\0';
+  }
+
+  const ExtensionSet extensions_;
+  char* buffer_;        // Decode instructions into this buffer.
+  size_t buffer_size_;  // The size of the character buffer.
+  size_t buffer_pos_;   // Current character position in buffer.
+};
+
+void RISCVDisassembler::DisassembleInstruction(Instr instr) {
+  switch (instr.opcode()) {
+    case LUI:
+      DisassembleLUI(instr);
+      break;
+    case AUIPC:
+      DisassembleAUIPC(instr);
+      break;
+    case JAL:
+      DisassembleJAL(instr);
+      break;
+    case JALR:
+      DisassembleJALR(instr);
+      break;
+    case BRANCH:
+      DisassembleBRANCH(instr);
+      break;
+    case LOAD:
+      DisassembleLOAD(instr);
+      break;
+    case STORE:
+      DisassembleSTORE(instr);
+      break;
+    case OPIMM:
+      DisassembleOPIMM(instr);
+      break;
+    case OPIMM32:
+      DisassembleOPIMM32(instr);
+      break;
+    case OP:
+      DisassembleOP(instr);
+      break;
+    case OP32:
+      DisassembleOP32(instr);
+      break;
+    case MISCMEM:
+      DisassembleMISCMEM(instr);
+      break;
+    case SYSTEM:
+      DisassembleSYSTEM(instr);
+      break;
+    case AMO:
+      DisassembleAMO(instr);
+      break;
+    case LOADFP:
+      DisassembleLOADFP(instr);
+      break;
+    case STOREFP:
+      DisassembleSTOREFP(instr);
+      break;
+    case FMADD:
+      DisassembleFMADD(instr);
+      break;
+    case FMSUB:
+      DisassembleFMSUB(instr);
+      break;
+    case FNMADD:
+      DisassembleFNMADD(instr);
+      break;
+    case FNMSUB:
+      DisassembleFNMSUB(instr);
+      break;
+    case OPFP:
+      DisassembleOPFP(instr);
+      break;
+    default:
+      if ((instr.encoding() == 0) ||
+          (instr.encoding() == static_cast<uint32_t>(-1))) {
+        Print("trap", instr, RV_I);
+        break;
+      }
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleInstruction(CInstr instr) {
+  switch (instr.opcode()) {
+    case C_LWSP:
+      Print("lw 'rd, 'spload4imm(sp)", instr, RV_C);
+      break;
+#if XLEN == 32
+    case C_FLWSP:
+      Print("flw 'frd, 'spload4imm(sp)", instr, RV_C | RV_F);
+      break;
+#else
+    case C_LDSP:
+      Print("ld 'rd, 'spload8imm(sp)", instr, RV_C);
+      break;
+#endif
+    case C_FLDSP:
+      Print("fld 'frd, 'spload8imm(sp)", instr, RV_C | RV_D);
+      break;
+    case C_SWSP:
+      Print("sw 'rs2, 'spstore4imm(sp)", instr, RV_C);
+      break;
+#if XLEN == 32
+    case C_FSWSP:
+      Print("fsw 'frs2, 'spstore4imm(sp)", instr, RV_C | RV_F);
+      break;
+#else
+    case C_SDSP:
+      Print("sd 'rs2, 'spstore8imm(sp)", instr, RV_C);
+      break;
+#endif
+    case C_FSDSP:
+      Print("fsd 'frs2, 'spstore8imm(sp)", instr, RV_C | RV_D);
+      break;
+    case C_LW:
+      Print("lw 'rdp, 'mem4imm('rs1p)", instr, RV_C);
+      break;
+#if XLEN == 32
+    case C_FLW:
+      Print("flw 'frdp, 'mem4imm('rs1p)", instr, RV_C | RV_F);
+      break;
+#else
+    case C_LD:
+      Print("ld 'rdp, 'mem8imm('rs1p)", instr, RV_C);
+      break;
+#endif
+    case C_FLD:
+      Print("fld 'frdp, 'mem8imm('rs1p)", instr, RV_C | RV_D);
+      break;
+    case C_SW:
+      Print("sw 'rs2p, 'mem4imm('rs1p)", instr, RV_C);
+      break;
+#if XLEN == 32
+    case C_FSW:
+      Print("fsw 'frs2p, 'mem4imm('rs1p)", instr, RV_C | RV_F);
+      break;
+#else
+    case C_SD:
+      Print("sd 'rs2p, 'mem8imm('rs1p)", instr, RV_C);
+      break;
+#endif
+    case C_FSD:
+      Print("fsd 'frs2p, 'mem8imm('rs1p)", instr, RV_C | RV_F);
+      break;
+    case C_J:
+      Print("j 'jimm", instr, RV_C);
+      break;
+#if XLEN == 32
+    case C_JAL:
+      Print("jal 'jimm", instr, RV_C);
+      break;
+#endif
+    case C_JR:
+      if (instr.encoding() & (C_JALR ^ C_JR)) {
+        if ((instr.rs1() == ZR) && (instr.rs2() == ZR)) {
+          Print("ebreak", instr, RV_C);
+        } else if (instr.rs2() == ZR) {
+          Print("jalr 'rs1", instr, RV_C);
+        } else {
+          Print("add 'rd, 'rs1, 'rs2", instr, RV_C);
+        }
+      } else {
+        if (instr.rd() != ZR && instr.rs2() != ZR) {
+          Print("mv 'rd, 'rs2", instr, RV_C);
+        } else if (instr.rs2() != ZR) {
+          UnknownInstruction(instr);
+        } else if (instr.rs1() == RA) {
+          Print("ret", instr, RV_C);
+        } else {
+          Print("jr 'rs1", instr, RV_C);
+        }
+      }
+      break;
+    case C_BEQZ:
+      Print("beqz 'rs1p, 'bimm", instr, RV_C);
+      break;
+    case C_BNEZ:
+      Print("bnez 'rs1p, 'bimm", instr, RV_C);
+      break;
+    case C_LI:
+      Print("li 'rd, 'iimm", instr, RV_C);
+      break;
+    case C_LUI:
+      if (instr.rd() == SP) {
+        Print("addi 'rd, 'rs1, 'i16imm", instr, RV_C);
+      } else {
+        Print("lui 'rd, 'uimm", instr, RV_C);
+      }
+      break;
+    case C_ADDI:
+      if ((instr.rd() == ZR) && (instr.rs1() == ZR) && (instr.i_imm() == 0)) {
+        Print("nop", instr, RV_C);
+      } else {
+        Print("addi 'rd, 'rs1, 'iimm", instr, RV_C);
+      }
+      break;
+#if XLEN >= 64
+    case C_ADDIW:
+      if (instr.i_imm() == 0) {
+        Print("sext.w 'rd, 'rs1", instr, RV_C);
+      } else {
+        Print("addiw 'rd, 'rs1, 'iimm", instr, RV_C);
+      }
+      break;
+#endif
+    case C_ADDI4SPN:
+      if (instr.i4spn_imm() == 0) {
+        UnknownInstruction(instr);
+      } else {
+        Print("addi 'rdp, sp, 'i4spnimm", instr, RV_C);
+      }
+      break;
+    case C_SLLI:
+      if (instr.i_imm() == 0) {
+        UnknownInstruction(instr);
+      } else {
+        Print("slli 'rd, 'rs1, 'iimm", instr, RV_C);
+      }
+      break;
+    case C_MISCALU:
+      switch (instr.encoding() & C_MISCALU_MASK) {
+        case C_SRLI:
+          if (instr.i_imm() == 0) {
+            UnknownInstruction(instr);
+          } else {
+            Print("srli 'rs1p, 'rs1p, 'iimm", instr, RV_C);
+          }
+          break;
+        case C_SRAI:
+          if (instr.i_imm() == 0) {
+            UnknownInstruction(instr);
+          } else {
+            Print("srai 'rs1p, 'rs1p, 'iimm", instr, RV_C);
+          }
+          break;
+        case C_ANDI:
+          Print("andi 'rs1p, 'rs1p, 'iimm", instr, RV_C);
+          break;
+        case C_RR:
+          switch (instr.encoding() & C_RR_MASK) {
+            case C_AND:
+              Print("and 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+            case C_OR:
+              Print("or 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+            case C_XOR:
+              Print("xor 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+            case C_SUB:
+              Print("sub 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+#if XLEN >= 64
+            case C_ADDW:
+              Print("addw 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+            case C_SUBW:
+              Print("subw 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
+              break;
+#endif
+            default:
+              UnknownInstruction(instr);
+          }
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    default:
+      if ((instr.encoding() == 0) ||
+          (instr.encoding() == static_cast<uint16_t>(-1))) {
+        Print("trap", instr, RV_C);
+        break;
+      }
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleLUI(Instr instr) {
+  Print("lui 'rd, 'uimm", instr, RV_I);
+}
+
+void RISCVDisassembler::DisassembleAUIPC(Instr instr) {
+  Print("auipc 'rd, 'uimm", instr, RV_I);
+}
+
+void RISCVDisassembler::DisassembleJAL(Instr instr) {
+  if (instr.rd() == ZR) {
+    Print("j 'jimm", instr, RV_I);
+  } else if (instr.rd() == RA) {
+    Print("jal 'jimm", instr, RV_I);
+  } else {
+    Print("jal 'rd, 'jimm", instr, RV_I);
+  }
+}
+
+void RISCVDisassembler::DisassembleJALR(Instr instr) {
+  if (instr.rd() == ZR) {
+    if ((instr.rs1() == RA) && (instr.itype_imm() == 0)) {
+      Print("ret", instr, RV_I);
+    } else if (instr.itype_imm() == 0) {
+      Print("jr 'rs1", instr, RV_I);
+    } else {
+      Print("jr 'iimm('rs1)", instr, RV_I);
+    }
+  } else if (instr.rd() == RA) {
+    if (instr.itype_imm() == 0) {
+      Print("jalr 'rs1", instr, RV_I);
+    } else {
+      Print("jalr 'iimm('rs1)", instr, RV_I);
+    }
+  } else {
+    if (instr.itype_imm() == 0) {
+      Print("jalr 'rd, 'rs1", instr, RV_I);
+    } else {
+      Print("jalr 'rd, 'iimm('rs1)", instr, RV_I);
+    }
+  }
+}
+
+void RISCVDisassembler::DisassembleBRANCH(Instr instr) {
+  switch (instr.funct3()) {
+    case BEQ:
+      if (instr.rs2() == ZR) {
+        Print("beqz 'rs1, 'bimm", instr, RV_I);
+      } else {
+        Print("beq 'rs1, 'rs2, 'bimm", instr, RV_I);
+      }
+      break;
+    case BNE:
+      if (instr.rs2() == ZR) {
+        Print("bnez 'rs1, 'bimm", instr, RV_I);
+      } else {
+        Print("bne 'rs1, 'rs2, 'bimm", instr, RV_I);
+      }
+      break;
+    case BLT:
+      if (instr.rs2() == ZR) {
+        Print("bltz 'rs1, 'bimm", instr, RV_I);
+      } else if (instr.rs1() == ZR) {
+        Print("bgtz 'rs2, 'bimm", instr, RV_I);
+      } else {
+        Print("blt 'rs1, 'rs2, 'bimm", instr, RV_I);
+      }
+      break;
+    case BGE:
+      if (instr.rs2() == ZR) {
+        Print("bgez 'rs1, 'bimm", instr, RV_I);
+      } else if (instr.rs1() == ZR) {
+        Print("blez 'rs2, 'bimm", instr, RV_I);
+      } else {
+        Print("ble 'rs2, 'rs1, 'bimm", instr, RV_I);
+      }
+      break;
+    case BLTU:
+      Print("bltu 'rs1, 'rs2, 'bimm", instr, RV_I);
+      break;
+    case BGEU:
+      Print("bleu 'rs2, 'rs1, 'bimm", instr, RV_I);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleLOAD(Instr instr) {
+  switch (instr.funct3()) {
+    case LB:
+      Print("lb 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+    case LH:
+      Print("lh 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+    case LW:
+      Print("lw 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+    case LBU:
+      Print("lbu 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+    case LHU:
+      Print("lhu 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+#if XLEN >= 64
+    case LWU:
+      Print("lwu 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+    case LD:
+      Print("ld 'rd, 'iimm('rs1)", instr, RV_I);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleLOADFP(Instr instr) {
+  switch (instr.funct3()) {
+    case S:
+      Print("flw 'frd, 'iimm('rs1)", instr, RV_F);
+      break;
+    case D:
+      Print("fld 'frd, 'iimm('rs1)", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleSTORE(Instr instr) {
+  switch (instr.funct3()) {
+    case SB:
+      Print("sb 'rs2, 'simm('rs1)", instr, RV_I);
+      break;
+    case SH:
+      Print("sh 'rs2, 'simm('rs1)", instr, RV_I);
+      break;
+    case SW:
+      Print("sw 'rs2, 'simm('rs1)", instr, RV_I);
+      break;
+#if XLEN >= 64
+    case SD:
+      Print("sd 'rs2, 'simm('rs1)", instr, RV_I);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleSTOREFP(Instr instr) {
+  switch (instr.funct3()) {
+    case S:
+      Print("fsw 'frs2, 'simm('rs1)", instr, RV_F);
+      break;
+    case D:
+      Print("fsd 'frs2, 'simm('rs1)", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOPIMM(Instr instr) {
+  switch (instr.funct3()) {
+    case ADDI:
+      if ((instr.rd() == ZR) && (instr.rs1() == ZR) &&
+          (instr.itype_imm() == 0)) {
+        Print("nop", instr, RV_I);  // The canonical nop.
+      } else if (instr.itype_imm() == 0) {
+        Print("mv 'rd, 'rs1", instr, RV_I);
+      } else if (instr.rs1() == ZR) {
+        Print("li 'rd, 'iimm", instr, RV_I);
+      } else {
+        Print("addi 'rd, 'rs1, 'iimm", instr, RV_I);
+      }
+      break;
+    case SLTI:
+      Print("slti 'rd, 'rs1, 'iimm", instr, RV_I);
+      break;
+    case SLTIU:
+      if (instr.itype_imm() == 1) {
+        Print("seqz 'rd, 'rs1", instr, RV_I);
+      } else {
+        Print("sltiu 'rd, 'rs1, 'iimm", instr, RV_I);
+      }
+      break;
+    case XORI:
+      if (instr.itype_imm() == -1) {
+        Print("not 'rd, 'rs1", instr, RV_I);
+      } else {
+        Print("xori 'rd, 'rs1, 'iimm", instr, RV_I);
+      }
+      break;
+    case ORI:
+      Print("ori 'rd, 'rs1, 'iimm", instr, RV_I);
+      break;
+    case ANDI:
+      Print("andi 'rd, 'rs1, 'iimm", instr, RV_I);
+      break;
+    case SLLI:
+      Print("slli 'rd, 'rs1, 'shamt", instr, RV_I);
+      break;
+    case SRI:
+      if ((instr.funct7() & 0b1111110) == SRA) {
+        Print("srai 'rd, 'rs1, 'shamt", instr, RV_I);
+      } else {
+        Print("srli 'rd, 'rs1, 'shamt", instr, RV_I);
+      }
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOPIMM32(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case ADDI:
+      if (instr.itype_imm() == 0) {
+        Print("sext.w 'rd, 'rs1", instr, RV_I);
+      } else {
+        Print("addiw 'rd, 'rs1, 'iimm", instr, RV_I);
+      }
+      break;
+    case SLLI:
+      Print("slliw 'rd, 'rs1, 'shamt", instr, RV_I);
+      break;
+    case SRI:
+      if (instr.funct7() == SRA) {
+        Print("sraiw 'rd, 'rs1, 'shamt", instr, RV_I);
+      } else {
+        Print("srliw 'rd, 'rs1, 'shamt", instr, RV_I);
+      }
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP(Instr instr) {
+  switch (instr.funct7()) {
+    case 0:
+      DisassembleOP_0(instr);
+      break;
+    case SUB:
+      DisassembleOP_SUB(instr);
+      break;
+    case MULDIV:
+      DisassembleOP_MULDIV(instr);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP_0(Instr instr) {
+  switch (instr.funct3()) {
+    case ADD:
+      Print("add 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case SLL:
+      Print("sll 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case SLT:
+      if (instr.rs2() == ZR) {
+        Print("sltz 'rd, 'rs1", instr, RV_I);
+      } else if (instr.rs1() == ZR) {
+        Print("sgtz 'rd, 'rs2", instr, RV_I);
+      } else {
+        Print("slt 'rd, 'rs1, 'rs2", instr, RV_I);
+      }
+      break;
+    case SLTU:
+      if (instr.rs1() == ZR) {
+        Print("snez 'rd, 'rs2", instr, RV_I);
+      } else {
+        Print("sltu 'rd, 'rs1, 'rs2", instr, RV_I);
+      }
+      break;
+    case XOR:
+      Print("xor 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case SR:
+      Print("srl 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case OR:
+      Print("or 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case AND:
+      Print("and 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP_SUB(Instr instr) {
+  switch (instr.funct3()) {
+    case ADD:
+      if (instr.rs1() == ZR) {
+        Print("neg 'rd, 'rs2", instr, RV_I);
+      } else {
+        Print("sub 'rd, 'rs1, 'rs2", instr, RV_I);
+      }
+      break;
+    case SR:
+      Print("sra 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP_MULDIV(Instr instr) {
+  switch (instr.funct3()) {
+    case MUL:
+      Print("mul 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case MULH:
+      Print("mulh 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case MULHSU:
+      Print("mulhsu 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case MULHU:
+      Print("mulhu 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case DIV:
+      Print("div 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case DIVU:
+      Print("divu 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case REM:
+      Print("rem 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case REMU:
+      Print("remu 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP32(Instr instr) {
+  switch (instr.funct7()) {
+    case 0:
+      DisassembleOP32_0(instr);
+      break;
+    case SUB:
+      DisassembleOP32_SUB(instr);
+      break;
+    case MULDIV:
+      DisassembleOP32_MULDIV(instr);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP32_0(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case ADD:
+      Print("addw 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case SLL:
+      Print("sllw 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    case SR: {
+      Print("srlw 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+    }
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP32_SUB(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case ADD:
+      if (instr.rs1() == ZR) {
+        Print("negw 'rd, 'rs2", instr, RV_I);
+      } else {
+        Print("subw 'rd, 'rs1, 'rs2", instr, RV_I);
+      }
+      break;
+    case SR:
+      Print("sraw 'rd, 'rs1, 'rs2", instr, RV_I);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOP32_MULDIV(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case MULW:
+      Print("mulw 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case DIVW:
+      Print("divw 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case DIVUW:
+      Print("divuw 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case REMW:
+      Print("remw 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+    case REMUW:
+      Print("remuw 'rd, 'rs1, 'rs2", instr, RV_M);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleMISCMEM(Instr instr) {
+  switch (instr.funct3()) {
+    case FENCE:
+      Print("fence'predsucc", instr, RV_I);
+      break;
+    case FENCEI:
+      Print("fence.i", instr, RV_I);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleSYSTEM(Instr instr) {
+  switch (instr.funct3()) {
+    case 0:
+      switch (instr.funct12()) {
+        case ECALL:
+          if (instr.rs1() == ZR) {
+            Print("ecall", instr, RV_I);
+          } else {
+            Print("SimulatorPrintObject 'rs1", instr, RV_I);
+          }
+          break;
+        case EBREAK:
+          Print("ebreak", instr, RV_I);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case CSRRW:
+      if (instr.rd() == ZR) {
+        Print("csrw 'csr, 'rs1", instr, RV_I);
+      } else {
+        Print("csrrw 'rd, 'csr, 'rs1", instr, RV_I);
+      }
+      break;
+    case CSRRS:
+      if (instr.rs1() == ZR) {
+        Print("csrr 'rd, 'csr", instr, RV_I);
+      } else if (instr.rd() == ZR) {
+        Print("csrs 'csr, 'rs1", instr, RV_I);
+      } else {
+        Print("csrrs 'rd, 'csr, 'rs1", instr, RV_I);
+      }
+      break;
+    case CSRRC:
+      if (instr.rd() == ZR) {
+        Print("csrc 'csr, 'rs1", instr, RV_I);
+      } else {
+        Print("csrrc 'rd, 'csr, 'rs1", instr, RV_I);
+      }
+      break;
+    case CSRRWI:
+      if (instr.rd() == ZR) {
+        Print("csrwi 'csr, 'zimm", instr, RV_I);
+      } else {
+        Print("csrrwi 'rd, 'csr, 'zimm", instr, RV_I);
+      }
+      break;
+    case CSRRSI:
+      if (instr.rd() == ZR) {
+        Print("csrsi 'csr, 'zimm", instr, RV_I);
+      } else {
+        Print("csrrsi 'rd, 'csr, 'zimm", instr, RV_I);
+      }
+      break;
+    case CSRRCI:
+      if (instr.rd() == ZR) {
+        Print("csrci 'csr, 'zimm", instr, RV_I);
+      } else {
+        Print("csrrci 'rd, 'csr, 'zimm", instr, RV_I);
+      }
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleAMO(Instr instr) {
+  switch (instr.funct3()) {
+    case WIDTH32:
+      DisassembleAMO32(instr);
+      break;
+    case WIDTH64:
+      DisassembleAMO64(instr);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleAMO32(Instr instr) {
+  switch (instr.funct5()) {
+    case LR:
+      Print("lr.w'order 'rd, ('rs1)", instr, RV_A);
+      break;
+    case SC:
+      Print("sc.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOSWAP:
+      Print("amoswap.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOADD:
+      Print("amoadd.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOXOR:
+      Print("amoxor.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOAND:
+      Print("amoand.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOOR:
+      Print("amoor.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMIN:
+      Print("amomin.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMAX:
+      Print("amomax.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMINU:
+      Print("amominu.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMAXU:
+      Print("amomaxu.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleAMO64(Instr instr) {
+  switch (instr.funct5()) {
+#if XLEN >= 64
+    case LR:
+      Print("lr.d'order 'rd, ('rs1)", instr, RV_A);
+      break;
+    case SC:
+      Print("sc.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOSWAP:
+      Print("amoswap.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOADD:
+      Print("amoadd.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOXOR:
+      Print("amoxor.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOAND:
+      Print("amoand.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOOR:
+      Print("amoor.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMIN:
+      Print("amomin.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMAX:
+      Print("amomax.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMINU:
+      Print("amominu.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+    case AMOMAXU:
+      Print("amomaxu.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleFMADD(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S:
+      Print("fmadd.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
+      break;
+    case F2_D:
+      Print("fmadd.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleFMSUB(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S:
+      Print("fmsub.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
+      break;
+    case F2_D:
+      Print("fmsub.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleFNMADD(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S:
+      Print("fnmadd.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
+      break;
+    case F2_D:
+      Print("fnmadd.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleFNMSUB(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S:
+      Print("fnmsub.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
+      break;
+    case F2_D:
+      Print("fnmsub.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
+      break;
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::DisassembleOPFP(Instr instr) {
+  switch (instr.funct7()) {
+    case FADDS:
+      Print("fadd.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
+      break;
+    case FSUBS:
+      Print("fsub.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
+      break;
+    case FMULS:
+      Print("fmul.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
+      break;
+    case FDIVS:
+      Print("fdiv.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
+      break;
+    case FSQRTS:
+      Print("fsqrt.s 'frd, 'frs1'round", instr, RV_F);
+      break;
+    case FSGNJS: {
+      switch (instr.funct3()) {
+        case J:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fmv.s 'frd, 'frs1", instr, RV_F);
+          } else {
+            Print("fsgnj.s 'frd, 'frs1, 'frs2", instr, RV_F);
+          }
+          break;
+        case JN:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fneg.s 'frd, 'frs1", instr, RV_F);
+          } else {
+            Print("fsgnjn.s 'frd, 'frs1, 'frs2", instr, RV_F);
+          }
+          break;
+        case JX:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fabs.s 'frd, 'frs1", instr, RV_F);
+          } else {
+            Print("fsgnjx.s 'frd, 'frs1, 'frs2", instr, RV_F);
+          }
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FMINMAXS: {
+      switch (instr.funct3()) {
+        case MIN:
+          Print("fmin.s 'frd, 'frs1, 'frs2", instr, RV_F);
+          break;
+        case MAX:
+          Print("fmax.s 'frd, 'frs1, 'frs2", instr, RV_F);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCMPS: {
+      switch (instr.funct3()) {
+        case FEQ:
+          Print("feq.s 'rd, 'frs1, 'frs2", instr, RV_F);
+          break;
+        case FLT:
+          Print("flt.s 'rd, 'frs1, 'frs2", instr, RV_F);
+          break;
+        case FLE:
+          Print("fle.s 'rd, 'frs1, 'frs2", instr, RV_F);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCLASSS:  // = FMVXW
+      switch (instr.funct3()) {
+        case 1:
+          Print("fclass.s 'rd, 'frs1", instr, RV_F);
+          break;
+        case 0:
+          Print("fmv.x.w 'rd, 'frs1", instr, RV_F);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case FCVTintS:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          Print("fcvt.w.s 'rd, 'frs1'round", instr, RV_F);
+          break;
+        case WU:
+          Print("fcvt.wu.s 'rd, 'frs1'round", instr, RV_F);
+          break;
+#if XLEN >= 64
+        case L:
+          Print("fcvt.l.s 'rd, 'frs1'round", instr, RV_F);
+          break;
+        case LU:
+          Print("fcvt.lu.s 'rd, 'frs1'round", instr, RV_F);
+          break;
+#endif
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case FCVTSint:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          Print("fcvt.s.w 'frd, 'rs1", instr, RV_F);
+          break;
+        case WU:
+          Print("fcvt.s.wu 'frd, 'rs1", instr, RV_F);
+          break;
+#if XLEN >= 64
+        case L:
+          Print("fcvt.s.l 'frd, 'rs1", instr, RV_F);
+          break;
+        case LU:
+          Print("fcvt.s.lu 'frd, 'rs1", instr, RV_F);
+          break;
+#endif
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case FMVWX:
+      Print("fmv.w.x 'frd, 'rs1", instr, RV_F);
+      break;
+    case FADDD:
+      Print("fadd.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
+      break;
+    case FSUBD:
+      Print("fsub.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
+      break;
+    case FMULD:
+      Print("fmul.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
+      break;
+    case FDIVD:
+      Print("fdiv.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
+      break;
+    case FSQRTD:
+      Print("fsqrt.d 'frd, 'frs1'round", instr, RV_D);
+      break;
+    case FSGNJD: {
+      switch (instr.funct3()) {
+        case J:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fmv.d 'frd, 'frs1", instr, RV_D);
+          } else {
+            Print("fsgnj.d 'frd, 'frs1, 'frs2", instr, RV_D);
+          }
+          break;
+        case JN:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fneg.d 'frd, 'frs1", instr, RV_D);
+          } else {
+            Print("fsgnjn.d 'frd, 'frs1, 'frs2", instr, RV_D);
+          }
+          break;
+        case JX:
+          if (instr.frs1() == instr.frs2()) {
+            Print("fabs.d 'frd, 'frs1", instr, RV_D);
+          } else {
+            Print("fsgnjx.d 'frd, 'frs1, 'frs2", instr, RV_D);
+          }
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FMINMAXD: {
+      switch (instr.funct3()) {
+        case MIN:
+          Print("fmin.d 'frd, 'frs1, 'frs2", instr, RV_D);
+          break;
+        case MAX:
+          Print("fmax.d 'frd, 'frs1, 'frs2", instr, RV_D);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCVTS: {
+      switch (instr.rs2()) {
+        case 1:
+          Print("fcvt.s.d 'frd, 'frs1'round", instr, RV_D);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCVTD: {
+      switch (instr.rs2()) {
+        case 0:
+          Print("fcvt.d.s 'frd, 'frs1", instr, RV_D);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCMPD: {
+      switch (instr.funct3()) {
+        case FEQ:
+          Print("feq.d 'rd, 'frs1, 'frs2", instr, RV_D);
+          break;
+        case FLT:
+          Print("flt.d 'rd, 'frs1, 'frs2", instr, RV_D);
+          break;
+        case FLE:
+          Print("fle.d 'rd, 'frs1, 'frs2", instr, RV_D);
+          break;
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    }
+    case FCLASSD:  // = FMVXD
+      switch (instr.funct3()) {
+        case 1:
+          Print("fclass.d 'rd, 'frs1", instr, RV_D);
+          break;
+#if XLEN >= 64
+        case 0:
+          Print("fmv.x.d 'rd, 'frs1", instr, RV_D);
+          break;
+#endif
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case FCVTintD:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          Print("fcvt.w.d 'rd, 'frs1'round", instr, RV_D);
+          break;
+        case WU:
+          Print("fcvt.wu.d 'rd, 'frs1'round", instr, RV_D);
+          break;
+#if XLEN >= 64
+        case L:
+          Print("fcvt.l.d 'rd, 'frs1'round", instr, RV_D);
+          break;
+        case LU:
+          Print("fcvt.lu.d 'rd, 'frs1'round", instr, RV_D);
+          break;
+#endif
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+    case FCVTDint:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          Print("fcvt.d.w 'frd, 'rs1", instr, RV_D);
+          break;
+        case WU:
+          Print("fcvt.d.wu 'frd, 'rs1", instr, RV_D);
+          break;
+#if XLEN >= 64
+        case L:
+          Print("fcvt.d.l 'frd, 'rs1", instr, RV_D);
+          break;
+        case LU:
+          Print("fcvt.d.lu 'frd, 'rs1", instr, RV_D);
+          break;
+#endif
+        default:
+          UnknownInstruction(instr);
+      }
+      break;
+#if XLEN >= 64
+    case FMVDX:
+      Print("fmv.d.x 'frd, 'rs1", instr, RV_D);
+      break;
+#endif
+    default:
+      UnknownInstruction(instr);
+  }
+}
+
+void RISCVDisassembler::UnknownInstruction(Instr instr) {
+  if (instr.encoding() == 0) {
+    Print("trap", instr, RV_I);
+  } else {
+    Print("unknown", instr, ExtensionSet::Empty());
+  }
+}
+
+void RISCVDisassembler::UnknownInstruction(CInstr instr) {
+  if (instr.encoding() == 0) {
+    Print("trap", instr, RV_I);
+  } else {
+    Print("unknown", instr, ExtensionSet::Empty());
+  }
+}
+
+void RISCVDisassembler::Print(const char* format,
+                              Instr instr,
+                              ExtensionSet ex) {
+  // Printf("  %08x ", instr.encoding());
+
+  while (format[0] != '\0') {
+    if (format[0] == '\'') {
+      format = PrintOption(format + 1, instr);
+    } else {
+      Printf("%c", format[0]);
+      format++;
+    }
+  }
+
+  // Printf("\n");
+}
+
+void RISCVDisassembler::Print(const char* format,
+                              CInstr instr,
+                              ExtensionSet ex) {
+  // Printf("      %04x ", instr.encoding());
+
+  while (format[0] != '\0') {
+    if (format[0] == '\'') {
+      format = PrintOption(format + 1, instr);
+    } else {
+      Printf("%c", format[0]);
+      format++;
+    }
+  }
+
+  // Printf("\n");
+}
+
+#define STRING_STARTS_WITH(string, compare_string)                             \
+  (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+const char* RISCVDisassembler::PrintOption(const char* format, Instr instr) {
+  if (STRING_STARTS_WITH(format, "rd")) {
+    Printf("%s", cpu_reg_names[instr.rd()]);
+    return format + 2;
+  } else if (STRING_STARTS_WITH(format, "rs1")) {
+    Printf("%s", cpu_reg_names[instr.rs1()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "rs2")) {
+    Printf("%s", cpu_reg_names[instr.rs2()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "shamt")) {
+    Printf("0x%x", instr.shamt());
+    return format + 5;
+  } else if (STRING_STARTS_WITH(format, "jimm")) {
+    Printf("%+" Pd, static_cast<intptr_t>(instr.jtype_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "uimm")) {
+    // objdump instead displays (imm >> 12) as hex.
+    Printf("%" Pd, static_cast<intptr_t>(instr.utype_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "iimm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.itype_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "simm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.stype_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "bimm")) {
+    Printf("%+" Pd, static_cast<intptr_t>(instr.btype_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "zimm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.zimm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "csr")) {
+    Printf("0x%" Px, static_cast<intptr_t>(instr.csr()));
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "order")) {
+    switch (instr.memory_order()) {
+      case std::memory_order_relaxed:
+        break;
+      case std::memory_order_acquire:
+        Printf(".aq");
+        break;
+      case std::memory_order_release:
+        Printf(".rl");
+        break;
+      case std::memory_order_acq_rel:
+        Printf(".aqrl");
+        break;
+      default:
+        UNREACHABLE();
+    }
+    return format + 5;
+  } else if (STRING_STARTS_WITH(format, "round")) {
+    switch (instr.rounding()) {
+      case RNE:
+        // Printf(", rne");
+        break;
+      case RTZ:
+        Printf(", rtz");
+        break;
+      case RDN:
+        Printf(", rdn");
+        break;
+      case RUP:
+        Printf(", rup");
+        break;
+      case RMM:
+        Printf(", rmm");
+        break;
+      case DYN:
+        Printf(", dyn");
+        break;
+      default:
+        Printf("<invalid rounding mode>");
+    }
+    return format + 5;
+  } else if (STRING_STARTS_WITH(format, "predsucc")) {
+    HartEffects pred = static_cast<HartEffects>((instr.itype_imm() >> 4) & 0xF);
+    HartEffects succ = static_cast<HartEffects>((instr.itype_imm() >> 0) & 0xF);
+    if ((pred != HartEffects::kAll) || (succ != HartEffects::kAll)) {
+      Printf(" ");
+      if ((pred & HartEffects::kInput) != 0) Printf("i");
+      if ((pred & HartEffects::kOutput) != 0) Printf("o");
+      if ((pred & HartEffects::kRead) != 0) Printf("r");
+      if ((pred & HartEffects::kWrite) != 0) Printf("w");
+      Printf(",");
+      if ((succ & HartEffects::kInput) != 0) Printf("i");
+      if ((succ & HartEffects::kOutput) != 0) Printf("o");
+      if ((succ & HartEffects::kRead) != 0) Printf("r");
+      if ((succ & HartEffects::kWrite) != 0) Printf("w");
+    }
+    return format + 8;
+  } else if (STRING_STARTS_WITH(format, "frd")) {
+    Printf("%s", fpu_reg_names[instr.frd()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "frs1")) {
+    Printf("%s", fpu_reg_names[instr.frs1()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "frs2")) {
+    Printf("%s", fpu_reg_names[instr.frs2()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "frs3")) {
+    Printf("%s", fpu_reg_names[instr.frs3()]);
+    return format + 4;
+  }
+
+  FATAL1("Bad format %s\n", format);
+  return nullptr;
+}
+
+const char* RISCVDisassembler::PrintOption(const char* format, CInstr instr) {
+  if (STRING_STARTS_WITH(format, "rdp")) {
+    Printf("%s", cpu_reg_names[instr.rdp()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "rs1p")) {
+    Printf("%s", cpu_reg_names[instr.rs1p()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "rs2p")) {
+    Printf("%s", cpu_reg_names[instr.rs2p()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "rd")) {
+    Printf("%s", cpu_reg_names[instr.rd()]);
+    return format + 2;
+  } else if (STRING_STARTS_WITH(format, "rs1")) {
+    Printf("%s", cpu_reg_names[instr.rs1()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "rs2")) {
+    Printf("%s", cpu_reg_names[instr.rs2()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "frdp")) {
+    Printf("%s", fpu_reg_names[instr.frdp()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "frs1p")) {
+    Printf("%s", fpu_reg_names[instr.frs1p()]);
+    return format + 5;
+  } else if (STRING_STARTS_WITH(format, "frs2p")) {
+    Printf("%s", fpu_reg_names[instr.frs2p()]);
+    return format + 5;
+  } else if (STRING_STARTS_WITH(format, "frd")) {
+    Printf("%s", fpu_reg_names[instr.frd()]);
+    return format + 3;
+  } else if (STRING_STARTS_WITH(format, "frs1")) {
+    Printf("%s", fpu_reg_names[instr.frs1()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "frs2")) {
+    Printf("%s", fpu_reg_names[instr.frs2()]);
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "spload4imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.spload4_imm()));
+    return format + 10;
+  } else if (STRING_STARTS_WITH(format, "spload8imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.spload8_imm()));
+    return format + 10;
+  } else if (STRING_STARTS_WITH(format, "spstore4imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.spstore4_imm()));
+    return format + 11;
+  } else if (STRING_STARTS_WITH(format, "spstore8imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.spstore8_imm()));
+    return format + 11;
+  } else if (STRING_STARTS_WITH(format, "mem4imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.mem4_imm()));
+    return format + 7;
+  } else if (STRING_STARTS_WITH(format, "mem8imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.mem8_imm()));
+    return format + 7;
+  } else if (STRING_STARTS_WITH(format, "jimm")) {
+    Printf("%+" Pd, static_cast<intptr_t>(instr.j_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "bimm")) {
+    Printf("%+" Pd, static_cast<intptr_t>(instr.b_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "iimm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.i_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "uimm")) {
+    // objdump instead displays (imm >> 12) as hex.
+    Printf("%" Pd, static_cast<intptr_t>(instr.u_imm()));
+    return format + 4;
+  } else if (STRING_STARTS_WITH(format, "i16imm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.i16_imm()));
+    return format + 6;
+  } else if (STRING_STARTS_WITH(format, "i4spnimm")) {
+    Printf("%" Pd, static_cast<intptr_t>(instr.i4spn_imm()));
+    return format + 8;
+  }
+
+  FATAL1("Bad format %s\n", format);
+  return nullptr;
+}
+
+void Disassembler::DecodeInstruction(char* hex_buffer,
+                                     intptr_t hex_size,
+                                     char* human_buffer,
+                                     intptr_t human_size,
+                                     int* out_instr_size,
+                                     const Code& code,
+                                     Object** object,
+                                     uword pc) {
+  RISCVDisassembler decoder(human_buffer, human_size,
+                            FLAG_use_compressed_instructions ? RV_GC : RV_G);
+  int instr_size = decoder.Disassemble(pc);
+  if (instr_size == 2) {
+    Utils::SNPrint(hex_buffer, hex_size, "    %04x",
+                   *reinterpret_cast<uint16_t*>(pc));
+  } else if (instr_size == 4) {
+    Utils::SNPrint(hex_buffer, hex_size, "%08x",
+                   *reinterpret_cast<uint32_t*>(pc));
+  }
+  if (out_instr_size) {
+    *out_instr_size = instr_size;
+  }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
+}
+
+#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 1dbf213..22ff2d3 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1954,136 +1954,153 @@
   }
 }
 
-static void UnboxPhi(PhiInstr* phi, bool is_aot) {
-  Representation unboxed = phi->representation();
+namespace {
+class PhiUnboxingHeuristic : public ValueObject {
+ public:
+  explicit PhiUnboxingHeuristic(FlowGraph* flow_graph)
+      : worklist_(flow_graph, 10) {}
 
-  switch (phi->Type()->ToCid()) {
-    case kDoubleCid:
-      if (CanUnboxDouble()) {
-        unboxed = kUnboxedDouble;
-      }
-      break;
-    case kFloat32x4Cid:
-      if (ShouldInlineSimd()) {
-        unboxed = kUnboxedFloat32x4;
-      }
-      break;
-    case kInt32x4Cid:
-      if (ShouldInlineSimd()) {
-        unboxed = kUnboxedInt32x4;
-      }
-      break;
-    case kFloat64x2Cid:
-      if (ShouldInlineSimd()) {
-        unboxed = kUnboxedFloat64x2;
-      }
-      break;
-  }
+  void Process(PhiInstr* phi) {
+    Representation unboxed = phi->representation();
 
-  // If all the inputs are unboxed, leave the Phi unboxed.
-  if ((unboxed == kTagged) && phi->Type()->IsInt()) {
-    bool should_unbox = true;
-    Representation new_representation = kTagged;
-    for (intptr_t i = 0; i < phi->InputCount(); i++) {
-      Definition* input = phi->InputAt(i)->definition();
-      if (input->representation() != kUnboxedInt64 &&
-          input->representation() != kUnboxedInt32 &&
-          input->representation() != kUnboxedUint32 && !(input == phi)) {
-        should_unbox = false;
+    switch (phi->Type()->ToCid()) {
+      case kDoubleCid:
+        if (CanUnboxDouble()) {
+          unboxed = kUnboxedDouble;
+        }
         break;
-      }
-
-      if (new_representation == kTagged) {
-        new_representation = input->representation();
-      } else if (new_representation != input->representation()) {
-        new_representation = kNoRepresentation;
-      }
-    }
-    if (should_unbox) {
-      unboxed = new_representation != kNoRepresentation
-                    ? new_representation
-                    : RangeUtils::Fits(phi->range(),
-                                       RangeBoundary::kRangeBoundaryInt32)
-                          ? kUnboxedInt32
-                          : kUnboxedInt64;
-    }
-  }
-
-  if ((unboxed == kTagged) && phi->Type()->IsInt() &&
-      !phi->Type()->can_be_sentinel()) {
-    // Conservatively unbox phis that:
-    //   - are proven to be of type Int;
-    //   - fit into 64bits range;
-    //   - have either constants or Box() operations as inputs;
-    //   - have at least one Box() operation as an input;
-    //   - are used in at least 1 Unbox() operation.
-    bool should_unbox = false;
-    for (intptr_t i = 0; i < phi->InputCount(); i++) {
-      Definition* input = phi->InputAt(i)->definition();
-      if (input->IsBox()) {
-        should_unbox = true;
-      } else if (!input->IsConstant()) {
-        should_unbox = false;
+      case kFloat32x4Cid:
+        if (ShouldInlineSimd()) {
+          unboxed = kUnboxedFloat32x4;
+        }
         break;
-      }
+      case kInt32x4Cid:
+        if (ShouldInlineSimd()) {
+          unboxed = kUnboxedInt32x4;
+        }
+        break;
+      case kFloat64x2Cid:
+        if (ShouldInlineSimd()) {
+          unboxed = kUnboxedFloat64x2;
+        }
+        break;
     }
 
-    if (should_unbox) {
-      // We checked inputs. Check if phi is used in at least one unbox
-      // operation.
-      bool has_unboxed_use = false;
-      for (Value* use = phi->input_use_list(); use != NULL;
-           use = use->next_use()) {
-        Instruction* instr = use->instruction();
-        if (instr->IsUnbox()) {
-          has_unboxed_use = true;
+    // If all the inputs are unboxed, leave the Phi unboxed.
+    if ((unboxed == kTagged) && phi->Type()->IsInt()) {
+      bool should_unbox = true;
+      Representation new_representation = kTagged;
+      for (auto input : phi->inputs()) {
+        if (input == phi) continue;
+
+        if (!IsUnboxedInteger(input->representation())) {
+          should_unbox = false;
           break;
-        } else if (IsUnboxedInteger(
-                       instr->RequiredInputRepresentation(use->use_index()))) {
-          has_unboxed_use = true;
-          break;
+        }
+
+        if (new_representation == kTagged) {
+          new_representation = input->representation();
+        } else if (new_representation != input->representation()) {
+          new_representation = kNoRepresentation;
         }
       }
 
-      if (!has_unboxed_use) {
-        should_unbox = false;
+      if (should_unbox) {
+        unboxed =
+            new_representation != kNoRepresentation ? new_representation
+            : RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
+                ? kUnboxedInt32
+                : kUnboxedInt64;
       }
     }
 
-    if (should_unbox) {
-      unboxed =
-          RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
-              ? kUnboxedInt32
-              : kUnboxedInt64;
-    }
-  }
-
+    // Decide if it is worth to unbox an integer phi.
+    if ((unboxed == kTagged) && phi->Type()->IsInt() &&
+        !phi->Type()->can_be_sentinel()) {
 #if defined(TARGET_ARCH_IS_64_BIT)
-  // In AOT mode on 64-bit platforms always unbox integer typed phis (similar
-  // to how we treat doubles and other boxed numeric types).
-  // In JIT mode only unbox phis which are not fully known to be Smi.
-  if ((unboxed == kTagged) && phi->Type()->IsInt() &&
-      !phi->Type()->can_be_sentinel() &&
-      (is_aot || phi->Type()->ToCid() != kSmiCid)) {
-    unboxed = kUnboxedInt64;
-  }
-#endif
+      // In AOT mode on 64-bit platforms always unbox integer typed phis
+      // (similar to how we treat doubles and other boxed numeric types).
+      // In JIT mode only unbox phis which are not fully known to be Smi.
+      if (is_aot_ || phi->Type()->ToCid() != kSmiCid) {
+        unboxed = kUnboxedInt64;
+      }
+#else
+      // If we are on a 32-bit platform check if there are unboxed values
+      // flowing into the phi and the phi value itself is flowing into an
+      // unboxed operation prefer to keep it unboxed.
+      // We use this heuristic instead of eagerly unboxing all the phis
+      // because we are concerned about the code size and register pressure.
+      const bool has_unboxed_incomming_value = HasUnboxedIncommingValue(phi);
+      const bool flows_into_unboxed_use = FlowsIntoUnboxedUse(phi);
 
-  phi->set_representation(unboxed);
-}
+      if (has_unboxed_incomming_value && flows_into_unboxed_use) {
+        unboxed =
+            RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
+                ? kUnboxedInt32
+                : kUnboxedInt64;
+      }
+#endif
+    }
+
+    phi->set_representation(unboxed);
+  }
+
+ private:
+  // Returns |true| iff there is an unboxed definition among all potential
+  // definitions that can flow into the |phi|.
+  // This function looks through phis.
+  bool HasUnboxedIncommingValue(PhiInstr* phi) {
+    worklist_.Clear();
+    worklist_.Add(phi);
+    for (intptr_t i = 0; i < worklist_.definitions().length(); i++) {
+      const auto defn = worklist_.definitions()[i];
+      for (auto input : defn->inputs()) {
+        if (IsUnboxedInteger(input->representation()) || input->IsBox()) {
+          return true;
+        } else if (input->IsPhi()) {
+          worklist_.Add(input);
+        }
+      }
+    }
+    return false;
+  }
+
+  // Returns |true| iff |phi| potentially flows into an unboxed use.
+  // This function looks through phis.
+  bool FlowsIntoUnboxedUse(PhiInstr* phi) {
+    worklist_.Clear();
+    worklist_.Add(phi);
+    for (intptr_t i = 0; i < worklist_.definitions().length(); i++) {
+      const auto defn = worklist_.definitions()[i];
+      for (auto use : defn->input_uses()) {
+        if (IsUnboxedInteger(use->instruction()->RequiredInputRepresentation(
+                use->use_index())) ||
+            use->instruction()->IsUnbox()) {
+          return true;
+        } else if (auto phi_use = use->instruction()->AsPhi()) {
+          worklist_.Add(phi_use);
+        }
+      }
+    }
+    return false;
+  }
+
+  const bool is_aot_ = CompilerState::Current().is_aot();
+  DefinitionWorklist worklist_;
+};
+}  // namespace
 
 void FlowGraph::SelectRepresentations() {
-  const auto is_aot = CompilerState::Current().is_aot();
-
   // First we decide for each phi if it is beneficial to unbox it. If so, we
   // change it's `phi->representation()`
+  PhiUnboxingHeuristic phi_unboxing_heuristic(this);
   for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
        block_it.Advance()) {
     JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
     if (join_entry != NULL) {
       for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
         PhiInstr* phi = it.Current();
-        UnboxPhi(phi, is_aot);
+        phi_unboxing_heuristic.Process(phi);
       }
     }
   }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index a6d5418..aa1d703 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -3572,60 +3572,6 @@
   }
 }
 
-void FlowGraphCompiler::EmitMoveConst(const compiler::ffi::NativeLocation& dst,
-                                      Location src,
-                                      Representation src_type,
-                                      TemporaryRegisterAllocator* temp) {
-  ASSERT(src.IsConstant());
-  const auto& dst_type = dst.payload_type();
-  if (dst.IsExpressibleAsLocation() &&
-      dst_type.IsExpressibleAsRepresentation() &&
-      dst_type.AsRepresentationOverApprox(zone_) == src_type) {
-    // We can directly emit the const in the right place and representation.
-    const Location dst_loc = dst.AsLocation();
-    EmitMove(dst_loc, src, temp);
-  } else {
-    // We need an intermediate location.
-    Location intermediate;
-    if (dst_type.IsInt()) {
-      if (TMP == kNoRegister) {
-        Register scratch = temp->AllocateTemporary();
-        Location::RegisterLocation(scratch);
-      } else {
-        intermediate = Location::RegisterLocation(TMP);
-      }
-    } else {
-      ASSERT(dst_type.IsFloat());
-      intermediate = Location::FpuRegisterLocation(FpuTMP);
-    }
-
-    if (src.IsPairLocation()) {
-      for (intptr_t i : {0, 1}) {
-        const Representation src_type_split =
-            compiler::ffi::NativeType::FromUnboxedRepresentation(zone_,
-                                                                 src_type)
-                .Split(zone_, i)
-                .AsRepresentation();
-        const auto& intermediate_native =
-            compiler::ffi::NativeLocation::FromLocation(zone_, intermediate,
-                                                        src_type_split);
-        EmitMove(intermediate, src.AsPairLocation()->At(i), temp);
-        EmitNativeMove(dst.Split(zone_, 2, i), intermediate_native, temp);
-      }
-    } else {
-      const auto& intermediate_native =
-          compiler::ffi::NativeLocation::FromLocation(zone_, intermediate,
-                                                      src_type);
-      EmitMove(intermediate, src, temp);
-      EmitNativeMove(dst, intermediate_native, temp);
-    }
-
-    if (dst_type.IsInt() && TMP == kNoRegister) {
-      temp->ReleaseTemporary();
-    }
-  }
-  return;
-}
 
 // The assignment to loading units here must match that in
 // AssignLoadingUnitsCodeVisitor, which runs after compilation is done.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 975e431..f53e11f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -613,12 +613,6 @@
                           const compiler::ffi::NativeLocation& src,
                           TemporaryRegisterAllocator* temp);
 
-  // Emits a Dart const to a native location.
-  void EmitMoveConst(const compiler::ffi::NativeLocation& dst,
-                     Location src,
-                     Representation src_type,
-                     TemporaryRegisterAllocator* temp);
-
   bool CheckAssertAssignableTypeTestingABILocations(
       const LocationSummary& locs);
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
new file mode 100644
index 0000000..c31d864
--- /dev/null
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -0,0 +1,1164 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/backend/flow_graph_compiler.h"
+
+#include "vm/compiler/api/type_check_mode.h"
+#include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/compiler/jit/compiler.h"
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
+#include "vm/deopt_instructions.h"
+#include "vm/dispatch_table.h"
+#include "vm/instructions.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
+DECLARE_FLAG(bool, enable_simd_inline);
+
+void FlowGraphCompiler::ArchSpecificInitialization() {
+  // Note: Unlike the other architectures, we are not using PC-relative calls
+  // in AOT to call the write barrier stubs. We are making use of TMP as an
+  // alternate link register to avoid spilling RA inline and don't want to
+  // introduce another relocation type.
+}
+
+FlowGraphCompiler::~FlowGraphCompiler() {
+  // BlockInfos are zone-allocated, so their destructors are not called.
+  // Verify the labels explicitly here.
+  for (int i = 0; i < block_info_.length(); ++i) {
+    ASSERT(!block_info_[i]->jump_label()->IsLinked());
+  }
+}
+
+bool FlowGraphCompiler::SupportsUnboxedDoubles() {
+  return true;
+}
+
+bool FlowGraphCompiler::SupportsUnboxedSimd128() {
+  // TODO(riscv): Dynamically test for the vector extension and otherwise
+  // allocate SIMD values to register-pairs or quads?
+  return false;
+}
+
+bool FlowGraphCompiler::CanConvertInt64ToDouble() {
+#if XLEN == 32
+  return false;
+#else
+  return true;
+#endif
+}
+
+void FlowGraphCompiler::EnterIntrinsicMode() {
+  ASSERT(!intrinsic_mode());
+  intrinsic_mode_ = true;
+  ASSERT(!assembler()->constant_pool_allowed());
+}
+
+void FlowGraphCompiler::ExitIntrinsicMode() {
+  ASSERT(intrinsic_mode());
+  intrinsic_mode_ = false;
+}
+
+TypedDataPtr CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+                                                DeoptInfoBuilder* builder,
+                                                const Array& deopt_table) {
+  if (deopt_env_ == NULL) {
+    ++builder->current_info_number_;
+    return TypedData::null();
+  }
+
+  intptr_t stack_height = compiler->StackSize();
+  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
+
+  intptr_t slot_ix = 0;
+  Environment* current = deopt_env_;
+
+  // Emit all kMaterializeObject instructions describing objects to be
+  // materialized on the deoptimization as a prefix to the deoptimization info.
+  EmitMaterializations(deopt_env_, builder);
+
+  // The real frame starts here.
+  builder->MarkFrameStart();
+
+  Zone* zone = compiler->zone();
+
+  builder->AddPp(current->function(), slot_ix++);
+  builder->AddPcMarker(Function::ZoneHandle(zone), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+
+  // Emit all values that are needed for materialization as a part of the
+  // expression stack for the bottom-most frame. This guarantees that GC
+  // will be able to find them during materialization.
+  slot_ix = builder->EmitMaterializationArguments(slot_ix);
+
+  // For the innermost environment, set outgoing arguments and the locals.
+  for (intptr_t i = current->Length() - 1;
+       i >= current->fixed_parameter_count(); i--) {
+    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+  }
+
+  Environment* previous = current;
+  current = current->outer();
+  while (current != NULL) {
+    builder->AddPp(current->function(), slot_ix++);
+    builder->AddPcMarker(previous->function(), slot_ix++);
+    builder->AddCallerFp(slot_ix++);
+
+    // For any outer environment the deopt id is that of the call instruction
+    // which is recorded in the outer environment.
+    builder->AddReturnAddress(current->function(),
+                              DeoptId::ToDeoptAfter(current->GetDeoptId()),
+                              slot_ix++);
+
+    // The values of outgoing arguments can be changed from the inlined call so
+    // we must read them from the previous environment.
+    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+      builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i),
+                       slot_ix++);
+    }
+
+    // Set the locals, note that outgoing arguments are not in the environment.
+    for (intptr_t i = current->Length() - 1;
+         i >= current->fixed_parameter_count(); i--) {
+      builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
+    }
+
+    // Iterate on the outer environment.
+    previous = current;
+    current = current->outer();
+  }
+  // The previous pointer is now the outermost environment.
+  ASSERT(previous != NULL);
+
+  // Add slots for the outermost environment.
+  builder->AddCallerPp(slot_ix++);
+  builder->AddPcMarker(previous->function(), slot_ix++);
+  builder->AddCallerFp(slot_ix++);
+  builder->AddCallerPc(slot_ix++);
+
+  // For the outermost environment, set the incoming arguments.
+  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
+    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
+  }
+
+  return builder->CreateDeoptInfo(deopt_table);
+}
+
+void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
+                                             intptr_t stub_ix) {
+  // Calls do not need stubs, they share a deoptimization trampoline.
+  ASSERT(reason() != ICData::kDeoptAtCall);
+  compiler::Assembler* assembler = compiler->assembler();
+#define __ assembler->
+  __ Comment("%s", Name());
+  __ Bind(entry_label());
+  if (FLAG_trap_on_deoptimization) {
+    __ trap();
+  }
+
+  ASSERT(deopt_env() != NULL);
+  __ Call(compiler::Address(THR, Thread::deoptimize_entry_offset()));
+  set_pc_offset(assembler->CodeSize());
+#undef __
+}
+
+#define __ assembler->
+// Static methods of FlowGraphCompiler that take an assembler.
+
+void FlowGraphCompiler::GenerateIndirectTTSCall(compiler::Assembler* assembler,
+                                                Register reg_to_call,
+                                                intptr_t sub_type_cache_index) {
+  __ LoadField(
+      TTSInternalRegs::kScratchReg,
+      compiler::FieldAddress(
+          reg_to_call,
+          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
+  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
+                           sub_type_cache_index);
+  __ jalr(TTSInternalRegs::kScratchReg);
+}
+
+#undef __
+#define __ assembler()->
+// Instance methods of FlowGraphCompiler.
+
+// Fall through if bool_register contains null.
+void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
+                                           compiler::Label* is_true,
+                                           compiler::Label* is_false) {
+  compiler::Label fall_through;
+  __ beq(bool_register, NULL_REG, &fall_through,
+         compiler::Assembler::kNearJump);
+  BranchLabels labels = {is_true, is_false, &fall_through};
+  Condition true_condition =
+      EmitBoolTest(bool_register, labels, /*invert=*/false);
+  ASSERT(true_condition != kInvalidCondition);
+  __ BranchIf(true_condition, is_true);
+  __ j(is_false);
+  __ Bind(&fall_through);
+}
+
+void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
+  if (is_optimizing()) {
+    return;
+  }
+  Definition* defn = instr->AsDefinition();
+  if ((defn != NULL) && defn->HasTemp()) {
+    const Location value = defn->locs()->out(0);
+    if (value.IsRegister()) {
+      __ PushRegister(value.reg());
+    } else if (value.IsFpuRegister()) {
+      ASSERT(instr->representation() == kUnboxedDouble);
+      // In unoptimized code at instruction epilogue the only
+      // live register is an output register.
+      instr->locs()->live_registers()->Clear();
+      __ MoveUnboxedDouble(BoxDoubleStubABI::kValueReg, value.fpu_reg());
+      GenerateNonLazyDeoptableStubCall(
+          InstructionSource(),  // No token position.
+          StubCode::BoxDouble(), UntaggedPcDescriptors::kOther, instr->locs());
+      __ PushRegister(BoxDoubleStubABI::kResultReg);
+    } else {
+      UNREACHABLE();
+    }
+  }
+}
+
+void FlowGraphCompiler::GenerateMethodExtractorIntrinsic(
+    const Function& extracted_method,
+    intptr_t type_arguments_field_offset) {
+  // No frame has been setup here.
+  ASSERT(!__ constant_pool_allowed());
+  ASSERT(extracted_method.IsZoneHandle());
+
+  const Code& build_method_extractor =
+      Code::ZoneHandle(extracted_method.IsGeneric()
+                           ? isolate_group()
+                                 ->object_store()
+                                 ->build_generic_method_extractor_code()
+                           : isolate_group()
+                                 ->object_store()
+                                 ->build_nongeneric_method_extractor_code());
+
+  const intptr_t stub_index = __ object_pool_builder().AddObject(
+      build_method_extractor, ObjectPool::Patchability::kNotPatchable);
+  const intptr_t function_index = __ object_pool_builder().AddObject(
+      extracted_method, ObjectPool::Patchability::kNotPatchable);
+
+  // We use a custom pool register to preserve caller PP.
+  Register kPoolReg = A1;
+
+  // T1 = extracted function
+  // T4 = offset of type argument vector (or 0 if class is not generic)
+  intptr_t pp_offset = 0;
+  if (FLAG_precompiled_mode) {
+    // PP is not tagged on riscv.
+    kPoolReg = PP;
+    pp_offset = kHeapObjectTag;
+  } else {
+    __ LoadFieldFromOffset(kPoolReg, CODE_REG, Code::object_pool_offset());
+  }
+  __ LoadImmediate(T4, type_arguments_field_offset);
+  __ LoadFieldFromOffset(
+      T1, kPoolReg, ObjectPool::element_offset(function_index) + pp_offset);
+  __ LoadFieldFromOffset(CODE_REG, kPoolReg,
+                         ObjectPool::element_offset(stub_index) + pp_offset);
+  __ LoadFieldFromOffset(TMP, CODE_REG,
+                         Code::entry_point_offset(Code::EntryKind::kUnchecked));
+  __ jr(TMP);
+}
+
+void FlowGraphCompiler::EmitFrameEntry() {
+  const Function& function = parsed_function().function();
+  if (CanOptimizeFunction() && function.IsOptimizable() &&
+      (!is_optimizing() || may_reoptimize())) {
+    __ Comment("Invocation Count Check");
+    const Register function_reg = A0;
+    const Register usage_reg = A1;
+    __ lx(function_reg, compiler::FieldAddress(CODE_REG, Code::owner_offset()));
+
+    __ LoadFieldFromOffset(usage_reg, function_reg,
+                           Function::usage_counter_offset(),
+                           compiler::kFourBytes);
+    // Reoptimization of an optimized function is triggered by counting in
+    // IC stubs, but not at the entry of the function.
+    if (!is_optimizing()) {
+      __ addi(usage_reg, usage_reg, 1);
+      __ StoreFieldToOffset(usage_reg, function_reg,
+                            Function::usage_counter_offset(),
+                            compiler::kFourBytes);
+    }
+    __ CompareImmediate(usage_reg, GetOptimizationThreshold());
+    compiler::Label dont_optimize;
+    __ BranchIf(LT, &dont_optimize, compiler::Assembler::kNearJump);
+    __ lx(TMP, compiler::Address(THR, Thread::optimize_entry_offset()));
+    __ jr(TMP);
+    __ Bind(&dont_optimize);
+  }
+
+  if (flow_graph().graph_entry()->NeedsFrame()) {
+    __ Comment("Enter frame");
+    if (flow_graph().IsCompiledForOsr()) {
+      const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
+      ASSERT(extra_slots >= 0);
+      __ EnterOsrFrame(extra_slots * kWordSize);
+    } else {
+      ASSERT(StackSize() >= 0);
+      __ EnterDartFrame(StackSize() * kWordSize);
+    }
+  } else if (FLAG_precompiled_mode) {
+    assembler()->set_constant_pool_allowed(true);
+  }
+}
+
+const InstructionSource& PrologueSource() {
+  static InstructionSource prologue_source(TokenPosition::kDartCodePrologue,
+                                           /*inlining_id=*/0);
+  return prologue_source;
+}
+
+void FlowGraphCompiler::EmitPrologue() {
+  BeginCodeSourceRange(PrologueSource());
+
+  EmitFrameEntry();
+  ASSERT(assembler()->constant_pool_allowed());
+
+  // In unoptimized code, initialize (non-argument) stack allocated slots.
+  if (!is_optimizing()) {
+    const int num_locals = parsed_function().num_stack_locals();
+
+    intptr_t args_desc_slot = -1;
+    if (parsed_function().has_arg_desc_var()) {
+      args_desc_slot = compiler::target::frame_layout.FrameSlotForVariable(
+          parsed_function().arg_desc_var());
+    }
+
+    __ Comment("Initialize spill slots");
+    for (intptr_t i = 0; i < num_locals; ++i) {
+      const intptr_t slot_index =
+          compiler::target::frame_layout.FrameSlotForVariableIndex(-i);
+      Register value_reg =
+          slot_index == args_desc_slot ? ARGS_DESC_REG : NULL_REG;
+      __ StoreToOffset(value_reg, FP, slot_index * kWordSize);
+      // TODO(riscv): Using an SP-relative address instead of an FP-relative
+      // address would allow for compressed instructions.
+    }
+  }
+
+  EndCodeSourceRange(PrologueSource());
+}
+
+void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
+  if (CanPcRelativeCall(stub)) {
+    __ GenerateUnRelocatedPcRelativeCall();
+    AddPcRelativeCallStubTarget(stub);
+  } else {
+    __ JumpAndLink(stub);
+    AddStubCallTarget(stub);
+  }
+}
+
+void FlowGraphCompiler::EmitTailCallToStub(const Code& stub) {
+  ASSERT(!stub.IsNull());
+  if (CanPcRelativeCall(stub)) {
+    __ LeaveDartFrame();
+    __ GenerateUnRelocatedPcRelativeTailCall();
+    AddPcRelativeTailCallStubTarget(stub);
+#if defined(DEBUG)
+    __ Breakpoint();
+#endif
+  } else {
+    __ LoadObject(CODE_REG, stub);
+    __ LeaveDartFrame();
+    __ lx(TMP, compiler::FieldAddress(
+                   CODE_REG, compiler::target::Code::entry_point_offset()));
+    __ jr(TMP);
+    AddStubCallTarget(stub);
+  }
+}
+
+void FlowGraphCompiler::GeneratePatchableCall(const InstructionSource& source,
+                                              const Code& stub,
+                                              UntaggedPcDescriptors::Kind kind,
+                                              LocationSummary* locs) {
+  __ JumpAndLinkPatchable(stub);
+  EmitCallsiteMetadata(source, DeoptId::kNone, kind, locs,
+                       pending_deoptimization_env_);
+}
+
+void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
+                                         const InstructionSource& source,
+                                         const Code& stub,
+                                         UntaggedPcDescriptors::Kind kind,
+                                         LocationSummary* locs,
+                                         Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  __ JumpAndLinkPatchable(stub, entry_kind);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs,
+                       pending_deoptimization_env_);
+}
+
+void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
+                                               const InstructionSource& source,
+                                               UntaggedPcDescriptors::Kind kind,
+                                               LocationSummary* locs,
+                                               const Function& target,
+                                               Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  if (CanPcRelativeCall(target)) {
+    __ GenerateUnRelocatedPcRelativeCall();
+    AddPcRelativeCallTarget(target, entry_kind);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs,
+                         pending_deoptimization_env_);
+  } else {
+    // Call sites to the same target can share object pool entries. These
+    // call sites are never patched for breakpoints: the function is deoptimized
+    // and the unoptimized code with IC calls for static calls is patched
+    // instead.
+    ASSERT(is_optimizing());
+    const auto& stub = StubCode::CallStaticFunction();
+    __ JumpAndLinkWithEquivalence(stub, target, entry_kind);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs,
+                         pending_deoptimization_env_);
+    AddStaticCallTarget(target, entry_kind);
+  }
+}
+
+void FlowGraphCompiler::EmitEdgeCounter(intptr_t edge_id) {
+  // We do not check for overflow when incrementing the edge counter.  The
+  // function should normally be optimized long before the counter can
+  // overflow; and though we do not reset the counters when we optimize or
+  // deoptimize, there is a bound on the number of
+  // optimization/deoptimization cycles we will attempt.
+  ASSERT(!edge_counters_array_.IsNull());
+  ASSERT(assembler_->constant_pool_allowed());
+  __ Comment("Edge counter");
+  __ LoadObject(A0, edge_counters_array_);
+  __ LoadFieldFromOffset(TMP, A0, Array::element_offset(edge_id));
+  __ addi(TMP, TMP, Smi::RawValue(1));
+  __ StoreFieldToOffset(TMP, A0, Array::element_offset(edge_id));
+}
+
+void FlowGraphCompiler::EmitOptimizedInstanceCall(
+    const Code& stub,
+    const ICData& ic_data,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  // Each ICData propagated from unoptimized to optimized code contains the
+  // function that corresponds to the Dart function of that IC call. Due
+  // to inlining in optimized code, that function may not correspond to the
+  // top-level function (parsed_function().function()) which could be
+  // reoptimized and which counter needs to be incremented.
+  // Pass the function explicitly, it is used in IC stub.
+
+  __ LoadObject(A6, parsed_function().function());
+  __ LoadFromOffset(A0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
+  __ LoadUniqueObject(IC_DATA_REG, ic_data);
+  GenerateDartCall(deopt_id, source, stub, UntaggedPcDescriptors::kIcCall, locs,
+                   entry_kind);
+  __ Drop(ic_data.SizeWithTypeArgs());
+}
+
+void FlowGraphCompiler::EmitInstanceCallJIT(const Code& stub,
+                                            const ICData& ic_data,
+                                            intptr_t deopt_id,
+                                            const InstructionSource& source,
+                                            LocationSummary* locs,
+                                            Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  ASSERT(entry_kind == Code::EntryKind::kNormal ||
+         entry_kind == Code::EntryKind::kUnchecked);
+  ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
+  __ LoadFromOffset(A0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
+  __ LoadUniqueObject(IC_DATA_REG, ic_data);
+  __ LoadUniqueObject(CODE_REG, stub);
+  const intptr_t entry_point_offset =
+      entry_kind == Code::EntryKind::kNormal
+          ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
+          : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
+  __ lx(RA, compiler::FieldAddress(CODE_REG, entry_point_offset));
+  __ jalr(RA);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kIcCall, locs,
+                       pending_deoptimization_env_);
+  __ Drop(ic_data.SizeWithTypeArgs());
+}
+
+void FlowGraphCompiler::EmitMegamorphicInstanceCall(
+    const String& name,
+    const Array& arguments_descriptor,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs) {
+  ASSERT(CanCallDart());
+  ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
+  const ArgumentsDescriptor args_desc(arguments_descriptor);
+  const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
+      zone(),
+      MegamorphicCacheTable::Lookup(thread(), name, arguments_descriptor));
+
+  __ Comment("MegamorphicCall");
+  // Load receiver into A0.
+  __ LoadFromOffset(A0, SP,
+                    (args_desc.Count() - 1) * compiler::target::kWordSize);
+  // Use same code pattern as instance call so it can be parsed by code patcher.
+  if (FLAG_precompiled_mode) {
+    UNIMPLEMENTED();
+  } else {
+    __ LoadUniqueObject(IC_DATA_REG, cache);
+    __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
+    __ Call(compiler::FieldAddress(
+        CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+  }
+
+  RecordSafepoint(locs);
+  AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
+  if (!FLAG_precompiled_mode) {
+    const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
+    if (is_optimizing()) {
+      AddDeoptIndexAtCall(deopt_id_after, pending_deoptimization_env_);
+    } else {
+      // Add deoptimization continuation point after the call and before the
+      // arguments are removed.
+      AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after,
+                           source);
+    }
+  }
+  RecordCatchEntryMoves(pending_deoptimization_env_);
+  __ Drop(args_desc.SizeWithTypeArgs());
+}
+
+void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
+                                            intptr_t deopt_id,
+                                            const InstructionSource& source,
+                                            LocationSummary* locs,
+                                            Code::EntryKind entry_kind,
+                                            bool receiver_can_be_smi) {
+  ASSERT(CanCallDart());
+  ASSERT(ic_data.NumArgsTested() == 1);
+  const Code& initial_stub = StubCode::SwitchableCallMiss();
+  const char* switchable_call_mode = "smiable";
+  if (!receiver_can_be_smi) {
+    switchable_call_mode = "non-smi";
+    ic_data.set_receiver_cannot_be_smi(true);
+  }
+  const UnlinkedCall& data =
+      UnlinkedCall::ZoneHandle(zone(), ic_data.AsUnlinkedCall());
+
+  __ Comment("InstanceCallAOT (%s)", switchable_call_mode);
+  // Clear argument descriptor to keep gc happy when it gets pushed on to
+  // the stack.
+  __ LoadImmediate(ARGS_DESC_REG, 0);
+  __ LoadFromOffset(A0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
+  if (FLAG_precompiled_mode) {
+    // The AOT runtime will replace the slot in the object pool with the
+    // entrypoint address - see app_snapshot.cc.
+    __ LoadUniqueObject(RA, initial_stub);
+  } else {
+    __ LoadUniqueObject(CODE_REG, initial_stub);
+    const intptr_t entry_point_offset =
+        entry_kind == Code::EntryKind::kNormal
+            ? compiler::target::Code::entry_point_offset(
+                  Code::EntryKind::kMonomorphic)
+            : compiler::target::Code::entry_point_offset(
+                  Code::EntryKind::kMonomorphicUnchecked);
+    __ lx(RA, compiler::FieldAddress(CODE_REG, entry_point_offset));
+  }
+  __ LoadUniqueObject(IC_DATA_REG, data);
+  __ jalr(RA);
+
+  EmitCallsiteMetadata(source, DeoptId::kNone, UntaggedPcDescriptors::kOther,
+                       locs, pending_deoptimization_env_);
+  __ Drop(ic_data.SizeWithTypeArgs());
+}
+
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    const ICData& ic_data,
+    Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  const Code& stub =
+      StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
+  __ LoadObject(IC_DATA_REG, ic_data);
+  GenerateDartCall(deopt_id, source, stub,
+                   UntaggedPcDescriptors::kUnoptStaticCall, locs, entry_kind);
+  __ Drop(size_with_type_args);
+}
+
+void FlowGraphCompiler::EmitOptimizedStaticCall(
+    const Function& function,
+    const Array& arguments_descriptor,
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
+  ASSERT(!function.IsClosureFunction());
+  if (function.HasOptionalParameters() || function.IsGeneric()) {
+    __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
+  } else {
+    if (!FLAG_precompiled_mode) {
+      __ LoadImmediate(ARGS_DESC_REG, 0);  // GC safe smi zero because of stub.
+    }
+  }
+  // Do not use the code from the function, but let the code be patched so that
+  // we can record the outgoing edges to other code.
+  GenerateStaticDartCall(deopt_id, source, UntaggedPcDescriptors::kOther, locs,
+                         function, entry_kind);
+  __ Drop(size_with_type_args);
+}
+
+void FlowGraphCompiler::EmitDispatchTableCall(
+    int32_t selector_offset,
+    const Array& arguments_descriptor) {
+  const auto cid_reg = DispatchTableNullErrorABI::kClassIdReg;
+  ASSERT(CanCallDart());
+  ASSERT(cid_reg != ARGS_DESC_REG);
+  if (!arguments_descriptor.IsNull()) {
+    __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
+  }
+  const intptr_t offset = selector_offset - DispatchTable::OriginElement();
+  // Would like cid_reg to be available on entry to the target function
+  // for checking purposes.
+  ASSERT(cid_reg != TMP);
+  intx_t imm = offset << compiler::target::kWordSizeLog2;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  __ slli(TMP, cid_reg, compiler::target::kWordSizeLog2);
+  if (hi != 0) {
+    __ lui(TMP2, hi);
+    __ add(TMP, TMP, TMP2);
+  }
+  __ add(TMP, TMP, DISPATCH_TABLE_REG);
+  __ lx(TMP, compiler::Address(TMP, lo));
+  __ jalr(TMP);
+}
+
+Condition FlowGraphCompiler::EmitEqualityRegConstCompare(
+    Register reg,
+    const Object& obj,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
+  if (needs_number_check) {
+    ASSERT(!obj.IsMint() && !obj.IsDouble());
+    __ LoadObject(TMP, obj);
+    __ PushRegisterPair(TMP, reg);
+    if (is_optimizing()) {
+      __ JumpAndLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
+    } else {
+      __ JumpAndLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
+    }
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
+    __ PopRegisterPair(ZR, reg);
+    // RISC-V has no condition flags, so the result is instead returned as
+    // TMP zero if equal, non-zero if non-equal.
+    ASSERT(reg != TMP);
+    __ CompareImmediate(TMP, 0);
+  } else {
+    __ CompareObject(reg, obj);
+  }
+  return EQ;
+}
+
+Condition FlowGraphCompiler::EmitEqualityRegRegCompare(
+    Register left,
+    Register right,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
+  if (needs_number_check) {
+    __ PushRegisterPair(right, left);
+    if (is_optimizing()) {
+      __ JumpAndLinkPatchable(StubCode::OptimizedIdenticalWithNumberCheck());
+    } else {
+      __ JumpAndLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
+    }
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
+    __ PopRegisterPair(right, left);
+    // RISC-V has no condition flags, so the result is instead returned as
+    // TMP zero if equal, non-zero if non-equal.
+    ASSERT(left != TMP);
+    ASSERT(right != TMP);
+    __ CompareImmediate(TMP, 0);
+  } else {
+    __ CompareObjectRegisters(left, right);
+  }
+  return EQ;
+}
+
+Condition FlowGraphCompiler::EmitBoolTest(Register value,
+                                          BranchLabels labels,
+                                          bool invert) {
+  __ Comment("BoolTest");
+  __ TestImmediate(value, compiler::target::ObjectAlignment::kBoolValueMask);
+  return invert ? NE : EQ;
+}
+
+// This function must be in sync with FlowGraphCompiler::RecordSafepoint and
+// FlowGraphCompiler::SlowPathEnvironmentFor.
+void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
+#if defined(DEBUG)
+  locs->CheckWritableInputs();
+  ClobberDeadTempRegisters(locs);
+#endif
+  // TODO(vegorov): consider saving only caller save (volatile) registers.
+  __ PushRegisters(*locs->live_registers());
+}
+
+void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
+  __ PopRegisters(*locs->live_registers());
+}
+
+#if defined(DEBUG)
+void FlowGraphCompiler::ClobberDeadTempRegisters(LocationSummary* locs) {
+  // Clobber temporaries that have not been manually preserved.
+  for (intptr_t i = 0; i < locs->temp_count(); ++i) {
+    Location tmp = locs->temp(i);
+    // TODO(zerny): clobber non-live temporary FPU registers.
+    if (tmp.IsRegister() &&
+        !locs->live_registers()->ContainsRegister(tmp.reg())) {
+      __ li(tmp.reg(), 0xf7);
+    }
+  }
+}
+#endif
+
+Register FlowGraphCompiler::EmitTestCidRegister() {
+  return A1;
+}
+
+void FlowGraphCompiler::EmitTestAndCallLoadReceiver(
+    intptr_t count_without_type_args,
+    const Array& arguments_descriptor) {
+  __ Comment("EmitTestAndCall");
+  // Load receiver into A0.
+  __ LoadFromOffset(A0, SP, (count_without_type_args - 1) * kWordSize);
+  __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
+}
+
+void FlowGraphCompiler::EmitTestAndCallSmiBranch(compiler::Label* label,
+                                                 bool if_smi) {
+  if (if_smi) {
+    __ BranchIfSmi(A0, label);
+  } else {
+    __ BranchIfNotSmi(A0, label);
+  }
+}
+
+void FlowGraphCompiler::EmitTestAndCallLoadCid(Register class_id_reg) {
+  ASSERT(class_id_reg != A0);
+  __ LoadClassId(class_id_reg, A0);
+}
+
+#undef __
+#define __ assembler->
+
+int FlowGraphCompiler::EmitTestAndCallCheckCid(compiler::Assembler* assembler,
+                                               compiler::Label* label,
+                                               Register class_id_reg,
+                                               const CidRangeValue& range,
+                                               int bias,
+                                               bool jump_on_miss) {
+  const intptr_t cid_start = range.cid_start;
+  if (range.IsSingleCid()) {
+    __ AddImmediate(class_id_reg, class_id_reg, bias - cid_start);
+    if (jump_on_miss) {
+      __ bnez(class_id_reg, label);
+    } else {
+      __ beqz(class_id_reg, label);
+    }
+    bias = cid_start;
+  } else {
+    __ AddImmediate(class_id_reg, class_id_reg, bias - cid_start);
+    bias = cid_start;
+    __ CompareImmediate(class_id_reg, range.Extent());
+    __ BranchIf(jump_on_miss ? UNSIGNED_GREATER : UNSIGNED_LESS_EQUAL, label);
+  }
+  return bias;
+}
+
+#undef __
+#define __ assembler()->
+
+void FlowGraphCompiler::EmitMove(Location destination,
+                                 Location source,
+                                 TemporaryRegisterAllocator* allocator) {
+  if (destination.Equals(source)) return;
+
+  if (source.IsRegister()) {
+    if (destination.IsRegister()) {
+      __ mv(destination.reg(), source.reg());
+    } else {
+      ASSERT(destination.IsStackSlot());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset);
+    }
+  } else if (source.IsStackSlot()) {
+    if (destination.IsRegister()) {
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      __ LoadFromOffset(destination.reg(), source.base_reg(), source_offset);
+    } else if (destination.IsFpuRegister()) {
+      const intptr_t src_offset = source.ToStackSlotOffset();
+      FRegister dst = destination.fpu_reg();
+      __ fld(dst, compiler::Address(source.base_reg(), src_offset));
+    } else {
+      ASSERT(destination.IsStackSlot());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      Register tmp = allocator->AllocateTemporary();
+      __ LoadFromOffset(tmp, source.base_reg(), source_offset);
+      __ StoreToOffset(tmp, destination.base_reg(), dest_offset);
+      allocator->ReleaseTemporary();
+    }
+  } else if (source.IsFpuRegister()) {
+    if (destination.IsFpuRegister()) {
+      __ fmvd(destination.fpu_reg(), source.fpu_reg());
+    } else {
+      if (destination.IsStackSlot() /*32-bit float*/ ||
+          destination.IsDoubleStackSlot()) {
+        const intptr_t dest_offset = destination.ToStackSlotOffset();
+        FRegister src = source.fpu_reg();
+        __ fsd(src, compiler::Address(destination.base_reg(), dest_offset));
+      } else {
+        ASSERT(destination.IsQuadStackSlot());
+        UNIMPLEMENTED();
+      }
+    }
+  } else if (source.IsDoubleStackSlot()) {
+    if (destination.IsFpuRegister()) {
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const FRegister dst = destination.fpu_reg();
+      __ fld(dst, compiler::Address(source.base_reg(), source_offset));
+    } else {
+      ASSERT(destination.IsDoubleStackSlot() ||
+             destination.IsStackSlot() /*32-bit float*/);
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ fld(FTMP, compiler::Address(source.base_reg(), source_offset));
+      __ fsd(FTMP, compiler::Address(destination.base_reg(), dest_offset));
+    }
+  } else if (source.IsQuadStackSlot()) {
+    UNIMPLEMENTED();
+  } else if (source.IsPairLocation()) {
+#if XLEN == 32
+    ASSERT(destination.IsPairLocation());
+    for (intptr_t i : {0, 1}) {
+      EmitMove(destination.Component(i), source.Component(i), allocator);
+    }
+#else
+    UNREACHABLE();
+#endif
+  } else {
+    ASSERT(source.IsConstant());
+    if (destination.IsStackSlot()) {
+      Register tmp = allocator->AllocateTemporary();
+      source.constant_instruction()->EmitMoveToLocation(this, destination, tmp,
+                                                        source.pair_index());
+      allocator->ReleaseTemporary();
+    } else {
+      source.constant_instruction()->EmitMoveToLocation(
+          this, destination, kNoRegister, source.pair_index());
+    }
+  }
+}
+
+static compiler::OperandSize BytesToOperandSize(intptr_t bytes) {
+  switch (bytes) {
+    case 8:
+      return compiler::OperandSize::kEightBytes;
+    case 4:
+      return compiler::OperandSize::kFourBytes;
+    case 2:
+      return compiler::OperandSize::kTwoBytes;
+    case 1:
+      return compiler::OperandSize::kByte;
+    default:
+      UNIMPLEMENTED();
+  }
+}
+
+void FlowGraphCompiler::EmitNativeMoveArchitecture(
+    const compiler::ffi::NativeLocation& destination,
+    const compiler::ffi::NativeLocation& source) {
+  const auto& src_type = source.payload_type();
+  const auto& dst_type = destination.payload_type();
+  ASSERT(src_type.IsFloat() == dst_type.IsFloat());
+  ASSERT(src_type.IsInt() == dst_type.IsInt());
+  ASSERT(src_type.IsSigned() == dst_type.IsSigned());
+  ASSERT(src_type.IsPrimitive());
+  ASSERT(dst_type.IsPrimitive());
+  const intptr_t src_size = src_type.SizeInBytes();
+  const intptr_t dst_size = dst_type.SizeInBytes();
+  const bool sign_or_zero_extend = dst_size > src_size;
+
+  if (source.IsRegisters()) {
+    const auto& src = source.AsRegisters();
+    ASSERT(src.num_regs() == 1);
+    const auto src_reg = src.reg_at(0);
+
+    if (destination.IsRegisters()) {
+      const auto& dst = destination.AsRegisters();
+      ASSERT(dst.num_regs() == 1);
+      const auto dst_reg = dst.reg_at(0);
+      if (!sign_or_zero_extend) {
+        // TODO(riscv): Unreachable? Calling convention always extends.
+        __ mv(dst_reg, src_reg);
+      } else {
+        switch (src_type.AsPrimitive().representation()) {
+          // Calling convention: scalars are extended according to the sign of
+          // their type to 32-bits, then sign-extended to XLEN bits.
+          case compiler::ffi::kInt8:
+            __ slli(dst_reg, src_reg, XLEN - 8);
+            __ srai(dst_reg, dst_reg, XLEN - 8);
+            return;
+          case compiler::ffi::kInt16:
+            __ slli(dst_reg, src_reg, XLEN - 16);
+            __ srai(dst_reg, dst_reg, XLEN - 16);
+            return;
+          case compiler::ffi::kUint8:
+            __ andi(dst_reg, src_reg, 0xFF);
+            return;
+          case compiler::ffi::kUint16:
+            __ slli(dst_reg, src_reg, 16);
+#if XLEN == 32
+            __ srli(dst_reg, dst_reg, 16);
+#else
+            __ srliw(dst_reg, dst_reg, 16);
+#endif
+            return;
+          default:
+            // 32 to 64 bit is covered in IL by Representation conversions.
+            UNIMPLEMENTED();
+        }
+      }
+
+    } else if (destination.IsFpuRegisters()) {
+      // Fpu Registers should only contain doubles and registers only ints.
+      UNIMPLEMENTED();
+
+    } else {
+      ASSERT(destination.IsStack());
+      const auto& dst = destination.AsStack();
+      ASSERT(!sign_or_zero_extend);
+      auto const op_size = BytesToOperandSize(dst_size);
+      __ StoreToOffset(src.reg_at(0), dst.base_register(),
+                       dst.offset_in_bytes(), op_size);
+    }
+  } else if (source.IsFpuRegisters()) {
+    const auto& src = source.AsFpuRegisters();
+    // We have not implemented conversions here, use IL convert instructions.
+    ASSERT(src_type.Equals(dst_type));
+
+    if (destination.IsRegisters()) {
+      // Fpu Registers should only contain doubles and registers only ints.
+      UNIMPLEMENTED();
+
+    } else if (destination.IsFpuRegisters()) {
+      const auto& dst = destination.AsFpuRegisters();
+      __ fmvd(dst.fpu_reg(), src.fpu_reg());
+
+    } else {
+      ASSERT(destination.IsStack());
+      ASSERT(src_type.IsFloat());
+      const auto& dst = destination.AsStack();
+      switch (dst_size) {
+        case 8:
+          __ StoreDToOffset(src.fpu_reg(), dst.base_register(),
+                            dst.offset_in_bytes());
+          return;
+        case 4:
+          __ StoreSToOffset(src.fpu_reg(), dst.base_register(),
+                            dst.offset_in_bytes());
+          return;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+  } else {
+    ASSERT(source.IsStack());
+    const auto& src = source.AsStack();
+    if (destination.IsRegisters()) {
+      const auto& dst = destination.AsRegisters();
+      ASSERT(dst.num_regs() == 1);
+      const auto dst_reg = dst.reg_at(0);
+      ASSERT(!sign_or_zero_extend);
+      __ LoadFromOffset(dst_reg, src.base_register(), src.offset_in_bytes(),
+                        BytesToOperandSize(dst_size));
+    } else if (destination.IsFpuRegisters()) {
+      ASSERT(src_type.Equals(dst_type));
+      ASSERT(src_type.IsFloat());
+      const auto& dst = destination.AsFpuRegisters();
+      switch (src_size) {
+        case 8:
+          __ LoadDFromOffset(dst.fpu_reg(), src.base_register(),
+                             src.offset_in_bytes());
+          return;
+        case 4:
+          __ LoadSFromOffset(dst.fpu_reg(), src.base_register(),
+                             src.offset_in_bytes());
+          return;
+        default:
+          UNIMPLEMENTED();
+      }
+
+    } else {
+      ASSERT(destination.IsStack());
+      UNREACHABLE();
+    }
+  }
+}
+
+void FlowGraphCompiler::LoadBSSEntry(BSS::Relocation relocation,
+                                     Register dst,
+                                     Register tmp) {
+  UNIMPLEMENTED();
+}
+
+#undef __
+#define __ compiler_->assembler()->
+
+void ParallelMoveResolver::EmitSwap(int index) {
+  MoveOperands* move = moves_[index];
+  const Location source = move->src();
+  const Location destination = move->dest();
+
+  if (source.IsRegister() && destination.IsRegister()) {
+    ASSERT(source.reg() != TMP);
+    ASSERT(destination.reg() != TMP);
+    __ mv(TMP, source.reg());
+    __ mv(source.reg(), destination.reg());
+    __ mv(destination.reg(), TMP);
+  } else if (source.IsRegister() && destination.IsStackSlot()) {
+    Exchange(source.reg(), destination.base_reg(),
+             destination.ToStackSlotOffset());
+  } else if (source.IsStackSlot() && destination.IsRegister()) {
+    Exchange(destination.reg(), source.base_reg(), source.ToStackSlotOffset());
+  } else if (source.IsStackSlot() && destination.IsStackSlot()) {
+    Exchange(source.base_reg(), source.ToStackSlotOffset(),
+             destination.base_reg(), destination.ToStackSlotOffset());
+  } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
+    const FRegister dst = destination.fpu_reg();
+    const FRegister src = source.fpu_reg();
+    __ fmvd(FTMP, src);
+    __ fmvd(src, dst);
+    __ fmvd(dst, FTMP);
+  } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
+    UNIMPLEMENTED();
+  } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
+    const intptr_t source_offset = source.ToStackSlotOffset();
+    const intptr_t dest_offset = destination.ToStackSlotOffset();
+
+    ScratchFpuRegisterScope ensure_scratch(this, kNoFpuRegister);
+    FRegister scratch = ensure_scratch.reg();
+    __ LoadDFromOffset(FTMP, source.base_reg(), source_offset);
+    __ LoadDFromOffset(scratch, destination.base_reg(), dest_offset);
+    __ StoreDToOffset(FTMP, destination.base_reg(), dest_offset);
+    __ StoreDToOffset(scratch, source.base_reg(), source_offset);
+  } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
+    UNIMPLEMENTED();
+  } else {
+    UNREACHABLE();
+  }
+
+  // The swap of source and destination has executed a move from source to
+  // destination.
+  move->Eliminate();
+
+  // Any unperformed (including pending) move with a source of either
+  // this move's source or destination needs to have their source
+  // changed to reflect the state of affairs after the swap.
+  for (int i = 0; i < moves_.length(); ++i) {
+    const MoveOperands& other_move = *moves_[i];
+    if (other_move.Blocks(source)) {
+      moves_[i]->set_src(destination);
+    } else if (other_move.Blocks(destination)) {
+      moves_[i]->set_src(source);
+    }
+  }
+}
+
+void ParallelMoveResolver::MoveMemoryToMemory(const compiler::Address& dst,
+                                              const compiler::Address& src) {
+  UNREACHABLE();
+}
+
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
+void ParallelMoveResolver::Exchange(Register reg,
+                                    const compiler::Address& mem) {
+  UNREACHABLE();
+}
+
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
+void ParallelMoveResolver::Exchange(const compiler::Address& mem1,
+                                    const compiler::Address& mem2) {
+  UNREACHABLE();
+}
+
+void ParallelMoveResolver::Exchange(Register reg,
+                                    Register base_reg,
+                                    intptr_t stack_offset) {
+  ScratchRegisterScope tmp(this, reg);
+  __ mv(tmp.reg(), reg);
+  __ LoadFromOffset(reg, base_reg, stack_offset);
+  __ StoreToOffset(tmp.reg(), base_reg, stack_offset);
+}
+
+void ParallelMoveResolver::Exchange(Register base_reg1,
+                                    intptr_t stack_offset1,
+                                    Register base_reg2,
+                                    intptr_t stack_offset2) {
+  ScratchRegisterScope tmp1(this, kNoRegister);
+  ScratchRegisterScope tmp2(this, tmp1.reg());
+  __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1);
+  __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2);
+  __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2);
+  __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1);
+}
+
+void ParallelMoveResolver::SpillScratch(Register reg) {
+  __ PushRegister(reg);
+}
+
+void ParallelMoveResolver::RestoreScratch(Register reg) {
+  __ PopRegister(reg);
+}
+
+void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
+  __ subi(SP, SP, sizeof(double));
+  __ fsd(reg, compiler::Address(SP, 0));
+}
+
+void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
+  __ fld(reg, compiler::Address(SP, 0));
+  __ addi(SP, SP, sizeof(double));
+}
+
+#undef __
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 91cc786..bed125b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -866,14 +866,7 @@
   } else {
     ASSERT(!source.IsInvalid());
     ASSERT(source.IsConstant());
-    if (destination.IsFpuRegister() || destination.IsDoubleStackSlot()) {
-      Register scratch = tmp->AllocateTemporary();
-      source.constant_instruction()->EmitMoveToLocation(this, destination,
-                                                        scratch);
-      tmp->ReleaseTemporary();
-    } else {
-      source.constant_instruction()->EmitMoveToLocation(this, destination);
-    }
+    source.constant_instruction()->EmitMoveToLocation(this, destination);
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 878bcec..0a52e22 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5676,7 +5676,7 @@
 
   if (is_smi.IsLinked()) {
     compiler::Label done;
-    __ Jump(&done);
+    __ Jump(&done, compiler::Assembler::kNearJump);
     __ Bind(&is_smi);
     EmitSmiConversion(compiler);
     __ Bind(&done);
@@ -5729,10 +5729,9 @@
       EmitLoadInt32FromBoxOrSmi(compiler);
     } else if (representation() == kUnboxedInt64 && value()->Type()->IsInt()) {
       EmitLoadInt64FromBoxOrSmi(compiler);
-    } else if (value_cid == box_cid) {
+    } else if ((value_cid == box_cid) || !CanDeoptimize()) {
       EmitLoadFromBox(compiler);
     } else {
-      ASSERT(CanDeoptimize());
       EmitLoadFromBoxWithDeopt(compiler);
     }
   }
@@ -6374,7 +6373,8 @@
   set_native_c_function(native_function);
 }
 
-#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64)
+#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64) &&                \
+    !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
 
 LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   UNREACHABLE();
@@ -6384,7 +6384,8 @@
   UNREACHABLE();
 }
 
-#endif  // !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64)
+#endif  // !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64) &&         \
+        // !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
 
 Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
   if (idx < TargetAddressIndex()) {
@@ -6504,7 +6505,10 @@
 
       ConstantTemporaryAllocator temp_alloc(temp);
       if (origin.IsConstant()) {
-        compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
+        // Can't occur because we currently don't inline FFI trampolines (see
+        // http://dartbug.com/45055), which means all incomming arguments
+        // originate from parameters and thus are non-constant.
+        UNREACHABLE();
       } else {
         compiler->EmitMoveToNative(def_target, origin, origin_rep, &temp_alloc);
       }
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index c261131..58b4a50 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -62,7 +62,6 @@
 class Range;
 class RangeAnalysis;
 class RangeBoundary;
-class SuccessorsIterable;
 class TypeUsageInfo;
 class UnboxIntegerInstr;
 
@@ -769,6 +768,64 @@
 typedef ZoneGrowableArray<Value*> InputsArray;
 typedef ZoneGrowableArray<PushArgumentInstr*> PushArgumentsArray;
 
+template <typename Trait>
+class InstructionIndexedPropertyIterable {
+ public:
+  struct Iterator {
+    const Instruction* instr;
+    intptr_t index;
+
+    decltype(Trait::At(instr, index)) operator*() const {
+      return Trait::At(instr, index);
+    }
+    Iterator& operator++() {
+      index++;
+      return *this;
+    }
+
+    bool operator==(const Iterator& other) {
+      return instr == other.instr && index == other.index;
+    }
+
+    bool operator!=(const Iterator& other) { return !(*this == other); }
+  };
+
+  explicit InstructionIndexedPropertyIterable(const Instruction* instr)
+      : instr_(instr) {}
+
+  Iterator begin() const { return {instr_, 0}; }
+  Iterator end() const { return {instr_, Trait::Length(instr_)}; }
+
+ private:
+  const Instruction* instr_;
+};
+
+class ValueListIterable {
+ public:
+  struct Iterator {
+    Value* value;
+
+    Value* operator*() const { return value; }
+
+    Iterator& operator++() {
+      value = value->next_use();
+      return *this;
+    }
+
+    bool operator==(const Iterator& other) { return value == other.value; }
+
+    bool operator!=(const Iterator& other) { return !(*this == other); }
+  };
+
+  explicit ValueListIterable(Value* value) : value_(value) {}
+
+  Iterator begin() const { return {value_}; }
+  Iterator end() const { return {nullptr}; }
+
+ private:
+  Value* value_;
+};
+
 class Instruction : public ZoneAllocated {
  public:
 #define DECLARE_TAG(type, attrs) k##type,
@@ -828,6 +885,20 @@
     RawSetInputAt(i, value);
   }
 
+  struct InputsTrait {
+    static Definition* At(const Instruction* instr, intptr_t index) {
+      return instr->InputAt(index)->definition();
+    }
+
+    static intptr_t Length(const Instruction* instr) {
+      return instr->InputCount();
+    }
+  };
+
+  using InputsIterable = InstructionIndexedPropertyIterable<InputsTrait>;
+
+  InputsIterable inputs() { return InputsIterable(this); }
+
   // Remove all inputs (including in the environment) from their
   // definition's use lists.
   void UnuseAllInputs();
@@ -917,7 +988,22 @@
   virtual intptr_t SuccessorCount() const;
   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
 
-  inline SuccessorsIterable successors() const;
+  struct SuccessorsTrait {
+    static BlockEntryInstr* At(const Instruction* instr, intptr_t index) {
+      return instr->SuccessorAt(index);
+    }
+
+    static intptr_t Length(const Instruction* instr) {
+      return instr->SuccessorCount();
+    }
+  };
+
+  using SuccessorsIterable =
+      InstructionIndexedPropertyIterable<SuccessorsTrait>;
+
+  inline SuccessorsIterable successors() const {
+    return SuccessorsIterable(this);
+  }
 
   void Goto(JoinEntryInstr* entry);
 
@@ -1136,12 +1222,11 @@
   void Unsupported(FlowGraphCompiler* compiler);
 
   static bool SlowPathSharingSupported(bool is_optimizing) {
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM) ||                    \
-    defined(TARGET_ARCH_ARM64)
+#if defined(TARGET_ARCH_IA32)
+    return false;
+#else
     return FLAG_enable_slow_path_sharing && FLAG_precompiled_mode &&
            is_optimizing;
-#else
-    return false;
 #endif
   }
 
@@ -2297,6 +2382,10 @@
   Value* env_use_list() const { return env_use_list_; }
   void set_env_use_list(Value* head) { env_use_list_ = head; }
 
+  ValueListIterable input_uses() const {
+    return ValueListIterable(input_use_list_);
+  }
+
   void AddInputUse(Value* value) { Value::AddToList(value, &input_use_list_); }
   void AddEnvUse(Value* value) { Value::AddToList(value, &env_use_list_); }
 
@@ -4384,9 +4473,13 @@
       const compiler::TableSelector* selector);
 
   DECLARE_INSTRUCTION(DispatchTableCall)
+  DECLARE_ATTRIBUTES(selector_name())
 
   const Function& interface_target() const { return interface_target_; }
   const compiler::TableSelector* selector() const { return selector_; }
+  const char* selector_name() const {
+    return String::Handle(interface_target().name()).ToCString();
+  }
 
   Value* class_id() const { return InputAt(InputCount() - 1); }
 
@@ -5224,6 +5317,8 @@
                        const Register temp0,
                        const Register temp1);
 
+  void EmitCall(FlowGraphCompiler* compiler, Register target);
+
   Zone* const zone_;
   const compiler::ffi::CallMarshaller& marshaller_;
 
@@ -7875,7 +7970,7 @@
   }
 
   static bool IsSupported(Token::Kind op_kind, Value* left, Value* right) {
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#if defined(TARGET_ARCH_IS_32_BIT)
     switch (op_kind) {
       case Token::kADD:
       case Token::kSUB:
@@ -9764,37 +9859,6 @@
   return (constant == nullptr) || constant->value().ptr() == value.ptr();
 }
 
-class SuccessorsIterable {
- public:
-  struct Iterator {
-    const Instruction* instr;
-    intptr_t index;
-
-    BlockEntryInstr* operator*() const { return instr->SuccessorAt(index); }
-    Iterator& operator++() {
-      index++;
-      return *this;
-    }
-
-    bool operator==(const Iterator& other) {
-      return instr == other.instr && index == other.index;
-    }
-
-    bool operator!=(const Iterator& other) { return !(*this == other); }
-  };
-
-  explicit SuccessorsIterable(const Instruction* instr) : instr_(instr) {}
-
-  Iterator begin() const { return {instr_, 0}; }
-  Iterator end() const { return {instr_, instr_->SuccessorCount()}; }
-
- private:
-  const Instruction* instr_;
-};
-
-SuccessorsIterable Instruction::successors() const {
-  return SuccessorsIterable(this);
-}
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 1c5673c..979c8ba 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -5286,10 +5286,16 @@
   __ CompareObjectRegisters(result_mod, ZR);
   __ b(&done, GE);
   // Result is negative, adjust it.
-  __ CompareObjectRegisters(right, ZR);
-  __ sub(TMP2, result_mod, compiler::Operand(right), compiler::kObjectBytes);
-  __ add(TMP, result_mod, compiler::Operand(right), compiler::kObjectBytes);
-  __ csel(result_mod, TMP, TMP2, GE);
+  if (RangeUtils::IsNegative(divisor_range())) {
+    __ sub(result_mod, result_mod, compiler::Operand(right));
+  } else if (RangeUtils::IsPositive(divisor_range())) {
+    __ add(result_mod, result_mod, compiler::Operand(right));
+  } else {
+    __ CompareObjectRegisters(right, ZR);
+    __ sub(TMP2, result_mod, compiler::Operand(right), compiler::kObjectBytes);
+    __ add(TMP, result_mod, compiler::Operand(right), compiler::kObjectBytes);
+    __ csel(result_mod, TMP, TMP2, GE);
+  }
   __ Bind(&done);
 }
 
@@ -5634,8 +5640,7 @@
 
   // Handle modulo/division by zero exception on slow path.
   if (slow_path->has_divide_by_zero()) {
-    __ CompareRegisters(right, ZR);
-    __ b(slow_path->entry_label(), EQ);
+    __ cbz(slow_path->entry_label(), right);
   }
 
   // Perform actual operation
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
new file mode 100644
index 0000000..244a95e
--- /dev/null
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -0,0 +1,7378 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/backend/il.h"
+
+#include "vm/compiler/backend/flow_graph.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/compiler/backend/locations_helpers.h"
+#include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/ffi/native_calling_convention.h"
+#include "vm/compiler/jit/compiler.h"
+#include "vm/dart_entry.h"
+#include "vm/instructions.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/simulator.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
+
+#define __ (compiler->assembler())->
+#define Z (compiler->zone())
+
+namespace dart {
+
+// Generic summary for call instructions that have all arguments pushed
+// on the stack and return the result in a fixed register A0 (or FA0 if
+// the return type is double).
+LocationSummary* Instruction::MakeCallSummary(Zone* zone,
+                                              const Instruction* instr,
+                                              LocationSummary* locs) {
+  ASSERT(locs == nullptr || locs->always_calls());
+  LocationSummary* result =
+      ((locs == nullptr)
+           ? (new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall))
+           : locs);
+  const auto representation = instr->representation();
+  switch (representation) {
+    case kTagged:
+      result->set_out(
+          0, Location::RegisterLocation(CallingConventions::kReturnReg));
+      break;
+    case kUnboxedInt64:
+#if XLEN == 32
+      result->set_out(
+          0, Location::Pair(
+                 Location::RegisterLocation(CallingConventions::kReturnReg),
+                 Location::RegisterLocation(
+                     CallingConventions::kSecondReturnReg)));
+#else
+      result->set_out(
+          0, Location::RegisterLocation(CallingConventions::kReturnReg));
+#endif
+      break;
+    case kUnboxedDouble:
+      result->set_out(
+          0, Location::FpuRegisterLocation(CallingConventions::kReturnFpuReg));
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return result;
+}
+
+LocationSummary* LoadIndexedUnsafeInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+
+  locs->set_in(0, Location::RequiresRegister());
+  switch (representation()) {
+    case kTagged:
+      locs->set_out(0, Location::RequiresRegister());
+      break;
+    case kUnboxedInt64:
+#if XLEN == 32
+      locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+#else
+      locs->set_out(0, Location::RequiresRegister());
+#endif
+      break;
+    case kUnboxedDouble:
+      locs->set_out(0, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return locs;
+}
+
+void LoadIndexedUnsafeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(RequiredInputRepresentation(0) == kTagged);  // It is a Smi.
+  ASSERT(kSmiTag == 0);
+  ASSERT(kSmiTagSize == 1);
+
+  const Register index = locs()->in(0).reg();
+
+  switch (representation()) {
+    case kTagged: {
+      const auto out = locs()->out(0).reg();
+      __ slli(TMP, index, kWordSizeLog2 - kSmiTagSize);
+      __ add(TMP, TMP, base_reg());
+      __ LoadFromOffset(out, TMP, offset());
+      break;
+    }
+    case kUnboxedInt64: {
+#if XLEN == 32
+      const auto out_lo = locs()->out(0).AsPairLocation()->At(0).reg();
+      const auto out_hi = locs()->out(0).AsPairLocation()->At(1).reg();
+      __ slli(TMP, index, kWordSizeLog2 - kSmiTagSize);
+      __ add(TMP, TMP, base_reg());
+      __ LoadFromOffset(out_lo, TMP, offset());
+      __ LoadFromOffset(out_hi, TMP, offset() + compiler::target::kWordSize);
+#else
+      const auto out = locs()->out(0).reg();
+      __ slli(TMP, index, kWordSizeLog2 - kSmiTagSize);
+      __ add(TMP, TMP, base_reg());
+      __ LoadFromOffset(out, TMP, offset());
+#endif
+      break;
+    }
+    case kUnboxedDouble: {
+      const auto out = locs()->out(0).fpu_reg();
+      const intptr_t kDoubleSizeLog2 = 3;
+      __ slli(TMP, index, kDoubleSizeLog2 - kSmiTagSize);
+      __ add(TMP, TMP, base_reg());
+      __ LoadDFromOffset(out, TMP, offset());
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+DEFINE_BACKEND(StoreIndexedUnsafe,
+               (NoLocation, Register index, Register value)) {
+  ASSERT(instr->RequiredInputRepresentation(
+             StoreIndexedUnsafeInstr::kIndexPos) == kTagged);  // It is a Smi.
+  __ slli(TMP, index, compiler::target::kWordSizeLog2 - kSmiTagSize);
+  __ add(TMP, TMP, instr->base_reg());
+  __ sx(value, compiler::Address(TMP, instr->offset()));
+
+  ASSERT(kSmiTag == 0);
+}
+
+DEFINE_BACKEND(TailCall,
+               (NoLocation,
+                Fixed<Register, ARGS_DESC_REG>,
+                Temp<Register> temp)) {
+  compiler->EmitTailCallToStub(instr->code());
+
+  // Even though the TailCallInstr will be the last instruction in a basic
+  // block, the flow graph compiler will emit native code for other blocks after
+  // the one containing this instruction and needs to be able to use the pool.
+  // (The `LeaveDartFrame` above disables usages of the pool.)
+  __ set_constant_pool_allowed(true);
+}
+
+LocationSummary* MemoryCopyInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  const intptr_t kNumInputs = 5;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(kSrcPos, Location::WritableRegister());
+  locs->set_in(kDestPos, Location::WritableRegister());
+  locs->set_in(kSrcStartPos, Location::RequiresRegister());
+  locs->set_in(kDestStartPos, Location::RequiresRegister());
+  locs->set_in(kLengthPos, Location::WritableRegister());
+  return locs;
+}
+
+void MemoryCopyInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register src_reg = locs()->in(kSrcPos).reg();
+  const Register dest_reg = locs()->in(kDestPos).reg();
+  const Register src_start_reg = locs()->in(kSrcStartPos).reg();
+  const Register dest_start_reg = locs()->in(kDestStartPos).reg();
+  const Register length_reg = locs()->in(kLengthPos).reg();
+
+  EmitComputeStartPointer(compiler, src_cid_, src_start(), src_reg,
+                          src_start_reg);
+  EmitComputeStartPointer(compiler, dest_cid_, dest_start(), dest_reg,
+                          dest_start_reg);
+
+  compiler::Label loop, done;
+
+  // Untag length and skip copy if length is zero.
+  __ SmiUntag(length_reg);
+  __ beqz(length_reg, &done);
+
+  __ Bind(&loop);
+  switch (element_size_) {
+    case 1:
+      __ lb(TMP, compiler::Address(src_reg));
+      __ addi(src_reg, src_reg, 1);
+      __ sb(TMP, compiler::Address(dest_reg));
+      __ addi(dest_reg, dest_reg, 1);
+      break;
+    case 2:
+      __ lh(TMP, compiler::Address(src_reg));
+      __ addi(src_reg, src_reg, 2);
+      __ sh(TMP, compiler::Address(dest_reg));
+      __ addi(dest_reg, dest_reg, 2);
+      break;
+    case 4:
+      __ lw(TMP, compiler::Address(src_reg));
+      __ addi(src_reg, src_reg, 4);
+      __ sw(TMP, compiler::Address(dest_reg));
+      __ addi(dest_reg, dest_reg, 4);
+      break;
+    case 8:
+#if XLEN == 32
+      __ lw(TMP, compiler::Address(src_reg, 0));
+      __ lw(TMP2, compiler::Address(src_reg, 4));
+      __ addi(src_reg, src_reg, 16);
+      __ sw(TMP, compiler::Address(dest_reg, 0));
+      __ sw(TMP2, compiler::Address(dest_reg, 4));
+      __ addi(dest_reg, dest_reg, 16);
+#else
+      __ ld(TMP, compiler::Address(src_reg));
+      __ addi(src_reg, src_reg, 8);
+      __ sd(TMP, compiler::Address(dest_reg));
+      __ addi(dest_reg, dest_reg, 8);
+#endif
+      break;
+    case 16:
+#if XLEN == 32
+      __ lw(TMP, compiler::Address(src_reg, 0));
+      __ lw(TMP2, compiler::Address(src_reg, 4));
+      __ sw(TMP, compiler::Address(dest_reg, 0));
+      __ sw(TMP2, compiler::Address(dest_reg, 4));
+      __ lw(TMP, compiler::Address(src_reg, 8));
+      __ lw(TMP2, compiler::Address(src_reg, 12));
+      __ addi(src_reg, src_reg, 16);
+      __ sw(TMP, compiler::Address(dest_reg, 8));
+      __ sw(TMP2, compiler::Address(dest_reg, 12));
+      __ addi(dest_reg, dest_reg, 16);
+#elif XLEN == 64
+      __ ld(TMP, compiler::Address(src_reg, 0));
+      __ ld(TMP2, compiler::Address(src_reg, 8));
+      __ addi(src_reg, src_reg, 16);
+      __ sd(TMP, compiler::Address(dest_reg, 0));
+      __ sd(TMP2, compiler::Address(dest_reg, 8));
+      __ addi(dest_reg, dest_reg, 16);
+#elif XLEN == 128
+      __ lq(TMP, compiler::Address(src_reg));
+      __ addi(src_reg, src_reg, 16);
+      __ sq(TMP, compiler::Address(dest_reg));
+      __ addi(dest_reg, dest_reg, 16);
+#endif
+      break;
+  }
+  __ subi(length_reg, length_reg, 1);
+  __ bnez(length_reg, &loop);
+  __ Bind(&done);
+}
+
+void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler* compiler,
+                                              classid_t array_cid,
+                                              Value* start,
+                                              Register array_reg,
+                                              Register start_reg) {
+  if (IsTypedDataBaseClassId(array_cid)) {
+    __ lx(array_reg,
+          compiler::FieldAddress(
+              array_reg, compiler::target::TypedDataBase::data_field_offset()));
+  } else {
+    switch (array_cid) {
+      case kOneByteStringCid:
+        __ addi(
+            array_reg, array_reg,
+            compiler::target::OneByteString::data_offset() - kHeapObjectTag);
+        break;
+      case kTwoByteStringCid:
+        __ addi(
+            array_reg, array_reg,
+            compiler::target::OneByteString::data_offset() - kHeapObjectTag);
+        break;
+      case kExternalOneByteStringCid:
+        __ lx(array_reg,
+              compiler::FieldAddress(array_reg,
+                                     compiler::target::ExternalOneByteString::
+                                         external_data_offset()));
+        break;
+      case kExternalTwoByteStringCid:
+        __ lx(array_reg,
+              compiler::FieldAddress(array_reg,
+                                     compiler::target::ExternalTwoByteString::
+                                         external_data_offset()));
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+  intptr_t shift = Utils::ShiftForPowerOfTwo(element_size_) - 1;
+  if (shift < 0) {
+    __ srai(TMP, start_reg, -shift);
+    __ add(array_reg, array_reg, TMP);
+  } else if (shift == 0) {
+    __ add(array_reg, array_reg, start_reg);
+  } else {
+    __ slli(TMP, start_reg, shift);
+    __ add(array_reg, array_reg, TMP);
+  }
+}
+
+LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  if (representation() == kUnboxedDouble) {
+    locs->set_in(0, Location::RequiresFpuRegister());
+  } else if (representation() == kUnboxedInt64) {
+#if XLEN == 32
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+#else
+    locs->set_in(0, Location::RequiresRegister());
+#endif
+  } else {
+    locs->set_in(0, LocationAnyOrConstant(value()));
+  }
+  return locs;
+}
+
+void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
+  // where arguments are pushed by their definitions.
+  if (compiler->is_optimizing()) {
+    if (previous()->IsPushArgument()) {
+      // Already generated.
+      return;
+    }
+
+    // Count the arguments first so we can update SP once instead of using
+    // separate pushes.
+    intptr_t size = 0;
+    for (PushArgumentInstr* push_arg = this; push_arg != nullptr;
+         push_arg = push_arg->next()->AsPushArgument()) {
+      const Location value = push_arg->locs()->in(0);
+      if (value.IsRegister()) {
+        size += compiler::target::kWordSize;
+#if XLEN == 32
+      } else if (value.IsPairLocation()) {
+        size += 2 * compiler::target::kWordSize;
+#endif
+      } else if (value.IsConstant()) {
+        size += compiler::target::kWordSize;
+      } else if (value.IsFpuRegister()) {
+        size += sizeof(double);
+      } else if (value.IsStackSlot()) {
+        size += compiler::target::kWordSize;
+      } else {
+        UNREACHABLE();
+      }
+    }
+    __ subi(SP, SP, size);
+
+    intptr_t offset = size;
+    for (PushArgumentInstr* push_arg = this; push_arg != nullptr;
+         push_arg = push_arg->next()->AsPushArgument()) {
+      const Location value = push_arg->locs()->in(0);
+      if (value.IsRegister()) {
+        offset -= compiler::target::kWordSize;
+        __ StoreToOffset(value.reg(), SP, offset);
+#if XLEN == 32
+      } else if (value.IsPairLocation()) {
+        offset -= compiler::target::kWordSize;
+        __ StoreToOffset(value.AsPairLocation()->At(1).reg(), SP, offset);
+        offset -= compiler::target::kWordSize;
+        __ StoreToOffset(value.AsPairLocation()->At(0).reg(), SP, offset);
+#endif
+      } else if (value.IsConstant()) {
+        const Object& constant = value.constant();
+        Register reg;
+        if (constant.IsNull()) {
+          reg = NULL_REG;
+        } else if (constant.IsSmi() && Smi::Cast(constant).Value() == 0) {
+          reg = ZR;
+        } else {
+          reg = TMP;
+          __ LoadObject(TMP, constant);
+        }
+        offset -= compiler::target::kWordSize;
+        __ StoreToOffset(reg, SP, offset);
+      } else if (value.IsFpuRegister()) {
+        offset -= sizeof(double);
+        __ StoreDToOffset(value.fpu_reg(), SP, offset);
+      } else if (value.IsStackSlot()) {
+        const intptr_t value_offset = value.ToStackSlotOffset();
+        __ LoadFromOffset(TMP, value.base_reg(), value_offset);
+        offset -= compiler::target::kWordSize;
+        __ StoreToOffset(TMP, SP, offset);
+      } else {
+        UNREACHABLE();
+      }
+    }
+    ASSERT(offset == 0);
+  }
+}
+
+LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  switch (representation()) {
+    case kTagged:
+      locs->set_in(0,
+                   Location::RegisterLocation(CallingConventions::kReturnReg));
+      break;
+    case kUnboxedInt64:
+#if XLEN == 32
+      locs->set_in(
+          0, Location::Pair(
+                 Location::RegisterLocation(CallingConventions::kReturnReg),
+                 Location::RegisterLocation(
+                     CallingConventions::kSecondReturnReg)));
+#else
+      locs->set_in(0,
+                   Location::RegisterLocation(CallingConventions::kReturnReg));
+#endif
+      break;
+    case kUnboxedDouble:
+      locs->set_in(
+          0, Location::FpuRegisterLocation(CallingConventions::kReturnFpuReg));
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return locs;
+}
+
+// Attempt optimized compilation at return instruction instead of at the entry.
+// The entry needs to be patchable, no inlined objects are allowed in the area
+// that will be overwritten by the patch instructions: a branch macro sequence.
+void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (locs()->in(0).IsRegister()) {
+    const Register result = locs()->in(0).reg();
+    ASSERT(result == CallingConventions::kReturnReg);
+  } else if (locs()->in(0).IsPairLocation()) {
+    const Register result_lo = locs()->in(0).AsPairLocation()->At(0).reg();
+    const Register result_hi = locs()->in(0).AsPairLocation()->At(1).reg();
+    ASSERT(result_lo == CallingConventions::kReturnReg);
+    ASSERT(result_hi == CallingConventions::kSecondReturnReg);
+  } else {
+    ASSERT(locs()->in(0).IsFpuRegister());
+    const FpuRegister result = locs()->in(0).fpu_reg();
+    ASSERT(result == CallingConventions::kReturnFpuReg);
+  }
+
+  if (!compiler->flow_graph().graph_entry()->NeedsFrame()) {
+    __ ret();
+    return;
+  }
+
+#if defined(DEBUG)
+  compiler::Label stack_ok;
+  __ Comment("Stack Check");
+  const intptr_t fp_sp_dist =
+      (compiler::target::frame_layout.first_local_from_fp + 1 -
+       compiler->StackSize()) *
+      kWordSize;
+  ASSERT(fp_sp_dist <= 0);
+  __ sub(TMP, SP, FP);
+  __ CompareImmediate(TMP, fp_sp_dist);
+  __ BranchIf(EQ, &stack_ok, compiler::Assembler::kNearJump);
+  __ ebreak();
+  __ Bind(&stack_ok);
+#endif
+  ASSERT(__ constant_pool_allowed());
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
+    compiler->EmitYieldPositionMetadata(source(), yield_index());
+  }
+  __ LeaveDartFrame();  // Disallows constant pool use.
+  __ ret();
+  // This ReturnInstr may be emitted out of order by the optimizer. The next
+  // block may be a target expecting a properly set constant pool pointer.
+  __ set_constant_pool_allowed(true);
+}
+
+// Detect pattern when one value is zero and another is a power of 2.
+static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
+  return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
+         (Utils::IsPowerOfTwo(v2) && (v1 == 0));
+}
+
+LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  comparison()->InitializeLocationSummary(zone, opt);
+  return comparison()->locs();
+}
+
+void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register result = locs()->out(0).reg();
+
+  Location left = locs()->in(0);
+  Location right = locs()->in(1);
+  ASSERT(!left.IsConstant() || !right.IsConstant());
+
+  // Emit comparison code. This must not overwrite the result register.
+  // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
+  // the labels or returning an invalid condition.
+  BranchLabels labels = {NULL, NULL, NULL};
+  Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
+  ASSERT(true_condition != kInvalidCondition);
+
+  const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
+
+  intptr_t true_value = if_true_;
+  intptr_t false_value = if_false_;
+
+  if (is_power_of_two_kind) {
+    if (true_value == 0) {
+      // We need to have zero in result on true_condition.
+      true_condition = InvertCondition(true_condition);
+    }
+  } else {
+    if (true_value == 0) {
+      // Swap values so that false_value is zero.
+      intptr_t temp = true_value;
+      true_value = false_value;
+      false_value = temp;
+    } else {
+      true_condition = InvertCondition(true_condition);
+    }
+  }
+
+  __ SetIf(true_condition, result);
+
+  if (is_power_of_two_kind) {
+    const intptr_t shift =
+        Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
+    __ slli(result, result, shift + kSmiTagSize);
+  } else {
+    __ subi(result, result, 1);
+    const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value);
+    __ AndImmediate(result, result, val);
+    if (false_value != 0) {
+      __ AddImmediate(result, Smi::RawValue(false_value));
+    }
+  }
+}
+
+LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(T0));  // Function.
+  return MakeCallSummary(zone, this, summary);
+}
+
+void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Load arguments descriptor in S4.
+  const intptr_t argument_count = ArgumentCount();  // Includes type args.
+  const Array& arguments_descriptor =
+      Array::ZoneHandle(Z, GetArgumentsDescriptor());
+  __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
+
+  ASSERT(locs()->in(0).reg() == T0);
+  if (FLAG_precompiled_mode) {
+    // T0: Closure with a cached entry point.
+    __ LoadFieldFromOffset(A1, T0,
+                           compiler::target::Closure::entry_point_offset());
+  } else {
+    // T0: Function.
+    __ LoadCompressedFieldFromOffset(CODE_REG, T0,
+                                     compiler::target::Function::code_offset());
+    // Closure functions only have one entry point.
+    __ LoadFieldFromOffset(A1, T0,
+                           compiler::target::Function::entry_point_offset());
+  }
+
+  // T0: Function (argument to lazy compile stub)
+  // S4: Arguments descriptor array.
+  // A1: instructions entry point.
+  if (!FLAG_precompiled_mode) {
+    // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
+    __ LoadImmediate(IC_DATA_REG, 0);
+  }
+  __ jalr(A1);
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::kOther, locs(), env());
+  __ Drop(argument_count);
+}
+
+LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  return LocationSummary::Make(zone, 0, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register result = locs()->out(0).reg();
+  __ LoadFromOffset(result, FP,
+                    compiler::target::FrameOffsetInBytesForVariable(&local()));
+  // TODO(riscv): Using an SP-relative address instead of an FP-relative
+  // address would allow for compressed instructions.
+}
+
+LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
+                               LocationSummary::kNoCall);
+}
+
+void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  ASSERT(result == value);  // Assert that register assignment is correct.
+  __ StoreToOffset(value, FP,
+                   compiler::target::FrameOffsetInBytesForVariable(&local()));
+  // TODO(riscv): Using an SP-relative address instead of an FP-relative
+  // address would allow for compressed instructions.
+}
+
+LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
+                                                    bool opt) const {
+  return LocationSummary::Make(zone, 0, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // The register allocator drops constant definitions that have no uses.
+  if (!locs()->out(0).IsInvalid()) {
+    const Register result = locs()->out(0).reg();
+    __ LoadObject(result, value());
+  }
+}
+
+void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
+                                       const Location& destination,
+                                       Register tmp,
+                                       intptr_t pair_index) {
+  if (destination.IsRegister()) {
+    if (RepresentationUtils::IsUnboxedInteger(representation())) {
+      int64_t v;
+      const bool ok = compiler::HasIntegerValue(value_, &v);
+      RELEASE_ASSERT(ok);
+      if (value_.IsSmi() && RepresentationUtils::IsUnsigned(representation())) {
+        // If the value is negative, then the sign bit was preserved during
+        // Smi untagging, which means the resulting value may be unexpected.
+        ASSERT(v >= 0);
+      }
+#if XLEN == 32
+      __ LoadImmediate(destination.reg(), pair_index == 0
+                                              ? Utils::Low32Bits(v)
+                                              : Utils::High32Bits(v));
+#else
+      ASSERT(pair_index == 0);  // No pair representation needed on 64-bit.
+      __ LoadImmediate(destination.reg(), v);
+#endif
+    } else {
+      ASSERT(representation() == kTagged);
+      __ LoadObject(destination.reg(), value_);
+    }
+  } else if (destination.IsFpuRegister()) {
+    const FRegister dst = destination.fpu_reg();
+    __ LoadDImmediate(dst, Double::Cast(value_).value());
+  } else if (destination.IsDoubleStackSlot()) {
+    __ LoadDImmediate(FTMP, Double::Cast(value_).value());
+    const intptr_t dest_offset = destination.ToStackSlotOffset();
+    __ StoreDToOffset(FTMP, destination.base_reg(), dest_offset);
+  } else {
+    ASSERT(destination.IsStackSlot());
+    ASSERT(tmp != kNoRegister);
+    const intptr_t dest_offset = destination.ToStackSlotOffset();
+    if (RepresentationUtils::IsUnboxedInteger(representation())) {
+      int64_t v;
+      const bool ok = compiler::HasIntegerValue(value_, &v);
+      RELEASE_ASSERT(ok);
+#if XLEN == 32
+      __ LoadImmediate(
+          tmp, pair_index == 0 ? Utils::Low32Bits(v) : Utils::High32Bits(v));
+#else
+      ASSERT(pair_index == 0);  // No pair representation needed on 64-bit.
+      __ LoadImmediate(tmp, v);
+#endif
+    } else {
+      ASSERT(representation() == kTagged);
+      if (value_.IsNull()) {
+        tmp = NULL_REG;
+      } else if (value_.IsSmi() && Smi::Cast(value_).Value() == 0) {
+        tmp = ZR;
+      } else {
+        __ LoadObject(tmp, value_);
+      }
+    }
+    __ StoreToOffset(tmp, destination.base_reg(), dest_offset);
+  }
+}
+
+LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const bool is_unboxed_int =
+      RepresentationUtils::IsUnboxedInteger(representation());
+  ASSERT(!is_unboxed_int || RepresentationUtils::ValueSize(representation()) <=
+                                compiler::target::kWordSize);
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = is_unboxed_int ? 0 : 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  if (is_unboxed_int) {
+    locs->set_out(0, Location::RequiresRegister());
+  } else {
+    switch (representation()) {
+      case kUnboxedDouble:
+        locs->set_out(0, Location::RequiresFpuRegister());
+        locs->set_temp(0, Location::RequiresRegister());
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+  return locs;
+}
+
+void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (!locs()->out(0).IsInvalid()) {
+    const Register scratch =
+        RepresentationUtils::IsUnboxedInteger(representation())
+            ? kNoRegister
+            : locs()->temp(0).reg();
+    EmitMoveToLocation(compiler, locs()->out(0), scratch);
+  }
+}
+
+LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
+                                                            bool opt) const {
+  auto const dst_type_loc =
+      LocationFixedRegisterOrConstant(dst_type(), TypeTestABI::kDstTypeReg);
+
+  // We want to prevent spilling of the inputs (e.g. function/instantiator tav),
+  // since TTS preserves them. So we make this a `kNoCall` summary,
+  // even though most other registers can be modified by the stub. To tell the
+  // register allocator about it, we reserve all the other registers as
+  // temporary registers.
+  // TODO(http://dartbug.com/32788): Simplify this.
+
+  const intptr_t kNonChangeableInputRegs =
+      (1 << TypeTestABI::kInstanceReg) |
+      ((dst_type_loc.IsRegister() ? 1 : 0) << TypeTestABI::kDstTypeReg) |
+      (1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+      (1 << TypeTestABI::kFunctionTypeArgumentsReg);
+
+  const intptr_t kNumInputs = 4;
+
+  // We invoke a stub that can potentially clobber any CPU register
+  // but can only clobber FPU registers on the slow path when
+  // entering runtime. ARM64 ABI only guarantees that lower
+  // 64-bits of an V registers are preserved so we block all
+  // of them except for FpuTMP.
+  const intptr_t kCpuRegistersToPreserve =
+      kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
+  const intptr_t kFpuRegistersToPreserve =
+      Utils::NBitMask<intptr_t>(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
+
+  const intptr_t kNumTemps = (Utils::CountOneBits32(kCpuRegistersToPreserve) +
+                              Utils::CountOneBits32(kFpuRegistersToPreserve));
+
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallCalleeSafe);
+  summary->set_in(kInstancePos,
+                  Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(kDstTypePos, dst_type_loc);
+  summary->set_in(
+      kInstantiatorTAVPos,
+      Location::RegisterLocation(TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(kFunctionTAVPos, Location::RegisterLocation(
+                                       TypeTestABI::kFunctionTypeArgumentsReg));
+  summary->set_out(0, Location::SameAsFirstInput());
+
+  // Let's reserve all registers except for the input ones.
+  intptr_t next_temp = 0;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    const bool should_preserve = ((1 << i) & kCpuRegistersToPreserve) != 0;
+    if (should_preserve) {
+      summary->set_temp(next_temp++,
+                        Location::RegisterLocation(static_cast<Register>(i)));
+    }
+  }
+
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    const bool should_preserve = ((1l << i) & kFpuRegistersToPreserve) != 0;
+    if (should_preserve) {
+      summary->set_temp(next_temp++, Location::FpuRegisterLocation(
+                                         static_cast<FpuRegister>(i)));
+    }
+  }
+
+  return summary;
+}
+
+void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(locs()->always_calls());
+
+  auto object_store = compiler->isolate_group()->object_store();
+  const auto& assert_boolean_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
+
+  compiler::Label done;
+  __ andi(TMP, AssertBooleanABI::kObjectReg, 1 << kBoolVsNullBitPosition);
+  __ bnez(TMP, &done, compiler::Assembler::kNearJump);
+  compiler->GenerateStubCall(source(), assert_boolean_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
+                             deopt_id(), env());
+  __ Bind(&done);
+}
+
+static Condition TokenKindToIntCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ:
+      return EQ;
+    case Token::kNE:
+      return NE;
+    case Token::kLT:
+      return LT;
+    case Token::kGT:
+      return GT;
+    case Token::kLTE:
+      return LE;
+    case Token::kGTE:
+      return GE;
+    default:
+      UNREACHABLE();
+      return VS;
+  }
+}
+
+static Condition FlipCondition(Condition condition) {
+  switch (condition) {
+    case EQ:
+      return EQ;
+    case NE:
+      return NE;
+    case LT:
+      return GT;
+    case LE:
+      return GE;
+    case GT:
+      return LT;
+    case GE:
+      return LE;
+    case CC:
+      return HI;
+    case LS:
+      return CS;
+    case HI:
+      return CC;
+    case CS:
+      return LS;
+    default:
+      UNREACHABLE();
+      return EQ;
+  }
+}
+
+static void EmitBranchOnCondition(
+    FlowGraphCompiler* compiler,
+    Condition true_condition,
+    BranchLabels labels,
+    compiler::Assembler::JumpDistance jump_distance =
+        compiler::Assembler::kFarJump) {
+  if (labels.fall_through == labels.false_label) {
+    // If the next block is the false successor we will fall through to it.
+    __ BranchIf(true_condition, labels.true_label, jump_distance);
+  } else {
+    // If the next block is not the false successor we will branch to it.
+    Condition false_condition = InvertCondition(true_condition);
+    __ BranchIf(false_condition, labels.false_label, jump_distance);
+
+    // Fall through or jump to the true successor.
+    if (labels.fall_through != labels.true_label) {
+      __ j(labels.true_label, jump_distance);
+    }
+  }
+}
+
+static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
+                                     LocationSummary* locs,
+                                     Token::Kind kind,
+                                     BranchLabels labels) {
+  Location left = locs->in(0);
+  Location right = locs->in(1);
+  ASSERT(!left.IsConstant() || !right.IsConstant());
+
+  Condition true_condition = TokenKindToIntCondition(kind);
+  if (left.IsConstant() || right.IsConstant()) {
+    // Ensure constant is on the right.
+    if (left.IsConstant()) {
+      Location tmp = right;
+      right = left;
+      left = tmp;
+      true_condition = FlipCondition(true_condition);
+    }
+    __ CompareObject(left.reg(), right.constant());
+  } else {
+    __ CompareObjectRegisters(left.reg(), right.reg());
+  }
+  return true_condition;
+}
+
+#if XLEN == 32
+static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
+                                           LocationSummary* locs,
+                                           Token::Kind kind) {
+  ASSERT(Token::IsEqualityOperator(kind));
+  PairLocation* left_pair = locs->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* right_pair = locs->in(1).AsPairLocation();
+  Register right_lo = right_pair->At(0).reg();
+  Register right_hi = right_pair->At(1).reg();
+
+  __ xor_(TMP, left_lo, right_lo);
+  __ xor_(TMP2, left_hi, right_hi);
+  __ or_(TMP, TMP, TMP2);
+  __ CompareImmediate(TMP, 0);
+  if (kind == Token::kEQ) {
+    return EQUAL;
+  } else if (kind == Token::kNE) {
+    return NOT_EQUAL;
+  }
+  UNREACHABLE();
+}
+
+static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
+                                             LocationSummary* locs,
+                                             Token::Kind kind,
+                                             BranchLabels labels) {
+  PairLocation* left_pair = locs->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* right_pair = locs->in(1).AsPairLocation();
+  Register right_lo = right_pair->At(0).reg();
+  Register right_hi = right_pair->At(1).reg();
+
+  switch (kind) {
+    case Token::kEQ:
+      __ bne(left_lo, right_lo, labels.false_label);
+      __ CompareRegisters(left_hi, right_hi);
+      return EQUAL;
+    case Token::kNE:
+      __ bne(left_lo, right_lo, labels.true_label);
+      __ CompareRegisters(left_hi, right_hi);
+      return NOT_EQUAL;
+    case Token::kLT:
+      __ blt(left_hi, right_hi, labels.true_label);
+      __ bgt(left_hi, right_hi, labels.false_label);
+      __ CompareRegisters(left_lo, right_lo);
+      return UNSIGNED_LESS;
+    case Token::kGT:
+      __ bgt(left_hi, right_hi, labels.true_label);
+      __ blt(left_hi, right_hi, labels.false_label);
+      __ CompareRegisters(left_lo, right_lo);
+      return UNSIGNED_GREATER;
+    case Token::kLTE:
+      __ blt(left_hi, right_hi, labels.true_label);
+      __ bgt(left_hi, right_hi, labels.false_label);
+      __ CompareRegisters(left_lo, right_lo);
+      return UNSIGNED_LESS_EQUAL;
+    case Token::kGTE:
+      __ bgt(left_hi, right_hi, labels.true_label);
+      __ blt(left_hi, right_hi, labels.false_label);
+      __ CompareRegisters(left_lo, right_lo);
+      return UNSIGNED_GREATER_EQUAL;
+    default:
+      UNREACHABLE();
+  }
+}
+#else
+// Similar to ComparisonInstr::EmitComparisonCode, may either:
+//   - emit comparison code and return a valid condition in which case the
+//     caller is expected to emit a branch to the true label based on that
+//     condition (or a branch to the false label on the opposite condition).
+//   - emit comparison code with a branch directly to the labels and return
+//     kInvalidCondition.
+static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler,
+                                       LocationSummary* locs,
+                                       Token::Kind kind,
+                                       BranchLabels labels) {
+  Location left = locs->in(0);
+  Location right = locs->in(1);
+  ASSERT(!left.IsConstant() || !right.IsConstant());
+
+  Condition true_condition = TokenKindToIntCondition(kind);
+  if (left.IsConstant() || right.IsConstant()) {
+    // Ensure constant is on the right.
+    ConstantInstr* constant = nullptr;
+    if (left.IsConstant()) {
+      constant = left.constant_instruction();
+      Location tmp = right;
+      right = left;
+      left = tmp;
+      true_condition = FlipCondition(true_condition);
+    } else {
+      constant = right.constant_instruction();
+    }
+
+    if (RepresentationUtils::IsUnboxedInteger(constant->representation())) {
+      int64_t value;
+      const bool ok = compiler::HasIntegerValue(constant->value(), &value);
+      RELEASE_ASSERT(ok);
+      __ CompareImmediate(left.reg(), value);
+    } else {
+      UNREACHABLE();
+    }
+  } else {
+    __ CompareRegisters(left.reg(), right.reg());
+  }
+  return true_condition;
+}
+#endif
+
+static Condition EmitNullAwareInt64ComparisonOp(FlowGraphCompiler* compiler,
+                                                LocationSummary* locs,
+                                                Token::Kind kind,
+                                                BranchLabels labels) {
+  ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
+  const Register left = locs->in(0).reg();
+  const Register right = locs->in(1).reg();
+  const Condition true_condition = TokenKindToIntCondition(kind);
+  compiler::Label* equal_result =
+      (true_condition == EQ) ? labels.true_label : labels.false_label;
+  compiler::Label* not_equal_result =
+      (true_condition == EQ) ? labels.false_label : labels.true_label;
+
+  // Check if operands have the same value. If they don't, then they could
+  // be equal only if both of them are Mints with the same value.
+  __ CompareObjectRegisters(left, right);
+  __ BranchIf(EQ, equal_result);
+  __ and_(TMP, left, right);
+  __ BranchIfSmi(TMP, not_equal_result);
+  __ CompareClassId(left, kMintCid, TMP);
+  __ BranchIf(NE, not_equal_result);
+  __ CompareClassId(right, kMintCid, TMP);
+  __ BranchIf(NE, not_equal_result);
+#if XLEN == 32
+  __ LoadFieldFromOffset(TMP, left, compiler::target::Mint::value_offset());
+  __ LoadFieldFromOffset(TMP2, right, compiler::target::Mint::value_offset());
+  __ bne(TMP, TMP2, not_equal_result);
+  __ LoadFieldFromOffset(
+      TMP, left,
+      compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+  __ LoadFieldFromOffset(
+      TMP2, right,
+      compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+#else
+  __ LoadFieldFromOffset(TMP, left, Mint::value_offset());
+  __ LoadFieldFromOffset(TMP2, right, Mint::value_offset());
+#endif
+  __ CompareRegisters(TMP, TMP2);
+  return true_condition;
+}
+
+LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  if (is_null_aware()) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::RequiresRegister());
+    locs->set_in(1, Location::RequiresRegister());
+    locs->set_out(0, Location::RequiresRegister());
+    return locs;
+  }
+#if XLEN == 32
+  if (operation_cid() == kMintCid) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_out(0, Location::RequiresRegister());
+    return locs;
+  }
+#endif
+  if (operation_cid() == kDoubleCid) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::RequiresFpuRegister());
+    locs->set_in(1, Location::RequiresFpuRegister());
+    locs->set_out(0, Location::RequiresRegister());
+    return locs;
+  }
+  if (operation_cid() == kSmiCid || operation_cid() == kMintCid) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    if (is_null_aware()) {
+      locs->set_in(0, Location::RequiresRegister());
+      locs->set_in(1, Location::RequiresRegister());
+    } else {
+      locs->set_in(0, LocationRegisterOrConstant(left()));
+      // Only one input can be a constant operand. The case of two constant
+      // operands should be handled by constant propagation.
+      // Only right can be a stack slot.
+      locs->set_in(1, locs->in(0).IsConstant()
+                          ? Location::RequiresRegister()
+                          : LocationRegisterOrConstant(right()));
+    }
+    locs->set_out(0, Location::RequiresRegister());
+    return locs;
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+                                        LocationSummary* locs,
+                                        BranchLabels labels,
+                                        Token::Kind kind) {
+  const FRegister left = locs->in(0).fpu_reg();
+  const FRegister right = locs->in(1).fpu_reg();
+
+  // TODO(riscv): Check if this does want we want for comparisons involving NaN.
+  switch (kind) {
+    case Token::kEQ:
+      __ feqd(TMP, left, right);
+      __ CompareImmediate(TMP, 0);
+      return NE;
+    case Token::kNE:
+      __ feqd(TMP, left, right);
+      __ CompareImmediate(TMP, 0);
+      return EQ;
+    case Token::kLT:
+      __ fltd(TMP, left, right);
+      __ CompareImmediate(TMP, 0);
+      return NE;
+    case Token::kGT:
+      __ fltd(TMP, right, left);
+      __ CompareImmediate(TMP, 0);
+      return NE;
+    case Token::kLTE:
+      __ fled(TMP, left, right);
+      __ CompareImmediate(TMP, 0);
+      return NE;
+    case Token::kGTE:
+      __ fled(TMP, right, left);
+      __ CompareImmediate(TMP, 0);
+      return NE;
+    default:
+      UNREACHABLE();
+  }
+}
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                   BranchLabels labels) {
+  if (is_null_aware()) {
+    ASSERT(operation_cid() == kMintCid);
+    return EmitNullAwareInt64ComparisonOp(compiler, locs(), kind(), labels);
+  }
+  if (operation_cid() == kSmiCid) {
+    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
+  } else if (operation_cid() == kMintCid) {
+#if XLEN == 32
+    return EmitUnboxedMintEqualityOp(compiler, locs(), kind());
+#else
+    return EmitInt64ComparisonOp(compiler, locs(), kind(), labels);
+#endif
+  } else {
+    ASSERT(operation_cid() == kDoubleCid);
+    return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
+  }
+}
+
+LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  // Only one input can be a constant operand. The case of two constant
+  // operands should be handled by constant propagation.
+  locs->set_in(1, LocationRegisterOrConstant(right()));
+  return locs;
+}
+
+Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                           BranchLabels labels) {
+  const Register left = locs()->in(0).reg();
+  Location right = locs()->in(1);
+  if (right.IsConstant()) {
+    ASSERT(right.constant().IsSmi());
+    const intx_t imm = static_cast<intx_t>(right.constant().ptr());
+    __ TestImmediate(left, imm);
+  } else {
+    __ TestRegisters(left, right.reg());
+  }
+  Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
+  return true_condition;
+}
+
+LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
+                                                    bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  locs->set_temp(0, Location::RequiresRegister());
+  locs->set_out(0, Location::RequiresRegister());
+  return locs;
+}
+
+Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                            BranchLabels labels) {
+  ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
+  const Register val_reg = locs()->in(0).reg();
+  const Register cid_reg = locs()->temp(0).reg();
+
+  compiler::Label* deopt =
+      CanDeoptimize()
+          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids,
+                                   licm_hoisted_ ? ICData::kHoisted : 0)
+          : NULL;
+
+  const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
+  const ZoneGrowableArray<intptr_t>& data = cid_results();
+  ASSERT(data[0] == kSmiCid);
+  bool result = data[1] == true_result;
+  __ BranchIfSmi(val_reg, result ? labels.true_label : labels.false_label);
+  __ LoadClassId(cid_reg, val_reg);
+
+  for (intptr_t i = 2; i < data.length(); i += 2) {
+    const intptr_t test_cid = data[i];
+    ASSERT(test_cid != kSmiCid);
+    result = data[i + 1] == true_result;
+    __ CompareImmediate(cid_reg, test_cid);
+    __ BranchIf(EQ, result ? labels.true_label : labels.false_label);
+  }
+  // No match found, deoptimize or default action.
+  if (deopt == NULL) {
+    // If the cid is not in the list, jump to the opposite label from the cids
+    // that are in the list.  These must be all the same (see asserts in the
+    // constructor).
+    compiler::Label* target = result ? labels.false_label : labels.true_label;
+    if (target != labels.fall_through) {
+      __ j(target);
+    }
+  } else {
+    __ j(deopt);
+  }
+  // Dummy result as this method already did the jump, there's no need
+  // for the caller to branch on a condition.
+  return kInvalidCondition;
+}
+
+LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+#if XLEN == 32
+  if (operation_cid() == kMintCid) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_out(0, Location::RequiresRegister());
+    return locs;
+  }
+#endif
+  if (operation_cid() == kDoubleCid) {
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresFpuRegister());
+    summary->set_in(1, Location::RequiresFpuRegister());
+    summary->set_out(0, Location::RequiresRegister());
+    return summary;
+  }
+  if (operation_cid() == kSmiCid || operation_cid() == kMintCid) {
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, LocationRegisterOrConstant(left()));
+    // Only one input can be a constant operand. The case of two constant
+    // operands should be handled by constant propagation.
+    summary->set_in(1, summary->in(0).IsConstant()
+                           ? Location::RequiresRegister()
+                           : LocationRegisterOrConstant(right()));
+    summary->set_out(0, Location::RequiresRegister());
+    return summary;
+  }
+
+  UNREACHABLE();
+  return NULL;
+}
+
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                BranchLabels labels) {
+  if (operation_cid() == kSmiCid) {
+    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
+  } else if (operation_cid() == kMintCid) {
+#if XLEN == 32
+    return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels);
+#else
+    return EmitInt64ComparisonOp(compiler, locs(), kind(), labels);
+#endif
+  } else {
+    ASSERT(operation_cid() == kDoubleCid);
+    return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
+  }
+}
+
+void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  SetupNative();
+  const Register result = locs()->out(0).reg();
+
+  // All arguments are already @SP due to preceding PushArgument()s.
+  ASSERT(ArgumentCount() ==
+         function().NumParameters() + (function().IsGeneric() ? 1 : 0));
+
+  // Push the result place holder initialized to NULL.
+  __ PushObject(Object::null_object());
+
+  // Pass a pointer to the first argument in R2.
+  __ AddImmediate(T2, SP, ArgumentCount() * kWordSize);
+
+  // Compute the effective address. When running under the simulator,
+  // this is a redirection address that forces the simulator to call
+  // into the runtime system.
+  uword entry;
+  const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
+  const Code* stub;
+  if (link_lazily()) {
+    stub = &StubCode::CallBootstrapNative();
+    entry = NativeEntry::LinkNativeCallEntry();
+  } else {
+    entry = reinterpret_cast<uword>(native_c_function());
+    if (is_bootstrap_native()) {
+      stub = &StubCode::CallBootstrapNative();
+    } else if (is_auto_scope()) {
+      stub = &StubCode::CallAutoScopeNative();
+    } else {
+      stub = &StubCode::CallNoScopeNative();
+    }
+  }
+  __ LoadImmediate(T1, argc_tag);
+  compiler::ExternalLabel label(entry);
+  __ LoadNativeEntry(T5, &label,
+                     link_lazily() ? ObjectPool::Patchability::kPatchable
+                                   : ObjectPool::Patchability::kNotPatchable);
+  if (link_lazily()) {
+    compiler->GeneratePatchableCall(source(), *stub,
+                                    UntaggedPcDescriptors::kOther, locs());
+  } else {
+    // We can never lazy-deopt here because natives are never optimized.
+    ASSERT(!compiler->is_optimizing());
+    compiler->GenerateNonLazyDeoptableStubCall(
+        source(), *stub, UntaggedPcDescriptors::kOther, locs());
+  }
+  __ lx(result, compiler::Address(SP, 0));
+
+  __ Drop(ArgumentCount() + 1);  // Drop the arguments and result.
+}
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+                                                   bool is_optimizing) const {
+  LocationSummary* summary =
+      MakeLocationSummaryInternal(zone, is_optimizing, CALLEE_SAVED_TEMP2);
+  // A3/A4/A5 are blocked during Dart register allocation because they are
+  // assigned to TMP/TMP2/PP. This assignment is important for reducing code
+  // size. To work around this for FFI calls, the FFI argument definitions are
+  // allocated to other registers and moved to the correct register at the last
+  // moment (so there are no conflicting uses of TMP/TMP2/PP).
+  // FfiCallInstr itself sometimes also clobbers A2/CODE_REG.
+  // See also FfiCallInstr::EmitCall.
+  for (intptr_t i = 0; i < summary->input_count(); i++) {
+    if (!summary->in(i).IsRegister()) continue;
+    if (summary->in(i).reg() == A2) {
+      summary->set_in(i, Location::RegisterLocation(T2));
+    } else if (summary->in(i).reg() == A3) {
+      summary->set_in(i, Location::RegisterLocation(T3));
+    } else if (summary->in(i).reg() == A4) {
+      summary->set_in(i, Location::RegisterLocation(T4));
+    } else if (summary->in(i).reg() == A5) {
+      summary->set_in(i, Location::RegisterLocation(T5));
+    }
+  }
+  return summary;
+}
+
+void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // For regular calls, this holds the FP for rebasing the original locations
+  // during EmitParamMoves.
+  // For leaf calls, this holds the SP used to restore the pre-aligned SP after
+  // the call.
+  const Register saved_fp_or_sp = locs()->temp(0).reg();
+  RELEASE_ASSERT((CallingConventions::kCalleeSaveCpuRegisters &
+                  (1 << saved_fp_or_sp)) != 0);
+  const Register temp1 = locs()->temp(1).reg();
+  const Register temp2 = locs()->temp(2).reg();
+  const Register target = locs()->in(TargetAddressIndex()).reg();
+  ASSERT(temp1 != target);
+  ASSERT(temp2 != target);
+  ASSERT(temp1 != saved_fp_or_sp);
+  ASSERT(temp2 != saved_fp_or_sp);
+  ASSERT(saved_fp_or_sp != target);
+
+  // Ensure these are callee-saved register and are preserved across the call.
+  ASSERT((CallingConventions::kCalleeSaveCpuRegisters &
+          (1 << saved_fp_or_sp)) != 0);
+  // temps don't need to be preserved.
+
+  __ mv(saved_fp_or_sp, is_leaf_ ? SPREG : FPREG);
+
+  if (!is_leaf_) {
+    // We need to create a dummy "exit frame". It will share the same pool
+    // pointer but have a null code object.
+    __ LoadObject(CODE_REG, Object::null_object());
+    __ set_constant_pool_allowed(false);
+    __ EnterDartFrame(0, PP);
+  }
+
+  // Reserve space for the arguments that go on the stack (if any), then align.
+  __ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
+
+  EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1);
+
+  if (compiler::Assembler::EmittingComments()) {
+    __ Comment(is_leaf_ ? "Leaf Call" : "Call");
+  }
+
+  if (is_leaf_) {
+#if !defined(PRODUCT)
+    // Set the thread object's top_exit_frame_info and VMTag to enable the
+    // profiler to determine that thread is no longer executing Dart code.
+    __ StoreToOffset(FPREG, THR,
+                     compiler::target::Thread::top_exit_frame_info_offset());
+    __ StoreToOffset(target, THR, compiler::target::Thread::vm_tag_offset());
+#endif
+
+    EmitCall(compiler, target);
+
+#if !defined(PRODUCT)
+    __ LoadImmediate(temp1, compiler::target::Thread::vm_tag_dart_id());
+    __ StoreToOffset(temp1, THR, compiler::target::Thread::vm_tag_offset());
+    __ StoreToOffset(ZR, THR,
+                     compiler::target::Thread::top_exit_frame_info_offset());
+#endif
+  } else {
+    // We need to copy a dummy return address up into the dummy stack frame so
+    // the stack walker will know which safepoint to use.
+    //
+    // AUIPC loads relative to itself.
+    compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                   UntaggedPcDescriptors::Kind::kOther, locs(),
+                                   env());
+    __ auipc(temp1, 0);
+    __ StoreToOffset(temp1, FPREG, kSavedCallerPcSlotFromFp * kWordSize);
+
+    if (CanExecuteGeneratedCodeInSafepoint()) {
+      // Update information in the thread object and enter a safepoint.
+      __ LoadImmediate(temp1, compiler::target::Thread::exit_through_ffi());
+      __ TransitionGeneratedToNative(target, FPREG, temp1,
+                                     /*enter_safepoint=*/true);
+
+      EmitCall(compiler, target);
+
+      // Update information in the thread object and leave the safepoint.
+      __ TransitionNativeToGenerated(temp1, /*leave_safepoint=*/true);
+    } else {
+      // We cannot trust that this code will be executable within a safepoint.
+      // Therefore we delegate the responsibility of entering/exiting the
+      // safepoint to a stub which in the VM isolate's heap, which will never
+      // lose execute permission.
+      __ lx(temp1,
+            compiler::Address(
+                THR, compiler::target::Thread::
+                         call_native_through_safepoint_entry_point_offset()));
+
+      // Calls T0 and clobbers R19 (along with volatile registers).
+      ASSERT(target == T0);
+      EmitCall(compiler, temp1);
+    }
+
+    // Refresh pinned registers values (inc. write barrier mask and null
+    // object).
+    __ RestorePinnedRegisters();
+  }
+
+  EmitReturnMoves(compiler, temp1, temp2);
+
+  if (is_leaf_) {
+    // Restore the pre-aligned SP.
+    __ mv(SPREG, saved_fp_or_sp);
+  } else {
+    // Although PP is a callee-saved register, it may have been moved by the GC.
+    __ LeaveDartFrame(compiler::kRestoreCallerPP);
+
+    // Restore the global object pool after returning from runtime (old space is
+    // moving, so the GOP could have been relocated).
+    if (FLAG_precompiled_mode) {
+      __ SetupGlobalPoolAndDispatchTable();
+    }
+
+    __ set_constant_pool_allowed(true);
+  }
+}
+
+void FfiCallInstr::EmitCall(FlowGraphCompiler* compiler, Register target) {
+  // Marshall certain argument registers at the last possible moment.
+  // See FfiCallInstr::MakeLocationSummary for the details.
+  if (InputCount() > 2) __ mv(A2, T2);  // A2=CODE_REG
+  if (InputCount() > 3) __ mv(A3, T3);  // A3=TMP
+  if (InputCount() > 4) __ mv(A4, T4);  // A4=TMP2
+  if (InputCount() > 5) __ mv(A5, T5);  // A5=PP
+  __ jalr(target);
+}
+
+// Keep in sync with NativeEntryInstr::EmitNativeCode.
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  EmitReturnMoves(compiler);
+
+  __ LeaveDartFrame();
+
+  // The dummy return address is in RA, no need to pop it as on Intel.
+
+  // These can be anything besides the return registers (A0, A1) and THR (S1).
+  const Register vm_tag_reg = T2;
+  const Register old_exit_frame_reg = T3;
+  const Register old_exit_through_ffi_reg = T4;
+  const Register tmp = T5;
+
+  __ PopRegisterPair(old_exit_frame_reg, old_exit_through_ffi_reg);
+
+  // Restore top_resource.
+  __ PopRegisterPair(tmp, vm_tag_reg);
+  __ StoreToOffset(tmp, THR, compiler::target::Thread::top_resource_offset());
+
+  // Reset the exit frame info to old_exit_frame_reg *before* entering the
+  // safepoint.
+  //
+  // If we were called by a trampoline, it will enter the safepoint on our
+  // behalf.
+  __ TransitionGeneratedToNative(
+      vm_tag_reg, old_exit_frame_reg, old_exit_through_ffi_reg,
+      /*enter_safepoint=*/!NativeCallbackTrampolines::Enabled());
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Leave the entry frame.
+  __ LeaveFrame();
+
+  // Leave the dummy frame holding the pushed arguments.
+  __ LeaveFrame();
+
+  __ Ret();
+
+  // For following blocks.
+  __ set_constant_pool_allowed(true);
+}
+
+// Keep in sync with NativeReturnInstr::EmitNativeCode and ComputeInnerLRState.
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Constant pool cannot be used until we enter the actual Dart frame.
+  __ set_constant_pool_allowed(false);
+
+  __ Bind(compiler->GetJumpLabel(this));
+
+  // Create a dummy frame holding the pushed arguments. This simplifies
+  // NativeReturnInstr::EmitNativeCode.
+  __ EnterFrame(0);
+
+  // Save the argument registers, in reverse order.
+  SaveArguments(compiler);
+
+  // Enter the entry frame.
+  __ EnterFrame(0);
+
+  // Save a space for the code object.
+  __ PushImmediate(0);
+
+  __ PushNativeCalleeSavedRegisters();
+
+  // Load the thread object. If we were called by a trampoline, the thread is
+  // already loaded.
+  if (FLAG_precompiled_mode) {
+    compiler->LoadBSSEntry(BSS::Relocation::DRT_GetThreadForNativeCallback, A1,
+                           A0);
+  } else if (!NativeCallbackTrampolines::Enabled()) {
+    // In JIT mode, we can just paste the address of the runtime entry into the
+    // generated code directly. This is not a problem since we don't save
+    // callbacks into JIT snapshots.
+    __ LoadImmediate(
+        A1, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+  }
+
+  if (!NativeCallbackTrampolines::Enabled()) {
+    // Create another frame to align the frame before continuing in "native"
+    // code.
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    __ LoadImmediate(A0, callback_id_);
+    __ jalr(A1);
+    __ mv(THR, A0);
+
+    __ LeaveFrame();
+  }
+
+#if defined(USING_SHADOW_CALL_STACK)
+#error Unimplemented
+#endif
+
+  // Refresh pinned registers values (inc. write barrier mask and null object).
+  __ RestorePinnedRegisters();
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(TMP, THR, compiler::target::Thread::vm_tag_offset());
+  // Save the top resource.
+  __ LoadFromOffset(A0, THR, compiler::target::Thread::top_resource_offset());
+  __ PushRegisterPair(A0, TMP);
+
+  __ StoreToOffset(ZR, THR, compiler::target::Thread::top_resource_offset());
+
+  __ LoadFromOffset(A0, THR,
+                    compiler::target::Thread::exit_through_ffi_offset());
+  __ PushRegister(A0);
+
+  // Save the top exit frame info. We don't set it to 0 yet:
+  // TransitionNativeToGenerated will handle that.
+  __ LoadFromOffset(A0, THR,
+                    compiler::target::Thread::top_exit_frame_info_offset());
+  __ PushRegister(A0);
+
+  // In debug mode, verify that we've pushed the top exit frame info at the
+  // correct offset from FP.
+  __ EmitEntryFrameVerification();
+
+  // Either DLRT_GetThreadForNativeCallback or the callback trampoline (caller)
+  // will leave the safepoint for us.
+  __ TransitionNativeToGenerated(A0, /*exit_safepoint=*/false);
+
+  // Now that the safepoint has ended, we can touch Dart objects without
+  // handles.
+
+  // Load the code object.
+  __ LoadFromOffset(A0, THR, compiler::target::Thread::callback_code_offset());
+  __ LoadCompressedFieldFromOffset(
+      A0, A0, compiler::target::GrowableObjectArray::data_offset());
+  __ LoadCompressedFieldFromOffset(
+      CODE_REG, A0,
+      compiler::target::Array::data_offset() +
+          callback_id_ * compiler::target::kCompressedWordSize);
+
+  // Put the code object in the reserved slot.
+  __ StoreToOffset(CODE_REG, FPREG,
+                   kPcMarkerSlotFromFp * compiler::target::kWordSize);
+  if (FLAG_precompiled_mode) {
+    __ SetupGlobalPoolAndDispatchTable();
+  } else {
+    // We now load the pool pointer (PP) with a GC safe value as we are about to
+    // invoke dart code. We don't need a real object pool here.
+    // Smi zero does not work because ARM64 assumes PP to be untagged.
+    __ LoadObject(PP, compiler::NullObject());
+  }
+
+  // Load a GC-safe value for the arguments descriptor (unused but tagged).
+  __ mv(ARGS_DESC_REG, ZR);
+
+  // Load a dummy return address which suggests that we are inside of
+  // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+  __ LoadFromOffset(RA, THR,
+                    compiler::target::Thread::invoke_dart_code_stub_offset());
+  __ LoadFieldFromOffset(RA, RA, compiler::target::Code::entry_point_offset());
+
+  FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
+LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
+    Zone* zone,
+    bool opt) const {
+  const intptr_t kNumInputs = 1;
+  // TODO(fschneider): Allow immediate operands for the char code.
+  return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void OneByteStringFromCharCodeInstr::EmitNativeCode(
+    FlowGraphCompiler* compiler) {
+  ASSERT(compiler->is_optimizing());
+  const Register char_code = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  __ lx(result,
+        compiler::Address(THR, Thread::predefined_symbols_address_offset()));
+  __ slli(TMP, char_code, kWordSizeLog2 - kSmiTagSize);
+  __ add(result, result, TMP);
+  __ lx(result, compiler::Address(
+                    result, Symbols::kNullCharCodeSymbolOffset * kWordSize));
+}
+
+LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(cid_ == kOneByteStringCid);
+  Register str = locs()->in(0).reg();
+  Register result = locs()->out(0).reg();
+  compiler::Label is_one, done;
+  __ LoadCompressedSmi(result,
+                       compiler::FieldAddress(str, String::length_offset()));
+  __ CompareImmediate(result, Smi::RawValue(1));
+  __ BranchIf(EQUAL, &is_one, compiler::Assembler::kNearJump);
+  __ li(result, Smi::RawValue(-1));
+  __ j(&done, compiler::Assembler::kNearJump);
+  __ Bind(&is_one);
+  __ lbu(result, compiler::FieldAddress(str, OneByteString::data_offset()));
+  __ SmiTag(result);
+  __ Bind(&done);
+}
+
+LocationSummary* Utf8ScanInstr::MakeLocationSummary(Zone* zone,
+                                                    bool opt) const {
+  const intptr_t kNumInputs = 5;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::Any());               // decoder
+  summary->set_in(1, Location::WritableRegister());  // bytes
+  summary->set_in(2, Location::WritableRegister());  // start
+  summary->set_in(3, Location::WritableRegister());  // end
+  summary->set_in(4, Location::WritableRegister());  // table
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void Utf8ScanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register bytes_reg = locs()->in(1).reg();
+  const Register start_reg = locs()->in(2).reg();
+  const Register end_reg = locs()->in(3).reg();
+  const Register table_reg = locs()->in(4).reg();
+  const Register size_reg = locs()->out(0).reg();
+
+  const Register bytes_ptr_reg = start_reg;
+  const Register bytes_end_reg = end_reg;
+  const Register flags_reg = bytes_reg;
+  const Register temp_reg = TMP;
+  const Register decoder_temp_reg = start_reg;
+  const Register flags_temp_reg = end_reg;
+
+  static const intptr_t kSizeMask = 0x03;
+  static const intptr_t kFlagsMask = 0x3C;
+
+  compiler::Label loop, loop_in;
+
+  // Address of input bytes.
+  __ LoadFieldFromOffset(bytes_reg, bytes_reg,
+                         compiler::target::TypedDataBase::data_field_offset());
+
+  // Table.
+  __ AddImmediate(
+      table_reg, table_reg,
+      compiler::target::OneByteString::data_offset() - kHeapObjectTag);
+
+  // Pointers to start and end.
+  __ add(bytes_ptr_reg, bytes_reg, start_reg);
+  __ add(bytes_end_reg, bytes_reg, end_reg);
+
+  // Initialize size and flags.
+  __ li(size_reg, 0);
+  __ li(flags_reg, 0);
+
+  __ j(&loop_in, compiler::Assembler::kNearJump);
+  __ Bind(&loop);
+
+  // Read byte and increment pointer.
+  __ lbu(temp_reg, compiler::Address(bytes_ptr_reg, 0));
+  __ addi(bytes_ptr_reg, bytes_ptr_reg, 1);
+
+  // Update size and flags based on byte value.
+  __ add(temp_reg, table_reg, temp_reg);
+  __ lbu(temp_reg, compiler::Address(temp_reg));
+  __ or_(flags_reg, flags_reg, temp_reg);
+  __ andi(temp_reg, temp_reg, kSizeMask);
+  __ add(size_reg, size_reg, temp_reg);
+
+  // Stop if end is reached.
+  __ Bind(&loop_in);
+  __ bltu(bytes_ptr_reg, bytes_end_reg, &loop, compiler::Assembler::kNearJump);
+
+  // Write flags to field.
+  __ AndImmediate(flags_reg, flags_reg, kFlagsMask);
+  if (!IsScanFlagsUnboxed()) {
+    __ SmiTag(flags_reg);
+  }
+  Register decoder_reg;
+  const Location decoder_location = locs()->in(0);
+  if (decoder_location.IsStackSlot()) {
+    __ lx(decoder_temp_reg, LocationToStackSlotAddress(decoder_location));
+    decoder_reg = decoder_temp_reg;
+  } else {
+    decoder_reg = decoder_location.reg();
+  }
+  const auto scan_flags_field_offset = scan_flags_field_.offset_in_bytes();
+  if (scan_flags_field_.is_compressed() && !IsScanFlagsUnboxed()) {
+    UNIMPLEMENTED();
+  } else {
+    __ LoadFieldFromOffset(flags_temp_reg, decoder_reg,
+                           scan_flags_field_offset);
+    __ or_(flags_temp_reg, flags_temp_reg, flags_reg);
+    __ StoreFieldToOffset(flags_temp_reg, decoder_reg, scan_flags_field_offset);
+  }
+}
+
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register obj = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  if (object()->definition()->representation() == kUntagged) {
+    __ LoadFromOffset(result, obj, offset());
+  } else {
+    ASSERT(object()->definition()->representation() == kTagged);
+    __ LoadFieldFromOffset(result, obj, offset());
+  }
+}
+
+static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) {
+  ConstantInstr* constant = value->definition()->AsConstant();
+  if ((constant == NULL) || !constant->value().IsSmi()) {
+    return false;
+  }
+  const int64_t index = Smi::Cast(constant->value()).AsInt64Value();
+  const intptr_t scale = Instance::ElementSizeFor(cid);
+  const int64_t offset =
+      index * scale +
+      (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
+  if (IsITypeImm(offset)) {
+    ASSERT(IsSTypeImm(offset));
+    return true;
+  }
+  return false;
+}
+
+LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
+    locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
+  } else {
+    locs->set_in(1, Location::RequiresRegister());
+  }
+  if ((representation() == kUnboxedDouble) ||
+      (representation() == kUnboxedFloat32x4) ||
+      (representation() == kUnboxedInt32x4) ||
+      (representation() == kUnboxedFloat64x2)) {
+    locs->set_out(0, Location::RequiresFpuRegister());
+#if XLEN == 32
+  } else if (representation() == kUnboxedInt64) {
+    ASSERT(class_id() == kTypedDataInt64ArrayCid ||
+           class_id() == kTypedDataUint64ArrayCid);
+    locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+#endif
+  } else {
+    locs->set_out(0, Location::RequiresRegister());
+  }
+  return locs;
+}
+
+void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // The array register points to the backing store for external arrays.
+  const Register array = locs()->in(0).reg();
+  const Location index = locs()->in(1);
+
+  compiler::Address element_address(TMP);  // Bad address.
+  element_address = index.IsRegister()
+                        ? __ ElementAddressForRegIndex(
+                              IsExternal(), class_id(), index_scale(),
+                              index_unboxed_, array, index.reg(), TMP)
+                        : __ ElementAddressForIntIndex(
+                              IsExternal(), class_id(), index_scale(), array,
+                              Smi::Cast(index.constant()).Value());
+  if ((representation() == kUnboxedDouble) ||
+      (representation() == kUnboxedFloat32x4) ||
+      (representation() == kUnboxedInt32x4) ||
+      (representation() == kUnboxedFloat64x2)) {
+    const FRegister result = locs()->out(0).fpu_reg();
+    switch (class_id()) {
+      case kTypedDataFloat32ArrayCid:
+        // Load single precision float.
+        __ flw(result, element_address);
+        break;
+      case kTypedDataFloat64ArrayCid:
+        // Load double precision float.
+        __ fld(result, element_address);
+        break;
+      case kTypedDataFloat64x2ArrayCid:
+      case kTypedDataInt32x4ArrayCid:
+      case kTypedDataFloat32x4ArrayCid:
+        UNIMPLEMENTED();
+        break;
+      default:
+        UNREACHABLE();
+    }
+    return;
+  }
+
+  switch (class_id()) {
+    case kTypedDataInt32ArrayCid: {
+      ASSERT(representation() == kUnboxedInt32);
+      const Register result = locs()->out(0).reg();
+      __ lw(result, element_address);
+      break;
+    }
+    case kTypedDataUint32ArrayCid: {
+      ASSERT(representation() == kUnboxedUint32);
+      const Register result = locs()->out(0).reg();
+#if XLEN == 32
+      __ lw(result, element_address);
+#else
+      __ lwu(result, element_address);
+#endif
+      break;
+    }
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid: {
+      ASSERT(representation() == kUnboxedInt64);
+#if XLEN == 32
+      ASSERT(locs()->out(0).IsPairLocation());
+      PairLocation* result_pair = locs()->out(0).AsPairLocation();
+      const Register result_lo = result_pair->At(0).reg();
+      const Register result_hi = result_pair->At(1).reg();
+      __ lw(result_lo, element_address);
+      __ lw(result_hi, compiler::Address(element_address.base(),
+                                         element_address.offset() + 4));
+#else
+      const Register result = locs()->out(0).reg();
+      __ ld(result, element_address);
+#endif
+      break;
+    }
+    case kTypedDataInt8ArrayCid: {
+      ASSERT(representation() == kUnboxedIntPtr);
+      ASSERT(index_scale() == 1);
+      const Register result = locs()->out(0).reg();
+      __ lb(result, element_address);
+      break;
+    }
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kOneByteStringCid:
+    case kExternalOneByteStringCid: {
+      ASSERT(representation() == kUnboxedIntPtr);
+      ASSERT(index_scale() == 1);
+      const Register result = locs()->out(0).reg();
+      __ lbu(result, element_address);
+      break;
+    }
+    case kTypedDataInt16ArrayCid: {
+      ASSERT(representation() == kUnboxedIntPtr);
+      const Register result = locs()->out(0).reg();
+      __ lh(result, element_address);
+      break;
+    }
+    case kTypedDataUint16ArrayCid:
+    case kTwoByteStringCid:
+    case kExternalTwoByteStringCid: {
+      ASSERT(representation() == kUnboxedIntPtr);
+      const Register result = locs()->out(0).reg();
+      __ lhu(result, element_address);
+      break;
+    }
+    default: {
+      ASSERT(representation() == kTagged);
+      ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) ||
+             (class_id() == kTypeArgumentsCid));
+      const Register result = locs()->out(0).reg();
+      __ lx(result, element_address);
+      break;
+    }
+  }
+}
+
+LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+#if XLEN == 32
+  if (representation() == kUnboxedInt64) {
+    summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                       Location::RequiresRegister()));
+  } else {
+    ASSERT(representation() == kTagged);
+    summary->set_out(0, Location::RequiresRegister());
+  }
+#else
+  summary->set_out(0, Location::RequiresRegister());
+#endif
+  return summary;
+}
+
+void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // The string register points to the backing store for external strings.
+  const Register str = locs()->in(0).reg();
+  const Location index = locs()->in(1);
+  compiler::OperandSize sz = compiler::kByte;
+
+#if XLEN == 32
+  if (representation() == kUnboxedInt64) {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(locs()->out(0).IsPairLocation());
+    UNIMPLEMENTED();
+  }
+#endif
+
+  Register result = locs()->out(0).reg();
+  switch (class_id()) {
+    case kOneByteStringCid:
+    case kExternalOneByteStringCid:
+      switch (element_count()) {
+        case 1:
+          sz = compiler::kUnsignedByte;
+          break;
+        case 2:
+          sz = compiler::kUnsignedTwoBytes;
+          break;
+        case 4:
+          sz = compiler::kUnsignedFourBytes;
+          break;
+        default:
+          UNREACHABLE();
+      }
+      break;
+    case kTwoByteStringCid:
+    case kExternalTwoByteStringCid:
+      switch (element_count()) {
+        case 1:
+          sz = compiler::kUnsignedTwoBytes;
+          break;
+        case 2:
+          sz = compiler::kUnsignedFourBytes;
+          break;
+        default:
+          UNREACHABLE();
+      }
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  // Warning: element_address may use register TMP as base.
+  compiler::Address element_address = __ ElementAddressForRegIndexWithSize(
+      IsExternal(), class_id(), sz, index_scale(), /*index_unboxed=*/false, str,
+      index.reg(), TMP);
+  switch (sz) {
+    case compiler::kUnsignedByte:
+      __ lbu(result, element_address);
+      break;
+    case compiler::kUnsignedTwoBytes:
+      __ lhu(result, element_address);
+      break;
+    case compiler::kUnsignedFourBytes:
+#if XLEN == 32
+      __ lw(result, element_address);
+#else
+      __ lwu(result, element_address);
+#endif
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  ASSERT(can_pack_into_smi());
+  __ SmiTag(result);
+}
+
+LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
+    locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
+  } else {
+    locs->set_in(1, Location::RequiresRegister());
+  }
+  locs->set_temp(0, Location::RequiresRegister());
+
+  switch (class_id()) {
+    case kArrayCid:
+      locs->set_in(2, ShouldEmitStoreBarrier()
+                          ? Location::RegisterLocation(kWriteBarrierValueReg)
+                          : LocationRegisterOrConstant(value()));
+      if (ShouldEmitStoreBarrier()) {
+        locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
+        locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
+      }
+      break;
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kOneByteStringCid:
+    case kTwoByteStringCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+      locs->set_in(2, Location::RequiresRegister());
+      break;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+#if XLEN == 32
+      locs->set_in(2, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+#else
+      locs->set_in(2, Location::RequiresRegister());
+#endif
+      break;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:  // TODO(srdjan): Support Float64 constants.
+      locs->set_in(2, Location::RequiresFpuRegister());
+      break;
+    case kTypedDataInt32x4ArrayCid:
+    case kTypedDataFloat32x4ArrayCid:
+    case kTypedDataFloat64x2ArrayCid:
+      locs->set_in(2, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+  return locs;
+}
+
+void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // The array register points to the backing store for external arrays.
+  const Register array = locs()->in(0).reg();
+  const Location index = locs()->in(1);
+  const Register temp = locs()->temp(0).reg();
+  compiler::Address element_address(TMP);  // Bad address.
+
+  // Deal with a special case separately.
+  if (class_id() == kArrayCid && ShouldEmitStoreBarrier()) {
+    if (index.IsRegister()) {
+      __ ComputeElementAddressForRegIndex(temp, IsExternal(), class_id(),
+                                          index_scale(), index_unboxed_, array,
+                                          index.reg());
+    } else {
+      __ ComputeElementAddressForIntIndex(temp, IsExternal(), class_id(),
+                                          index_scale(), array,
+                                          Smi::Cast(index.constant()).Value());
+    }
+    const Register value = locs()->in(2).reg();
+    __ StoreIntoArray(array, temp, value, CanValueBeSmi());
+    return;
+  }
+
+  element_address = index.IsRegister()
+                        ? __ ElementAddressForRegIndex(
+                              IsExternal(), class_id(), index_scale(),
+                              index_unboxed_, array, index.reg(), temp)
+                        : __ ElementAddressForIntIndex(
+                              IsExternal(), class_id(), index_scale(), array,
+                              Smi::Cast(index.constant()).Value());
+
+  switch (class_id()) {
+    case kArrayCid:
+      ASSERT(!ShouldEmitStoreBarrier());  // Specially treated above.
+      if (locs()->in(2).IsConstant()) {
+        const Object& constant = locs()->in(2).constant();
+        __ StoreIntoObjectNoBarrier(array, element_address, constant);
+      } else {
+        const Register value = locs()->in(2).reg();
+        __ StoreIntoObjectNoBarrier(array, element_address, value);
+      }
+      break;
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kOneByteStringCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
+      if (locs()->in(2).IsConstant()) {
+        const Smi& constant = Smi::Cast(locs()->in(2).constant());
+        __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()));
+        __ sb(TMP, element_address);
+      } else {
+        const Register value = locs()->in(2).reg();
+        __ sb(value, element_address);
+      }
+      break;
+    }
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
+      if (locs()->in(2).IsConstant()) {
+        const Smi& constant = Smi::Cast(locs()->in(2).constant());
+        intptr_t value = constant.Value();
+        // Clamp to 0x0 or 0xFF respectively.
+        if (value > 0xFF) {
+          value = 0xFF;
+        } else if (value < 0) {
+          value = 0;
+        }
+        __ LoadImmediate(TMP, static_cast<int8_t>(value));
+        __ sb(TMP, element_address);
+      } else {
+        const Register value = locs()->in(2).reg();
+
+        compiler::Label store_zero, store_ff, done;
+        __ blt(value, ZR, &store_zero, compiler::Assembler::kNearJump);
+
+        __ li(TMP, 0xFF);
+        __ bgt(value, TMP, &store_ff, compiler::Assembler::kNearJump);
+
+        __ sb(value, element_address);
+        __ j(&done, compiler::Assembler::kNearJump);
+
+        __ Bind(&store_zero);
+        __ mv(TMP, ZR);
+
+        __ Bind(&store_ff);
+        __ sb(TMP, element_address);
+
+        __ Bind(&done);
+      }
+      break;
+    }
+    case kTwoByteStringCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
+      const Register value = locs()->in(2).reg();
+      __ sh(value, element_address);
+      break;
+    }
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid: {
+      const Register value = locs()->in(2).reg();
+      __ sw(value, element_address);
+      break;
+    }
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid: {
+#if XLEN >= 64
+      const Register value = locs()->in(2).reg();
+      __ sd(value, element_address);
+#else
+      PairLocation* value_pair = locs()->in(2).AsPairLocation();
+      Register value_lo = value_pair->At(0).reg();
+      Register value_hi = value_pair->At(1).reg();
+      __ sw(value_lo, element_address);
+      __ sw(value_hi, compiler::Address(element_address.base(),
+                                        element_address.offset() + 4));
+#endif
+      break;
+    }
+    case kTypedDataFloat32ArrayCid: {
+      const FRegister value_reg = locs()->in(2).fpu_reg();
+      __ fsw(value_reg, element_address);
+      break;
+    }
+    case kTypedDataFloat64ArrayCid: {
+      const FRegister value_reg = locs()->in(2).fpu_reg();
+      __ fsd(value_reg, element_address);
+      break;
+    }
+    case kTypedDataFloat64x2ArrayCid:
+    case kTypedDataInt32x4ArrayCid:
+    case kTypedDataFloat32x4ArrayCid: {
+      UNIMPLEMENTED();
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+static void LoadValueCid(FlowGraphCompiler* compiler,
+                         Register value_cid_reg,
+                         Register value_reg,
+                         compiler::Label* value_is_smi = NULL) {
+  compiler::Label done;
+  if (value_is_smi == NULL) {
+    __ LoadImmediate(value_cid_reg, kSmiCid);
+  }
+  __ BranchIfSmi(value_reg, value_is_smi == NULL ? &done : value_is_smi);
+  __ LoadClassId(value_cid_reg, value_reg);
+  __ Bind(&done);
+}
+
+DEFINE_UNIMPLEMENTED_INSTRUCTION(GuardFieldTypeInstr)
+DEFINE_UNIMPLEMENTED_INSTRUCTION(CheckConditionInstr)
+
+LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 1;
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+
+  const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg =
+      emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  intptr_t num_temps = 0;
+  if (needs_value_cid_temp_reg) {
+    num_temps++;
+  }
+  if (needs_field_temp_reg) {
+    num_temps++;
+  }
+
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+
+  for (intptr_t i = 0; i < num_temps; i++) {
+    summary->set_temp(i, Location::RequiresRegister());
+  }
+
+  return summary;
+}
+
+void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t field_cid = field().guarded_cid();
+  const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+  if (field_cid == kDynamicCid) {
+    return;  // Nothing to emit.
+  }
+
+  const bool emit_full_guard =
+      !compiler->is_optimizing() || (field_cid == kIllegalCid);
+
+  const bool needs_value_cid_temp_reg =
+      emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid));
+
+  const bool needs_field_temp_reg = emit_full_guard;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  const Register value_cid_reg =
+      needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister;
+
+  const Register field_reg = needs_field_temp_reg
+                                 ? locs()->temp(locs()->temp_count() - 1).reg()
+                                 : kNoRegister;
+
+  compiler::Label ok, fail_label;
+
+  compiler::Label* deopt =
+      compiler->is_optimizing()
+          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
+          : NULL;
+
+  compiler::Label* fail = (deopt != NULL) ? deopt : &fail_label;
+
+  if (emit_full_guard) {
+    __ LoadObject(field_reg, Field::ZoneHandle((field().Original())));
+
+    compiler::FieldAddress field_cid_operand(field_reg,
+                                             Field::guarded_cid_offset());
+    compiler::FieldAddress field_nullability_operand(
+        field_reg, Field::is_nullable_offset());
+
+    if (value_cid == kDynamicCid) {
+      LoadValueCid(compiler, value_cid_reg, value_reg);
+      compiler::Label skip_length_check;
+      __ lhu(TMP, field_cid_operand);
+      __ CompareRegisters(value_cid_reg, TMP);
+      __ BranchIf(EQ, &ok);
+      __ lhu(TMP, field_nullability_operand);
+      __ CompareRegisters(value_cid_reg, TMP);
+    } else if (value_cid == kNullCid) {
+      __ lhu(value_cid_reg, field_nullability_operand);
+      __ CompareImmediate(value_cid_reg, value_cid);
+    } else {
+      compiler::Label skip_length_check;
+      __ lhu(value_cid_reg, field_cid_operand);
+      __ CompareImmediate(value_cid_reg, value_cid);
+    }
+    __ BranchIf(EQ, &ok);
+
+    // Check if the tracked state of the guarded field can be initialized
+    // inline. If the field needs length check we fall through to runtime
+    // which is responsible for computing offset of the length field
+    // based on the class id.
+    // Length guard will be emitted separately when needed via GuardFieldLength
+    // instruction after GuardFieldClass.
+    if (!field().needs_length_check()) {
+      // Uninitialized field can be handled inline. Check if the
+      // field is still unitialized.
+      __ lhu(TMP, field_cid_operand);
+      __ CompareImmediate(TMP, kIllegalCid);
+      __ BranchIf(NE, fail);
+
+      if (value_cid == kDynamicCid) {
+        __ sh(value_cid_reg, field_cid_operand);
+        __ sh(value_cid_reg, field_nullability_operand);
+      } else {
+        __ LoadImmediate(TMP, value_cid);
+        __ sh(TMP, field_cid_operand);
+        __ sh(TMP, field_nullability_operand);
+      }
+
+      __ j(&ok);
+    }
+
+    if (deopt == NULL) {
+      __ Bind(fail);
+
+      __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(),
+                             compiler::kUnsignedTwoBytes);
+      __ CompareImmediate(TMP, kDynamicCid);
+      __ BranchIf(EQ, &ok);
+
+      __ PushRegisterPair(value_reg, field_reg);
+      ASSERT(!compiler->is_optimizing());  // No deopt info needed.
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ j(fail);
+    }
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(deopt != NULL);
+
+    // Field guard class has been initialized and is known.
+    if (value_cid == kDynamicCid) {
+      // Value's class id is not known.
+      __ TestImmediate(value_reg, kSmiTagMask);
+
+      if (field_cid != kSmiCid) {
+        __ BranchIf(EQ, fail);
+        __ LoadClassId(value_cid_reg, value_reg);
+        __ CompareImmediate(value_cid_reg, field_cid);
+      }
+
+      if (field().is_nullable() && (field_cid != kNullCid)) {
+        __ BranchIf(EQ, &ok);
+        __ CompareObject(value_reg, Object::null_object());
+      }
+
+      __ BranchIf(NE, fail);
+    } else if (value_cid == field_cid) {
+      // This would normaly be caught by Canonicalize, but RemoveRedefinitions
+      // may sometimes produce the situation after the last Canonicalize pass.
+    } else {
+      // Both value's and field's class id is known.
+      ASSERT(value_cid != nullability);
+      __ j(fail);
+    }
+  }
+  __ Bind(&ok);
+}
+
+LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const intptr_t kNumTemps = 3;
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    // We need temporaries for field object, length offset and expected length.
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+    summary->set_temp(2, Location::RequiresRegister());
+    return summary;
+  } else {
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    return summary;
+  }
+  UNREACHABLE();
+}
+
+void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (field().guarded_list_length() == Field::kNoFixedLength) {
+    return;  // Nothing to emit.
+  }
+
+  compiler::Label* deopt =
+      compiler->is_optimizing()
+          ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
+          : NULL;
+
+  const Register value_reg = locs()->in(0).reg();
+
+  if (!compiler->is_optimizing() ||
+      (field().guarded_list_length() == Field::kUnknownFixedLength)) {
+    const Register field_reg = locs()->temp(0).reg();
+    const Register offset_reg = locs()->temp(1).reg();
+    const Register length_reg = locs()->temp(2).reg();
+
+    compiler::Label ok;
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().Original()));
+
+    __ lb(offset_reg,
+          compiler::FieldAddress(
+              field_reg, Field::guarded_list_length_in_object_offset_offset()));
+    __ LoadCompressed(
+        length_reg,
+        compiler::FieldAddress(field_reg, Field::guarded_list_length_offset()));
+
+    __ bltz(offset_reg, &ok, compiler::Assembler::kNearJump);
+
+    // Load the length from the value. GuardFieldClass already verified that
+    // value's class matches guarded class id of the field.
+    // offset_reg contains offset already corrected by -kHeapObjectTag that is
+    // why we use Address instead of FieldAddress.
+    __ add(TMP, value_reg, offset_reg);
+    __ lx(TMP, compiler::Address(TMP, 0));
+    __ CompareObjectRegisters(length_reg, TMP);
+
+    if (deopt == NULL) {
+      __ BranchIf(EQ, &ok);
+
+      __ PushRegisterPair(value_reg, field_reg);
+      ASSERT(!compiler->is_optimizing());  // No deopt info needed.
+      __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
+      __ Drop(2);  // Drop the field and the value.
+    } else {
+      __ BranchIf(NE, deopt);
+    }
+
+    __ Bind(&ok);
+  } else {
+    ASSERT(compiler->is_optimizing());
+    ASSERT(field().guarded_list_length() >= 0);
+    ASSERT(field().guarded_list_length_in_object_offset() !=
+           Field::kUnknownLengthOffset);
+
+    __ lx(TMP, compiler::FieldAddress(
+                   value_reg, field().guarded_list_length_in_object_offset()));
+    __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length()));
+    __ BranchIf(NE, deopt);
+  }
+}
+
+static void EnsureMutableBox(FlowGraphCompiler* compiler,
+                             StoreInstanceFieldInstr* instruction,
+                             Register box_reg,
+                             const Class& cls,
+                             Register instance_reg,
+                             intptr_t offset,
+                             Register temp) {
+  compiler::Label done;
+  __ LoadCompressedFieldFromOffset(box_reg, instance_reg, offset);
+  __ CompareObject(box_reg, Object::null_object());
+  __ BranchIf(NE, &done);
+  BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
+  __ MoveRegister(temp, box_reg);
+  __ StoreCompressedIntoObjectOffset(instance_reg, offset, temp,
+                                     compiler::Assembler::kValueIsNotSmi);
+  __ Bind(&done);
+}
+
+LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                              bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = (IsUnboxedDartFieldStore() && opt)
+                                 ? (FLAG_precompiled_mode ? 0 : 2)
+                                 : (IsPotentialUnboxedDartFieldStore() ? 2 : 0);
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      (!FLAG_precompiled_mode &&
+       ((IsUnboxedDartFieldStore() && opt && is_initialization()) ||
+        IsPotentialUnboxedDartFieldStore()))
+          ? LocationSummary::kCallOnSlowPath
+          : LocationSummary::kNoCall);
+
+  summary->set_in(kInstancePos, Location::RequiresRegister());
+  if (slot().representation() != kTagged) {
+    ASSERT(RepresentationUtils::IsUnboxedInteger(slot().representation()));
+    const size_t value_size =
+        RepresentationUtils::ValueSize(slot().representation());
+    if (value_size <= compiler::target::kWordSize) {
+      summary->set_in(kValuePos, Location::RequiresRegister());
+    } else {
+#if XLEN == 32
+      ASSERT(value_size <= 2 * compiler::target::kWordSize);
+      summary->set_in(kValuePos, Location::Pair(Location::RequiresRegister(),
+                                                Location::RequiresRegister()));
+#else
+      UNREACHABLE();
+#endif
+    }
+  } else if (IsUnboxedDartFieldStore() && opt) {
+    summary->set_in(kValuePos, Location::RequiresFpuRegister());
+    if (!FLAG_precompiled_mode) {
+      summary->set_temp(0, Location::RequiresRegister());
+      summary->set_temp(1, Location::RequiresRegister());
+    }
+  } else if (IsPotentialUnboxedDartFieldStore()) {
+    summary->set_in(kValuePos, ShouldEmitStoreBarrier()
+                                   ? Location::WritableRegister()
+                                   : Location::RequiresRegister());
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+  } else {
+    summary->set_in(kValuePos,
+                    ShouldEmitStoreBarrier()
+                        ? Location::RegisterLocation(kWriteBarrierValueReg)
+                        : LocationRegisterOrConstant(value()));
+  }
+  return summary;
+}
+
+void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
+
+  compiler::Label skip_store;
+
+  const Register instance_reg = locs()->in(kInstancePos).reg();
+  const intptr_t offset_in_bytes = OffsetInBytes();
+  ASSERT(offset_in_bytes > 0);  // Field is finalized and points after header.
+
+  if (slot().representation() != kTagged) {
+    ASSERT(memory_order_ != compiler::AssemblerBase::kRelease);
+    auto const rep = slot().representation();
+    ASSERT(RepresentationUtils::IsUnboxedInteger(rep));
+    const size_t value_size = RepresentationUtils::ValueSize(rep);
+    __ Comment("NativeUnboxedStoreInstanceFieldInstr");
+    if (value_size <= compiler::target::kWordSize) {
+      const Register value = locs()->in(kValuePos).reg();
+      __ StoreFieldToOffset(value, instance_reg, offset_in_bytes,
+                            RepresentationUtils::OperandSize(rep));
+    } else {
+#if XLEN == 32
+      auto const in_pair = locs()->in(kValuePos).AsPairLocation();
+      const Register in_lo = in_pair->At(0).reg();
+      const Register in_hi = in_pair->At(1).reg();
+      const intptr_t offset_lo = OffsetInBytes() - kHeapObjectTag;
+      const intptr_t offset_hi = offset_lo + compiler::target::kWordSize;
+      __ StoreToOffset(in_lo, instance_reg, offset_lo);
+      __ StoreToOffset(in_hi, instance_reg, offset_hi);
+#else
+      UNREACHABLE();
+#endif
+    }
+    return;
+  }
+
+  if (IsUnboxedDartFieldStore() && compiler->is_optimizing()) {
+    ASSERT(memory_order_ != compiler::AssemblerBase::kRelease);
+    const FRegister value = locs()->in(kValuePos).fpu_reg();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
+
+    if (FLAG_precompiled_mode) {
+      switch (cid) {
+        case kDoubleCid:
+          __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
+          __ StoreDFieldToOffset(value, instance_reg, offset_in_bytes);
+          return;
+        case kFloat32x4Cid:
+          __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
+          UNIMPLEMENTED();
+          return;
+        case kFloat64x2Cid:
+          __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
+          UNIMPLEMENTED();
+          return;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+    const Register temp = locs()->temp(0).reg();
+    const Register temp2 = locs()->temp(1).reg();
+
+    if (is_initialization()) {
+      const Class* cls = NULL;
+      switch (cid) {
+        case kDoubleCid:
+          cls = &compiler->double_class();
+          break;
+        case kFloat32x4Cid:
+          cls = &compiler->float32x4_class();
+          break;
+        case kFloat64x2Cid:
+          cls = &compiler->float64x2_class();
+          break;
+        default:
+          UNREACHABLE();
+      }
+
+      BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
+      __ MoveRegister(temp2, temp);
+      __ StoreCompressedIntoObjectOffset(instance_reg, offset_in_bytes, temp2,
+                                         compiler::Assembler::kValueIsNotSmi);
+    } else {
+      __ LoadCompressedFieldFromOffset(temp, instance_reg, offset_in_bytes);
+    }
+    switch (cid) {
+      case kDoubleCid:
+        __ Comment("UnboxedDoubleStoreInstanceFieldInstr");
+        __ StoreDFieldToOffset(value, temp, Double::value_offset());
+        break;
+      case kFloat32x4Cid:
+        __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
+        UNIMPLEMENTED();
+        break;
+      case kFloat64x2Cid:
+        __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
+        UNIMPLEMENTED();
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    return;
+  }
+
+  if (IsPotentialUnboxedDartFieldStore()) {
+    ASSERT(memory_order_ != compiler::AssemblerBase::kRelease);
+    const Register value_reg = locs()->in(kValuePos).reg();
+    const Register temp = locs()->temp(0).reg();
+    const Register temp2 = locs()->temp(1).reg();
+
+    if (ShouldEmitStoreBarrier()) {
+      // Value input is a writable register and should be manually preserved
+      // across allocation slow-path.
+      locs()->live_registers()->Add(locs()->in(kValuePos), kTagged);
+    }
+
+    compiler::Label store_pointer;
+    compiler::Label store_double;
+    compiler::Label store_float32x4;
+    compiler::Label store_float64x2;
+
+    __ LoadObject(temp, Field::ZoneHandle(Z, slot().field().Original()));
+
+    __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(),
+                           compiler::kUnsignedTwoBytes);
+    __ CompareImmediate(temp2, kNullCid);
+    __ BranchIf(EQ, &store_pointer);
+
+    __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag,
+                      compiler::kUnsignedByte);
+    __ TestImmediate(temp2, 1 << Field::kUnboxingCandidateBit);
+    __ BranchIf(EQ, &store_pointer);
+
+    __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(),
+                           compiler::kUnsignedTwoBytes);
+    __ CompareImmediate(temp2, kDoubleCid);
+    __ BranchIf(EQ, &store_double);
+
+    // Fall through.
+    __ j(&store_pointer);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(kInstancePos));
+      locs()->live_registers()->Add(locs()->in(kValuePos));
+    }
+
+    {
+      __ Bind(&store_double);
+      EnsureMutableBox(compiler, this, temp, compiler->double_class(),
+                       instance_reg, offset_in_bytes, temp2);
+      __ LoadDFieldFromOffset(FTMP, value_reg, Double::value_offset());
+      __ StoreDFieldToOffset(FTMP, temp, Double::value_offset());
+      __ j(&skip_store);
+    }
+
+    __ Bind(&store_pointer);
+  }
+
+  const bool compressed = slot().is_compressed();
+  if (ShouldEmitStoreBarrier()) {
+    const Register value_reg = locs()->in(kValuePos).reg();
+    if (!compressed) {
+      __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
+                               CanValueBeSmi(), memory_order_);
+    } else {
+      __ StoreCompressedIntoObjectOffset(instance_reg, offset_in_bytes,
+                                         value_reg, CanValueBeSmi(),
+                                         memory_order_);
+    }
+  } else {
+    if (locs()->in(kValuePos).IsConstant()) {
+      const auto& value = locs()->in(kValuePos).constant();
+      if (!compressed) {
+        __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes, value,
+                                          memory_order_);
+      } else {
+        __ StoreCompressedIntoObjectOffsetNoBarrier(
+            instance_reg, offset_in_bytes, value, memory_order_);
+      }
+    } else {
+      const Register value_reg = locs()->in(kValuePos).reg();
+      if (!compressed) {
+        __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes,
+                                          value_reg, memory_order_);
+      } else {
+        __ StoreCompressedIntoObjectOffsetNoBarrier(
+            instance_reg, offset_in_bytes, value_reg, memory_order_);
+      }
+    }
+  }
+  __ Bind(&skip_store);
+}
+
+LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone,
+                                                            bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  return locs;
+}
+
+void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+
+  compiler->used_static_fields().Add(&field());
+
+  __ LoadFromOffset(TMP, THR,
+                    compiler::target::Thread::field_table_values_offset());
+  // Note: static fields ids won't be changed by hot-reload.
+  __ StoreToOffset(value, TMP, compiler::target::FieldTable::OffsetOf(field()));
+}
+
+LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
+  summary->set_out(
+      0, Location::RegisterLocation(TypeTestABI::kInstanceOfResultReg));
+  return summary;
+}
+
+void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
+  ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
+  ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
+
+  compiler->GenerateInstanceOf(source(), deopt_id(), env(), type(), locs());
+  ASSERT(locs()->out(0).reg() == TypeTestABI::kInstanceOfResultReg);
+}
+
+LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(kTypeArgumentsPos,
+               Location::RegisterLocation(AllocateArrayABI::kTypeArgumentsReg));
+  locs->set_in(kLengthPos,
+               Location::RegisterLocation(AllocateArrayABI::kLengthReg));
+  locs->set_out(0, Location::RegisterLocation(AllocateArrayABI::kResultReg));
+  return locs;
+}
+
+// Inlines array allocation for known constant values.
+static void InlineArrayAllocation(FlowGraphCompiler* compiler,
+                                  intptr_t num_elements,
+                                  compiler::Label* slow_path,
+                                  compiler::Label* done) {
+  const int kInlineArraySize = 12;  // Same as kInlineInstanceSize.
+  const intptr_t instance_size = Array::InstanceSize(num_elements);
+
+  __ TryAllocateArray(kArrayCid, instance_size, slow_path,
+                      AllocateArrayABI::kResultReg,  // instance
+                      T3,                            // end address
+                      T4, T5);
+  // AllocateArrayABI::kResultReg: new object start as a tagged pointer.
+  // R3: new object end address.
+
+  // Store the type argument field.
+  __ StoreCompressedIntoObjectNoBarrier(
+      AllocateArrayABI::kResultReg,
+      compiler::FieldAddress(AllocateArrayABI::kResultReg,
+                             Array::type_arguments_offset()),
+      AllocateArrayABI::kTypeArgumentsReg);
+
+  // Set the length field.
+  __ StoreCompressedIntoObjectNoBarrier(
+      AllocateArrayABI::kResultReg,
+      compiler::FieldAddress(AllocateArrayABI::kResultReg,
+                             Array::length_offset()),
+      AllocateArrayABI::kLengthReg);
+
+  // Initialize all array elements to raw_null.
+  // AllocateArrayABI::kResultReg: new object start as a tagged pointer.
+  // T3: new object end address.
+  // T5: iterator which initially points to the start of the variable
+  // data area to be initialized.
+  if (num_elements > 0) {
+    const intptr_t array_size = instance_size - sizeof(UntaggedArray);
+    __ AddImmediate(T5, AllocateArrayABI::kResultReg,
+                    sizeof(UntaggedArray) - kHeapObjectTag);
+    if (array_size < (kInlineArraySize * kCompressedWordSize)) {
+      intptr_t current_offset = 0;
+      while (current_offset < array_size) {
+        __ StoreCompressedIntoObjectNoBarrier(
+            AllocateArrayABI::kResultReg, compiler::Address(T5, current_offset),
+            NULL_REG);
+        current_offset += kCompressedWordSize;
+      }
+    } else {
+      compiler::Label end_loop, init_loop;
+      __ Bind(&init_loop);
+      __ CompareRegisters(T5, T3);
+      __ BranchIf(CS, &end_loop, compiler::Assembler::kNearJump);
+      __ StoreCompressedIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
+                                            compiler::Address(T5, 0), NULL_REG);
+      __ AddImmediate(T5, kCompressedWordSize);
+      __ j(&init_loop);
+      __ Bind(&end_loop);
+    }
+  }
+  __ j(done, compiler::Assembler::kNearJump);
+}
+
+void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
+  if (type_usage_info != nullptr) {
+    const Class& list_class =
+        Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
+    RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
+                             type_arguments()->definition());
+  }
+
+  compiler::Label slow_path, done;
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
+        num_elements()->BindsToConstant() &&
+        num_elements()->BoundConstant().IsSmi()) {
+      const intptr_t length =
+          Smi::Cast(num_elements()->BoundConstant()).Value();
+      if (Array::IsValidLength(length)) {
+        InlineArrayAllocation(compiler, length, &slow_path, &done);
+      }
+    }
+  }
+
+  __ Bind(&slow_path);
+  auto object_store = compiler->isolate_group()->object_store();
+  const auto& allocate_array_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
+  compiler->GenerateStubCall(source(), allocate_array_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id(),
+                             env());
+  __ Bind(&done);
+}
+
+LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  const intptr_t kNumInputs = 1;
+  LocationSummary* locs = nullptr;
+  if (slot().representation() != kTagged) {
+    ASSERT(!calls_initializer());
+    ASSERT(RepresentationUtils::IsUnboxedInteger(slot().representation()));
+    const size_t value_size =
+        RepresentationUtils::ValueSize(slot().representation());
+
+    const intptr_t kNumTemps = 0;
+    locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::RequiresRegister());
+    if (value_size <= compiler::target::kWordSize) {
+      locs->set_out(0, Location::RequiresRegister());
+    } else {
+#if XLEN == 32
+      ASSERT(value_size <= 2 * compiler::target::kWordSize);
+      locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+#else
+      UNREACHABLE();
+#endif
+    }
+
+  } else if (IsUnboxedDartFieldLoad() && opt) {
+    ASSERT(!calls_initializer());
+    ASSERT(!slot().field().is_non_nullable_integer());
+
+    const intptr_t kNumTemps = FLAG_precompiled_mode ? 0 : 1;
+    locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::RequiresRegister());
+    if (!FLAG_precompiled_mode) {
+      locs->set_temp(0, Location::RequiresRegister());
+    }
+    locs->set_out(0, Location::RequiresFpuRegister());
+
+  } else if (IsPotentialUnboxedDartFieldLoad()) {
+    ASSERT(!calls_initializer());
+    const intptr_t kNumTemps = 1;
+    locs = new (zone) LocationSummary(zone, kNumInputs, kNumTemps,
+                                      LocationSummary::kCallOnSlowPath);
+    locs->set_in(0, Location::RequiresRegister());
+    locs->set_temp(0, Location::RequiresRegister());
+    locs->set_out(0, Location::RequiresRegister());
+
+  } else if (calls_initializer()) {
+    if (throw_exception_on_initialization()) {
+      const bool using_shared_stub = UseSharedSlowPathStub(opt);
+      const intptr_t kNumTemps = using_shared_stub ? 1 : 0;
+      locs = new (zone) LocationSummary(
+          zone, kNumInputs, kNumTemps,
+          using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
+                            : LocationSummary::kCallOnSlowPath);
+      if (using_shared_stub) {
+        locs->set_temp(0, Location::RegisterLocation(
+                              LateInitializationErrorABI::kFieldReg));
+      }
+      locs->set_in(0, Location::RequiresRegister());
+      locs->set_out(0, Location::RequiresRegister());
+    } else {
+      const intptr_t kNumTemps = 0;
+      locs = new (zone)
+          LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+      locs->set_in(
+          0, Location::RegisterLocation(InitInstanceFieldABI::kInstanceReg));
+      locs->set_out(
+          0, Location::RegisterLocation(InitInstanceFieldABI::kResultReg));
+    }
+  } else {
+    const intptr_t kNumTemps = 0;
+    locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    locs->set_in(0, Location::RequiresRegister());
+    locs->set_out(0, Location::RequiresRegister());
+  }
+  return locs;
+}
+
+void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
+
+  const Register instance_reg = locs()->in(0).reg();
+  if (slot().representation() != kTagged) {
+    auto const rep = slot().representation();
+    const size_t value_size = RepresentationUtils::ValueSize(rep);
+    __ Comment("NativeUnboxedLoadFieldInstr");
+    if (value_size <= compiler::target::kWordSize) {
+      auto const result = locs()->out(0).reg();
+      __ LoadFieldFromOffset(result, instance_reg, OffsetInBytes(),
+                             RepresentationUtils::OperandSize(rep));
+    } else {
+#if XLEN == 32
+      auto const out_pair = locs()->out(0).AsPairLocation();
+      const Register out_lo = out_pair->At(0).reg();
+      const Register out_hi = out_pair->At(1).reg();
+      const intptr_t offset_lo = OffsetInBytes() - kHeapObjectTag;
+      const intptr_t offset_hi = offset_lo + compiler::target::kWordSize;
+      __ LoadFromOffset(out_lo, instance_reg, offset_lo);
+      __ LoadFromOffset(out_hi, instance_reg, offset_hi);
+#else
+      UNREACHABLE();
+#endif
+    }
+    return;
+  }
+
+  if (IsUnboxedDartFieldLoad() && compiler->is_optimizing()) {
+    const FRegister result = locs()->out(0).fpu_reg();
+    const intptr_t cid = slot().field().UnboxedFieldCid();
+
+    if (FLAG_precompiled_mode) {
+      switch (cid) {
+        case kDoubleCid:
+          __ Comment("UnboxedDoubleLoadFieldInstr");
+          __ LoadDFieldFromOffset(result, instance_reg, OffsetInBytes());
+          return;
+        case kFloat32x4Cid:
+          __ Comment("UnboxedFloat32x4LoadFieldInstr");
+          UNIMPLEMENTED();
+          return;
+        case kFloat64x2Cid:
+          __ Comment("UnboxedFloat64x2LoadFieldInstr");
+          UNIMPLEMENTED();
+          return;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+    const Register temp = locs()->temp(0).reg();
+
+    __ LoadCompressedFieldFromOffset(temp, instance_reg, OffsetInBytes());
+    switch (cid) {
+      case kDoubleCid:
+        __ Comment("UnboxedDoubleLoadFieldInstr");
+        __ LoadDFieldFromOffset(result, temp, Double::value_offset());
+        break;
+      case kFloat32x4Cid:
+        UNIMPLEMENTED();
+        break;
+      case kFloat64x2Cid:
+        UNIMPLEMENTED();
+        break;
+      default:
+        UNREACHABLE();
+    }
+    return;
+  }
+
+  compiler::Label done;
+  const Register result_reg = locs()->out(0).reg();
+  if (IsPotentialUnboxedDartFieldLoad()) {
+    const Register temp = locs()->temp(0).reg();
+
+    compiler::Label load_pointer;
+    compiler::Label load_double;
+    compiler::Label load_float32x4;
+    compiler::Label load_float64x2;
+
+    __ LoadObject(result_reg, Field::ZoneHandle(slot().field().Original()));
+
+    compiler::FieldAddress field_cid_operand(result_reg,
+                                             Field::guarded_cid_offset());
+    compiler::FieldAddress field_nullability_operand(
+        result_reg, Field::is_nullable_offset());
+
+    __ lhu(temp, field_nullability_operand);
+    __ CompareImmediate(temp, kNullCid);
+    __ BranchIf(EQ, &load_pointer, compiler::Assembler::kNearJump);
+
+    __ lhu(temp, field_cid_operand);
+    __ CompareImmediate(temp, kDoubleCid);
+    __ BranchIf(EQ, &load_double, compiler::Assembler::kNearJump);
+
+    __ lhu(temp, field_cid_operand);
+    __ CompareImmediate(temp, kFloat32x4Cid);
+    __ BranchIf(EQ, &load_float32x4, compiler::Assembler::kNearJump);
+
+    __ lhu(temp, field_cid_operand);
+    __ CompareImmediate(temp, kFloat64x2Cid);
+    __ BranchIf(EQ, &load_float64x2, compiler::Assembler::kNearJump);
+
+    // Fall through.
+    __ j(&load_pointer);
+
+    if (!compiler->is_optimizing()) {
+      locs()->live_registers()->Add(locs()->in(0));
+    }
+
+    {
+      __ Bind(&load_double);
+      BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(),
+                                      result_reg, temp);
+      __ LoadCompressedFieldFromOffset(temp, instance_reg, OffsetInBytes());
+      __ LoadDFieldFromOffset(FTMP, temp, Double::value_offset());
+      __ StoreDFieldToOffset(FTMP, result_reg, Double::value_offset());
+      __ j(&done);
+    }
+
+    {
+      __ Bind(&load_float32x4);
+      __ ebreak();  // Unimplemented
+      __ j(&done);
+    }
+
+    {
+      __ Bind(&load_float64x2);
+      __ ebreak();  // Unimplemented
+      __ j(&done);
+    }
+
+    __ Bind(&load_pointer);
+  }
+
+  if (slot().is_compressed()) {
+    __ LoadCompressedFieldFromOffset(result_reg, instance_reg, OffsetInBytes());
+  } else {
+    __ LoadFieldFromOffset(result_reg, instance_reg, OffsetInBytes());
+  }
+
+  if (calls_initializer()) {
+    EmitNativeCodeForInitializerCall(compiler);
+  }
+
+  __ Bind(&done);
+}
+
+LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary(
+    Zone* zone,
+    bool opt) const {
+  ASSERT(opt);
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 3;
+  LocationSummary* locs = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  locs->set_temp(0, Location::RegisterLocation(T1));
+  locs->set_temp(1, Location::RegisterLocation(T2));
+  locs->set_temp(2, Location::RegisterLocation(T3));
+  locs->set_out(0, Location::RegisterLocation(A0));
+  return locs;
+}
+
+class AllocateContextSlowPath
+    : public TemplateSlowPathCode<AllocateUninitializedContextInstr> {
+ public:
+  explicit AllocateContextSlowPath(
+      AllocateUninitializedContextInstr* instruction)
+      : TemplateSlowPathCode(instruction) {}
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("AllocateContextSlowPath");
+    __ Bind(entry_label());
+
+    LocationSummary* locs = instruction()->locs();
+    locs->live_registers()->Remove(locs->out(0));
+
+    compiler->SaveLiveRegisters(locs);
+
+    auto slow_path_env = compiler->SlowPathEnvironmentFor(
+        instruction(), /*num_slow_path_args=*/0);
+    ASSERT(slow_path_env != nullptr);
+
+    auto object_store = compiler->isolate_group()->object_store();
+    const auto& allocate_context_stub = Code::ZoneHandle(
+        compiler->zone(), object_store->allocate_context_stub());
+
+    __ LoadImmediate(T1, instruction()->num_context_variables());
+    compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
+                               UntaggedPcDescriptors::kOther, locs,
+                               instruction()->deopt_id(), slow_path_env);
+    ASSERT(instruction()->locs()->out(0).reg() == A0);
+    compiler->RestoreLiveRegisters(instruction()->locs());
+    __ j(exit_label());
+  }
+};
+
+void AllocateUninitializedContextInstr::EmitNativeCode(
+    FlowGraphCompiler* compiler) {
+  Register temp0 = locs()->temp(0).reg();
+  Register temp1 = locs()->temp(1).reg();
+  Register temp2 = locs()->temp(2).reg();
+  Register result = locs()->out(0).reg();
+  // Try allocate the object.
+  AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+  intptr_t instance_size = Context::InstanceSize(num_context_variables());
+
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
+                        result,  // instance
+                        temp0, temp1, temp2);
+
+    // Setup up number of context variables field (int32_t).
+    __ LoadImmediate(temp0, num_context_variables());
+    __ sw(temp0,
+          compiler::FieldAddress(result, Context::num_variables_offset()));
+  } else {
+    __ Jump(slow_path->entry_label());
+  }
+
+  __ Bind(slow_path->exit_label());
+}
+
+LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_temp(0, Location::RegisterLocation(T1));
+  locs->set_out(0, Location::RegisterLocation(A0));
+  return locs;
+}
+
+void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(locs()->temp(0).reg() == T1);
+  ASSERT(locs()->out(0).reg() == A0);
+
+  auto object_store = compiler->isolate_group()->object_store();
+  const auto& allocate_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
+  __ LoadImmediate(T1, num_context_variables());
+  compiler->GenerateStubCall(source(), allocate_context_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id(),
+                             env());
+}
+
+LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(T5));
+  locs->set_out(0, Location::RegisterLocation(A0));
+  return locs;
+}
+
+void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(locs()->in(0).reg() == T5);
+  ASSERT(locs()->out(0).reg() == A0);
+
+  auto object_store = compiler->isolate_group()->object_store();
+  const auto& clone_context_stub =
+      Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
+  compiler->GenerateStubCall(source(), clone_context_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
+                             deopt_id(), env());
+}
+
+LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  UNREACHABLE();
+  return nullptr;
+}
+
+void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Bind(compiler->GetJumpLabel(this));
+  compiler->AddExceptionHandler(
+      catch_try_index(), try_index(), compiler->assembler()->CodeSize(),
+      is_generated(), catch_handler_types_, needs_stacktrace());
+  if (!FLAG_precompiled_mode) {
+    // On lazy deoptimization we patch the optimized code here to enter the
+    // deoptimization stub.
+    const intptr_t deopt_id = DeoptId::ToDeoptAfter(GetDeoptId());
+    if (compiler->is_optimizing()) {
+      compiler->AddDeoptIndexAtCall(deopt_id, env());
+    } else {
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id,
+                                     InstructionSource());
+    }
+  }
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
+
+  // Restore SP from FP as we are coming from a throw and the code for
+  // popping arguments has not been run.
+  const intptr_t fp_sp_dist =
+      (compiler::target::frame_layout.first_local_from_fp + 1 -
+       compiler->StackSize()) *
+      kWordSize;
+  ASSERT(fp_sp_dist <= 0);
+  __ AddImmediate(SP, FP, fp_sp_dist);
+
+  if (!compiler->is_optimizing()) {
+    if (raw_exception_var_ != nullptr) {
+      __ StoreToOffset(
+          kExceptionObjectReg, FP,
+          compiler::target::FrameOffsetInBytesForVariable(raw_exception_var_));
+    }
+    if (raw_stacktrace_var_ != nullptr) {
+      __ StoreToOffset(
+          kStackTraceObjectReg, FP,
+          compiler::target::FrameOffsetInBytesForVariable(raw_stacktrace_var_));
+    }
+  }
+}
+
+LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone,
+                                                              bool opt) const {
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 1;
+  const bool using_shared_stub = UseSharedSlowPathStub(opt);
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps,
+                      using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
+                                        : LocationSummary::kCallOnSlowPath);
+  summary->set_temp(0, Location::RequiresRegister());
+  return summary;
+}
+
+class CheckStackOverflowSlowPath
+    : public TemplateSlowPathCode<CheckStackOverflowInstr> {
+ public:
+  static constexpr intptr_t kNumSlowPathArgs = 0;
+
+  explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
+      : TemplateSlowPathCode(instruction) {}
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    auto locs = instruction()->locs();
+    if (compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
+      const Register value = locs->temp(0).reg();
+      __ Comment("CheckStackOverflowSlowPathOsr");
+      __ Bind(osr_entry_label());
+      __ li(value, Thread::kOsrRequest);
+      __ sx(value,
+            compiler::Address(THR, Thread::stack_overflow_flags_offset()));
+    }
+    __ Comment("CheckStackOverflowSlowPath");
+    __ Bind(entry_label());
+    const bool using_shared_stub = locs->call_on_shared_slow_path();
+    if (!using_shared_stub) {
+      compiler->SaveLiveRegisters(locs);
+    }
+    // pending_deoptimization_env_ is needed to generate a runtime call that
+    // may throw an exception.
+    ASSERT(compiler->pending_deoptimization_env_ == NULL);
+    Environment* env =
+        compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs);
+    compiler->pending_deoptimization_env_ = env;
+
+    if (using_shared_stub) {
+      auto object_store = compiler->isolate_group()->object_store();
+      const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
+      const auto& stub = Code::ZoneHandle(
+          compiler->zone(),
+          live_fpu_regs
+              ? object_store->stack_overflow_stub_with_fpu_regs_stub()
+              : object_store->stack_overflow_stub_without_fpu_regs_stub());
+
+      if (using_shared_stub && compiler->CanPcRelativeCall(stub)) {
+        __ GenerateUnRelocatedPcRelativeCall();
+        compiler->AddPcRelativeCallStubTarget(stub);
+      } else {
+        const uword entry_point_offset =
+            Thread::stack_overflow_shared_stub_entry_point_offset(
+                locs->live_registers()->FpuRegisterCount() > 0);
+        __ Call(compiler::Address(THR, entry_point_offset));
+      }
+      compiler->RecordSafepoint(locs, kNumSlowPathArgs);
+      compiler->RecordCatchEntryMoves(env);
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOther,
+                                     instruction()->deopt_id(),
+                                     instruction()->source());
+    } else {
+      __ CallRuntime(kStackOverflowRuntimeEntry, kNumSlowPathArgs);
+      compiler->EmitCallsiteMetadata(
+          instruction()->source(), instruction()->deopt_id(),
+          UntaggedPcDescriptors::kOther, instruction()->locs(), env);
+    }
+
+    if (compiler->isolate_group()->use_osr() && !compiler->is_optimizing() &&
+        instruction()->in_loop()) {
+      // In unoptimized code, record loop stack checks as possible OSR entries.
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
+                                     instruction()->deopt_id(),
+                                     InstructionSource());
+    }
+    compiler->pending_deoptimization_env_ = NULL;
+    if (!using_shared_stub) {
+      compiler->RestoreLiveRegisters(locs);
+    }
+    __ j(exit_label());
+  }
+
+  compiler::Label* osr_entry_label() {
+    ASSERT(IsolateGroup::Current()->use_osr());
+    return &osr_entry_label_;
+  }
+
+ private:
+  compiler::Label osr_entry_label_;
+};
+
+void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  __ lx(TMP,
+        compiler::Address(THR, compiler::target::Thread::stack_limit_offset()));
+  __ bleu(SP, TMP, slow_path->entry_label());
+  if (compiler->CanOSRFunction() && in_loop()) {
+    const Register function = locs()->temp(0).reg();
+    // In unoptimized code check the usage counter to trigger OSR at loop
+    // stack checks.  Use progressively higher thresholds for more deeply
+    // nested loops to attempt to hit outer loops with OSR when possible.
+    __ LoadObject(function, compiler->parsed_function().function());
+    intptr_t threshold =
+        FLAG_optimization_counter_threshold * (loop_depth() + 1);
+    __ LoadFieldFromOffset(TMP, function, Function::usage_counter_offset(),
+                           compiler::kFourBytes);
+    __ addi(TMP, TMP, 1);
+    __ StoreFieldToOffset(TMP, function, Function::usage_counter_offset(),
+                          compiler::kFourBytes);
+    __ CompareImmediate(TMP, threshold);
+    __ BranchIf(GE, slow_path->osr_entry_label());
+  }
+  if (compiler->ForceSlowPathForStackOverflow()) {
+    __ j(slow_path->entry_label());
+  }
+  __ Bind(slow_path->exit_label());
+}
+
+static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
+                             BinarySmiOpInstr* shift_left) {
+  const LocationSummary& locs = *shift_left->locs();
+  const Register left = locs.in(0).reg();
+  const Register result = locs.out(0).reg();
+  compiler::Label* deopt =
+      shift_left->CanDeoptimize()
+          ? compiler->AddDeoptStub(shift_left->deopt_id(),
+                                   ICData::kDeoptBinarySmiOp)
+          : NULL;
+  if (locs.in(1).IsConstant()) {
+    const Object& constant = locs.in(1).constant();
+    ASSERT(constant.IsSmi());
+    // Immediate shift operation takes 6/5 bits for the count.
+    const intptr_t kCountLimit = XLEN - 1;
+    const intptr_t value = Smi::Cast(constant).Value();
+    ASSERT((0 < value) && (value < kCountLimit));
+    __ slli(result, left, value);
+    if (shift_left->can_overflow()) {
+      ASSERT(result != left);
+      __ srai(TMP2, result, value);
+      __ bne(left, TMP2, deopt);  // Overflow.
+    }
+    return;
+  }
+
+  // Right (locs.in(1)) is not constant.
+  const Register right = locs.in(1).reg();
+  Range* right_range = shift_left->right_range();
+  if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
+    // TODO(srdjan): Implement code below for is_truncating().
+    // If left is constant, we know the maximal allowed size for right.
+    const Object& obj = shift_left->left()->BoundConstant();
+    if (obj.IsSmi()) {
+      const intptr_t left_int = Smi::Cast(obj).Value();
+      if (left_int == 0) {
+        __ bltz(right, deopt);
+        __ mv(result, ZR);
+        return;
+      }
+      const intptr_t max_right =
+          compiler::target::kSmiBits - Utils::HighestBit(left_int);
+      const bool right_needs_check =
+          !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+      if (right_needs_check) {
+        __ CompareObject(right, Smi::ZoneHandle(Smi::New(max_right)));
+        __ BranchIf(CS, deopt);
+      }
+      __ SmiUntag(TMP, right);
+      __ sll(result, left, TMP);
+    }
+    return;
+  }
+
+  const bool right_needs_check =
+      !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1));
+  if (!shift_left->can_overflow()) {
+    if (right_needs_check) {
+      if (!RangeUtils::IsPositive(right_range)) {
+        ASSERT(shift_left->CanDeoptimize());
+        __ bltz(right, deopt);
+      }
+
+      compiler::Label done, is_not_zero;
+      __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits)));
+      __ BranchIf(LESS, &is_not_zero, compiler::Assembler::kNearJump);
+      __ li(result, 0);
+      __ j(&done, compiler::Assembler::kNearJump);
+      __ Bind(&is_not_zero);
+      __ SmiUntag(TMP, right);
+      __ sll(result, left, TMP);
+      __ Bind(&done);
+    } else {
+      __ SmiUntag(TMP, right);
+      __ sll(result, left, TMP);
+    }
+  } else {
+    if (right_needs_check) {
+      ASSERT(shift_left->CanDeoptimize());
+      __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits)));
+      __ BranchIf(CS, deopt);
+    }
+    __ SmiUntag(TMP, right);
+    ASSERT(result != left);
+    __ sll(result, left, TMP);
+    __ sra(TMP, result, TMP);
+    __ bne(left, TMP, deopt);  // Overflow.
+  }
+}
+
+LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps =
+      ((op_kind() == Token::kUSHR) || (op_kind() == Token::kMUL)) ? 1 : 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  if (op_kind() == Token::kTRUNCDIV) {
+    summary->set_in(0, Location::RequiresRegister());
+    if (RightIsPowerOfTwoConstant()) {
+      ConstantInstr* right_constant = right()->definition()->AsConstant();
+      summary->set_in(1, Location::Constant(right_constant));
+    } else {
+      summary->set_in(1, Location::RequiresRegister());
+    }
+    summary->set_out(0, Location::RequiresRegister());
+    return summary;
+  }
+  if (op_kind() == Token::kMOD) {
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_in(1, Location::RequiresRegister());
+    summary->set_out(0, Location::RequiresRegister());
+    return summary;
+  }
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
+  if (kNumTemps == 1) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (op_kind() == Token::kSHL) {
+    EmitSmiShiftLeft(compiler, this);
+    return;
+  }
+
+  const Register left = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  compiler::Label* deopt = NULL;
+  if (CanDeoptimize()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
+  }
+
+  if (locs()->in(1).IsConstant()) {
+    const Object& constant = locs()->in(1).constant();
+    ASSERT(constant.IsSmi());
+    const intx_t imm = static_cast<intx_t>(constant.ptr());
+    switch (op_kind()) {
+      case Token::kADD: {
+        if (deopt == NULL) {
+          __ AddImmediate(result, left, imm);
+        } else {
+          __ AddImmediateBranchOverflow(result, left, imm, deopt);
+        }
+        break;
+      }
+      case Token::kSUB: {
+        if (deopt == NULL) {
+          __ AddImmediate(result, left, -imm);
+        } else {
+          // Negating imm and using AddImmediateSetFlags would not detect the
+          // overflow when imm == kMinInt64.
+          __ SubtractImmediateBranchOverflow(result, left, imm, deopt);
+        }
+        break;
+      }
+      case Token::kMUL: {
+        // Keep left value tagged and untag right value.
+        const intptr_t value = Smi::Cast(constant).Value();
+        if (deopt == NULL) {
+          __ LoadImmediate(TMP, value);
+          __ mul(result, left, TMP);
+        } else {
+          __ MultiplyImmediateBranchOverflow(result, left, value, deopt);
+        }
+        break;
+      }
+      case Token::kTRUNCDIV: {
+        const intptr_t value = Smi::Cast(constant).Value();
+        ASSERT(value != kIntptrMin);
+        ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
+        const intptr_t shift_count =
+            Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
+        ASSERT(kSmiTagSize == 1);
+        __ srai(TMP, left, XLEN - 1);
+        ASSERT(shift_count > 1);  // 1, -1 case handled above.
+        const Register temp = TMP2;
+        __ srli(TMP, TMP, XLEN - shift_count);
+        __ add(temp, left, TMP);
+        ASSERT(shift_count > 0);
+        __ srai(result, temp, shift_count);
+        if (value < 0) {
+          __ neg(result, result);
+        }
+        __ SmiTag(result);
+        break;
+      }
+      case Token::kBIT_AND:
+        // No overflow check.
+        __ AndImmediate(result, left, imm);
+        break;
+      case Token::kBIT_OR:
+        // No overflow check.
+        __ OrImmediate(result, left, imm);
+        break;
+      case Token::kBIT_XOR:
+        // No overflow check.
+        __ XorImmediate(result, left, imm);
+        break;
+      case Token::kSHR: {
+        // Asr operation masks the count to 6/5 bits.
+        const intptr_t kCountLimit = XLEN - 1;
+        intptr_t value = Smi::Cast(constant).Value();
+        __ srai(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit));
+        __ SmiTag(result);
+        break;
+      }
+      case Token::kUSHR: {
+#if XLEN == 32
+        const intptr_t value = compiler::target::SmiValue(constant);
+        ASSERT((value > 0) && (value < 64));
+        COMPILE_ASSERT(compiler::target::kSmiBits < 32);
+        // 64-bit representation of left operand value:
+        //
+        //       ss...sssss  s  s  xxxxxxxxxxxxx
+        //       |        |  |  |  |           |
+        //       63      32  31 30 kSmiBits-1  0
+        //
+        // Where 's' is a sign bit.
+        //
+        // If left operand is negative (sign bit is set), then
+        // result will fit into Smi range if and only if
+        // the shift amount >= 64 - kSmiBits.
+        //
+        // If left operand is non-negative, the result always
+        // fits into Smi range.
+        //
+        if (value < (64 - compiler::target::kSmiBits)) {
+          if (deopt != nullptr) {
+            __ bltz(left, deopt);
+          } else {
+            // Operation cannot overflow only if left value is always
+            // non-negative.
+            ASSERT(!can_overflow());
+          }
+          // At this point left operand is non-negative, so unsigned shift
+          // can't overflow.
+          if (value >= compiler::target::kSmiBits) {
+            __ li(result, 0);
+          } else {
+            __ srli(result, left, value + kSmiTagSize);
+            __ SmiTag(result);
+          }
+        } else {
+          // Shift amount > 32, and the result is guaranteed to fit into Smi.
+          // Low (Smi) part of the left operand is shifted out.
+          // High part is filled with sign bits.
+          __ srai(result, left, 31);
+          __ srli(result, result, value - 32);
+          __ SmiTag(result);
+        }
+#else
+        // Lsr operation masks the count to 6 bits, but
+        // unsigned shifts by >= kBitsPerInt64 are eliminated by
+        // BinaryIntegerOpInstr::Canonicalize.
+        const intptr_t kCountLimit = XLEN - 1;
+        intptr_t value = Smi::Cast(constant).Value();
+        ASSERT((value >= 0) && (value <= kCountLimit));
+        __ SmiUntag(TMP, left);
+        __ srli(TMP, TMP, value);
+        __ SmiTag(result, TMP);
+        if (deopt != nullptr) {
+          __ SmiUntag(TMP2, result);
+          __ bne(TMP, TMP2, deopt);
+        }
+#endif
+        break;
+      }
+      default:
+        UNREACHABLE();
+        break;
+    }
+    return;
+  }
+
+  const Register right = locs()->in(1).reg();
+  switch (op_kind()) {
+    case Token::kADD: {
+      if (deopt == NULL) {
+        __ add(result, left, right);
+      } else if (RangeUtils::IsPositive(right_range())) {
+        ASSERT(result != left);
+        __ add(result, left, right);
+        __ blt(result, left, deopt);
+      } else if (RangeUtils::IsNegative(right_range())) {
+        ASSERT(result != left);
+        __ add(result, left, right);
+        __ bgt(result, left, deopt);
+      } else {
+        __ AddBranchOverflow(result, left, right, deopt);
+      }
+      break;
+    }
+    case Token::kSUB: {
+      if (deopt == NULL) {
+        __ sub(result, left, right);
+      } else if (RangeUtils::IsPositive(right_range())) {
+        ASSERT(result != left);
+        __ sub(result, left, right);
+        __ bgt(result, left, deopt);
+      } else if (RangeUtils::IsNegative(right_range())) {
+        ASSERT(result != left);
+        __ sub(result, left, right);
+        __ blt(result, left, deopt);
+      } else {
+        __ SubtractBranchOverflow(result, left, right, deopt);
+      }
+      break;
+    }
+    case Token::kMUL: {
+      const Register temp = locs()->temp(0).reg();
+      __ SmiUntag(temp, left);
+      if (deopt == NULL) {
+        __ mul(result, temp, right);
+      } else {
+        __ MultiplyBranchOverflow(result, temp, right, deopt);
+      }
+      break;
+    }
+    case Token::kBIT_AND: {
+      // No overflow check.
+      __ and_(result, left, right);
+      break;
+    }
+    case Token::kBIT_OR: {
+      // No overflow check.
+      __ or_(result, left, right);
+      break;
+    }
+    case Token::kBIT_XOR: {
+      // No overflow check.
+      __ xor_(result, left, right);
+      break;
+    }
+    case Token::kTRUNCDIV: {
+      if (RangeUtils::CanBeZero(right_range())) {
+        // Handle divide by zero in runtime.
+        __ beqz(right, deopt);
+      }
+      __ SmiUntag(TMP, left);
+      __ SmiUntag(TMP2, right);
+      __ div(TMP, TMP, TMP2);
+      __ SmiTag(result, TMP);
+
+      if (RangeUtils::Overlaps(right_range(), -1, -1)) {
+        // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+        // case we cannot tag the result.
+        __ SmiUntag(TMP2, result);
+        __ bne(TMP, TMP2, deopt);
+      }
+      break;
+    }
+    case Token::kMOD: {
+      if (RangeUtils::CanBeZero(right_range())) {
+        // Handle divide by zero in runtime.
+        __ beqz(right, deopt);
+      }
+      __ SmiUntag(TMP, left);
+      __ SmiUntag(TMP2, right);
+
+      __ rem(result, TMP, TMP2);
+
+      //  res = left % right;
+      //  if (res < 0) {
+      //    if (right < 0) {
+      //      res = res - right;
+      //    } else {
+      //      res = res + right;
+      //    }
+      //  }
+      compiler::Label done, adjust;
+      __ bgez(result, &done, compiler::Assembler::kNearJump);
+      // Result is negative, adjust it.
+      __ bgez(right, &adjust, compiler::Assembler::kNearJump);
+      __ sub(result, result, TMP2);
+      __ j(&done, compiler::Assembler::kNearJump);
+      __ Bind(&adjust);
+      __ add(result, result, TMP2);
+      __ Bind(&done);
+      __ SmiTag(result);
+      break;
+    }
+    case Token::kSHR: {
+      if (CanDeoptimize()) {
+        __ bltz(right, deopt);
+      }
+      __ SmiUntag(TMP, right);
+      // asrv[w] operation masks the count to 6/5 bits.
+      const intptr_t kCountLimit = XLEN - 1;
+      if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
+        __ LoadImmediate(TMP2, kCountLimit);
+        compiler::Label shift_in_bounds;
+        __ ble(TMP, TMP2, &shift_in_bounds, compiler::Assembler::kNearJump);
+        __ mv(TMP, TMP2);
+        __ Bind(&shift_in_bounds);
+      }
+      __ SmiUntag(TMP2, left);
+      __ sra(result, TMP2, TMP);
+      __ SmiTag(result);
+      break;
+    }
+    case Token::kUSHR: {
+#if XLEN == 32
+      compiler::Label done;
+      __ SmiUntag(TMP, right);
+      // 64-bit representation of left operand value:
+      //
+      //       ss...sssss  s  s  xxxxxxxxxxxxx
+      //       |        |  |  |  |           |
+      //       63      32  31 30 kSmiBits-1  0
+      //
+      // Where 's' is a sign bit.
+      //
+      // If left operand is negative (sign bit is set), then
+      // result will fit into Smi range if and only if
+      // the shift amount >= 64 - kSmiBits.
+      //
+      // If left operand is non-negative, the result always
+      // fits into Smi range.
+      //
+      if (!RangeUtils::OnlyLessThanOrEqualTo(
+              right_range(), 64 - compiler::target::kSmiBits - 1)) {
+        if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(),
+                                               kBitsPerInt64 - 1)) {
+          ASSERT(result != left);
+          ASSERT(result != right);
+          __ li(result, 0);
+          __ CompareImmediate(TMP, kBitsPerInt64);
+          // If shift amount >= 64, then result is 0.
+          __ BranchIf(GE, &done);
+        }
+        __ CompareImmediate(TMP, 64 - compiler::target::kSmiBits);
+        // Shift amount >= 64 - kSmiBits > 32, but < 64.
+        // Result is guaranteed to fit into Smi range.
+        // Low (Smi) part of the left operand is shifted out.
+        // High part is filled with sign bits.
+        compiler::Label next;
+        __ BranchIf(LT, &next);
+        __ subi(TMP, TMP, 32);
+        __ srai(result, left, 31);
+        __ srl(result, result, TMP);
+        __ SmiTag(result);
+        __ j(&done);
+        __ Bind(&next);
+      }
+      // Shift amount < 64 - kSmiBits.
+      // If left is negative, then result will not fit into Smi range.
+      // Also deopt in case of negative shift amount.
+      if (deopt != nullptr) {
+        __ bltz(left, deopt);
+        __ bltz(right, deopt);
+      } else {
+        ASSERT(!can_overflow());
+      }
+      // At this point left operand is non-negative, so unsigned shift
+      // can't overflow.
+      if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(),
+                                             compiler::target::kSmiBits - 1)) {
+        ASSERT(result != left);
+        ASSERT(result != right);
+        __ li(result, 0);
+        __ CompareImmediate(TMP, compiler::target::kSmiBits);
+        // Left operand >= 0, shift amount >= kSmiBits. Result is 0.
+        __ BranchIf(GE, &done);
+      }
+      // Left operand >= 0, shift amount < kSmiBits < 32.
+      const Register temp = locs()->temp(0).reg();
+      __ SmiUntag(temp, left);
+      __ srl(result, temp, TMP);
+      __ SmiTag(result);
+      __ Bind(&done);
+#elif XLEN == 64
+      if (CanDeoptimize()) {
+        __ bltz(right, deopt);
+      }
+      __ SmiUntag(TMP, right);
+      // lsrv operation masks the count to 6 bits.
+      const intptr_t kCountLimit = XLEN - 1;
+      COMPILE_ASSERT(kCountLimit + 1 == kBitsPerInt64);
+      compiler::Label done;
+      if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
+        __ LoadImmediate(TMP2, kCountLimit);
+        compiler::Label shift_in_bounds;
+        __ ble(TMP, TMP2, &shift_in_bounds, compiler::Assembler::kNearJump);
+        __ mv(result, ZR);
+        __ j(&done, compiler::Assembler::kNearJump);
+        __ Bind(&shift_in_bounds);
+      }
+      __ SmiUntag(TMP2, left);
+      __ srl(TMP, TMP2, TMP);
+      __ SmiTag(result, TMP);
+      if (deopt != nullptr) {
+        __ SmiUntag(TMP2, result);
+        __ bne(TMP, TMP2, deopt);
+      }
+      __ Bind(&done);
+#else
+      UNIMPLEMENTED();
+#endif
+      break;
+    }
+    case Token::kDIV: {
+      // Dispatches to 'Double./'.
+      // TODO(srdjan): Implement as conversion to double and double division.
+      UNREACHABLE();
+      break;
+    }
+    case Token::kOR:
+    case Token::kAND: {
+      // Flow graph builder has dissected this operation to guarantee correct
+      // behavior (short-circuit evaluation).
+      UNREACHABLE();
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  return summary;
+}
+
+void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  compiler::Label* deopt =
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp,
+                             licm_hoisted_ ? ICData::kHoisted : 0);
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  if (this->left()->definition() == this->right()->definition()) {
+    __ BranchIfSmi(left, deopt);
+  } else if (left_cid == kSmiCid) {
+    __ BranchIfSmi(right, deopt);
+  } else if (right_cid == kSmiCid) {
+    __ BranchIfSmi(left, deopt);
+  } else {
+    __ or_(TMP, left, right);
+    __ BranchIfSmi(TMP, deopt);
+  }
+}
+
+LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register out_reg = locs()->out(0).reg();
+  const FRegister value = locs()->in(0).fpu_reg();
+
+  BoxAllocationSlowPath::Allocate(compiler, this,
+                                  compiler->BoxClassFor(from_representation()),
+                                  out_reg, TMP);
+
+  switch (from_representation()) {
+    case kUnboxedDouble:
+      __ StoreDFieldToOffset(value, out_reg, ValueOffset());
+      break;
+    case kUnboxedFloat:
+      __ fcvtds(FpuTMP, value);
+      __ StoreDFieldToOffset(FpuTMP, out_reg, ValueOffset());
+      break;
+    case kUnboxedFloat32x4:
+    case kUnboxedFloat64x2:
+    case kUnboxedInt32x4:
+      UNIMPLEMENTED();
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  ASSERT(!RepresentationUtils::IsUnsigned(representation()));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  const bool is_floating_point =
+      !RepresentationUtils::IsUnboxedInteger(representation());
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+
+  if (is_floating_point) {
+    summary->set_out(0, Location::RequiresFpuRegister());
+#if XLEN == 32
+  } else if (representation() == kUnboxedInt64) {
+    summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                       Location::RequiresRegister()));
+#endif
+  } else {
+    summary->set_out(0, Location::RequiresRegister());
+  }
+  return summary;
+}
+
+void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) {
+  const Register box = locs()->in(0).reg();
+
+  switch (representation()) {
+    case kUnboxedInt64: {
+#if XLEN == 32
+      PairLocation* result = locs()->out(0).AsPairLocation();
+      ASSERT(result->At(0).reg() != box);
+      __ LoadFieldFromOffset(result->At(0).reg(), box, ValueOffset());
+      __ LoadFieldFromOffset(result->At(1).reg(), box,
+                             ValueOffset() + compiler::target::kWordSize);
+#elif XLEN == 64
+      const Register result = locs()->out(0).reg();
+      __ ld(result, compiler::FieldAddress(box, ValueOffset()));
+#endif
+      break;
+    }
+
+    case kUnboxedDouble: {
+      const FRegister result = locs()->out(0).fpu_reg();
+      __ LoadDFieldFromOffset(result, box, ValueOffset());
+      break;
+    }
+
+    case kUnboxedFloat: {
+      const FRegister result = locs()->out(0).fpu_reg();
+      __ LoadDFieldFromOffset(result, box, ValueOffset());
+      __ fcvtsd(result, result);
+      break;
+    }
+
+    case kUnboxedFloat32x4:
+    case kUnboxedFloat64x2:
+    case kUnboxedInt32x4: {
+      UNIMPLEMENTED();
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) {
+  const Register box = locs()->in(0).reg();
+
+  switch (representation()) {
+#if XLEN == 32
+    case kUnboxedInt64: {
+      PairLocation* result = locs()->out(0).AsPairLocation();
+      __ SmiUntag(result->At(0).reg(), box);
+      __ srai(result->At(1).reg(), box, XLEN - 1);  // SignFill.
+      break;
+    }
+#elif XLEN == 64
+    case kUnboxedInt32:
+    case kUnboxedInt64: {
+      const Register result = locs()->out(0).reg();
+      __ SmiUntag(result, box);
+      break;
+    }
+#endif
+
+    case kUnboxedDouble: {
+      const FRegister result = locs()->out(0).fpu_reg();
+      __ SmiUntag(TMP, box);
+#if XLEN == 32
+      __ fcvtdw(result, TMP);
+#elif XLEN == 64
+      __ fcvtdl(result, TMP);
+#endif
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+void UnboxInstr::EmitLoadInt32FromBoxOrSmi(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  ASSERT(value != result);
+  compiler::Label done;
+  __ SmiUntag(result, value);
+  __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
+  __ LoadFieldFromOffset(result, value, Mint::value_offset(),
+                         compiler::kFourBytes);
+  __ Bind(&done);
+}
+
+void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  const Register box = locs()->in(0).reg();
+  PairLocation* result = locs()->out(0).AsPairLocation();
+  ASSERT(result->At(0).reg() != box);
+  ASSERT(result->At(1).reg() != box);
+  compiler::Label done;
+  __ srai(result->At(1).reg(), box, XLEN - 1);  // SignFill
+  __ SmiUntag(result->At(0).reg(), box);
+  __ BranchIfSmi(box, &done, compiler::Assembler::kNearJump);
+  EmitLoadFromBox(compiler);
+  __ Bind(&done);
+#else
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  ASSERT(value != result);
+  compiler::Label done;
+  __ SmiUntag(result, value);
+  __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
+  __ LoadFieldFromOffset(result, value, Mint::value_offset());
+  __ Bind(&done);
+#endif
+}
+
+LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  ASSERT((from_representation() == kUnboxedInt32) ||
+         (from_representation() == kUnboxedUint32));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+#if XLEN > 32
+  // ValueFitsSmi() may be overly conservative and false because we only
+  // perform range analysis during optimized compilation.
+  const bool kMayAllocateMint = false;
+#else
+  const bool kMayAllocateMint = !ValueFitsSmi();
+#endif
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps,
+                      kMayAllocateMint ? LocationSummary::kCallOnSlowPath
+                                       : LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register value = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+  ASSERT(value != out);
+
+#if XLEN > 32
+  ASSERT(compiler::target::kSmiBits >= 32);
+  __ slli(out, value, XLEN - 32);
+  if (from_representation() == kUnboxedInt32) {
+    __ srai(out, out, XLEN - 32 - kSmiTagShift);
+  } else {
+    ASSERT(from_representation() == kUnboxedUint32);
+    __ srli(out, out, XLEN - 32 - kSmiTagShift);
+  }
+#elif XLEN == 32
+  __ slli(out, value, 1);
+  if (ValueFitsSmi()) {
+    return;
+  }
+  compiler::Label done;
+  if (from_representation() == kUnboxedInt32) {
+    __ srai(TMP, out, 1);
+    __ beq(TMP, value, &done);
+  } else {
+    ASSERT(from_representation() == kUnboxedUint32);
+    __ srli(TMP, value, 30);
+    __ beqz(TMP, &done);
+  }
+
+  BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+                                  TMP);
+  __ StoreFieldToOffset(value, out, compiler::target::Mint::value_offset());
+  if (from_representation() == kUnboxedInt32) {
+    __ srai(TMP, value, 31);
+    __ StoreFieldToOffset(
+        TMP, out,
+        compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+  } else {
+    ASSERT(from_representation() == kUnboxedUint32);
+    __ StoreFieldToOffset(
+        ZR, out,
+        compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+  }
+  __ Bind(&done);
+#endif
+}
+
+LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
+                                                    bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+#if XLEN == 32
+  // Shared slow path is used in BoxInt64Instr::EmitNativeCode in
+  // FLAG_use_bare_instructions mode and only after VM isolate stubs where
+  // replaced with isolate-specific stubs.
+  auto object_store = IsolateGroup::Current()->object_store();
+  const bool stubs_in_vm_isolate =
+      object_store->allocate_mint_with_fpu_regs_stub()
+          ->untag()
+          ->InVMIsolateHeap() ||
+      object_store->allocate_mint_without_fpu_regs_stub()
+          ->untag()
+          ->InVMIsolateHeap();
+  const bool shared_slow_path_call =
+      SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      ValueFitsSmi()
+          ? LocationSummary::kNoCall
+          : ((shared_slow_path_call ? LocationSummary::kCallOnSharedSlowPath
+                                    : LocationSummary::kCallOnSlowPath)));
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  if (ValueFitsSmi()) {
+    summary->set_out(0, Location::RequiresRegister());
+  } else if (shared_slow_path_call) {
+    summary->set_out(0,
+                     Location::RegisterLocation(AllocateMintABI::kResultReg));
+  } else {
+    summary->set_out(0, Location::RequiresRegister());
+  }
+#else
+  // Shared slow path is used in BoxInt64Instr::EmitNativeCode in
+  // FLAG_use_bare_instructions mode and only after VM isolate stubs where
+  // replaced with isolate-specific stubs.
+  auto object_store = IsolateGroup::Current()->object_store();
+  const bool stubs_in_vm_isolate =
+      object_store->allocate_mint_with_fpu_regs_stub()
+          ->untag()
+          ->InVMIsolateHeap() ||
+      object_store->allocate_mint_without_fpu_regs_stub()
+          ->untag()
+          ->InVMIsolateHeap();
+  const bool shared_slow_path_call =
+      SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      ValueFitsSmi() ? LocationSummary::kNoCall
+      : shared_slow_path_call ? LocationSummary::kCallOnSharedSlowPath
+                              : LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresRegister());
+  if (ValueFitsSmi()) {
+    summary->set_out(0, Location::RequiresRegister());
+  } else if (shared_slow_path_call) {
+    summary->set_out(0,
+                     Location::RegisterLocation(AllocateMintABI::kResultReg));
+  } else {
+    summary->set_out(0, Location::RequiresRegister());
+  }
+#endif
+  return summary;
+}
+
+void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  if (ValueFitsSmi()) {
+    PairLocation* value_pair = locs()->in(0).AsPairLocation();
+    Register value_lo = value_pair->At(0).reg();
+    Register out_reg = locs()->out(0).reg();
+    __ SmiTag(out_reg, value_lo);
+    return;
+  }
+
+  PairLocation* value_pair = locs()->in(0).AsPairLocation();
+  Register value_lo = value_pair->At(0).reg();
+  Register value_hi = value_pair->At(1).reg();
+  Register out_reg = locs()->out(0).reg();
+
+  compiler::Label overflow, done;
+  __ SmiTag(out_reg, value_lo);
+  __ srai(TMP, out_reg, kSmiTagSize);
+  __ bne(value_lo, TMP, &overflow, compiler::Assembler::kNearJump);
+  __ srai(TMP, out_reg, XLEN - 1);  // SignFill
+  __ beq(value_hi, TMP, &done, compiler::Assembler::kNearJump);
+
+  __ Bind(&overflow);
+  if (compiler->intrinsic_mode()) {
+    __ TryAllocate(compiler->mint_class(),
+                   compiler->intrinsic_slow_path_label(),
+                   compiler::Assembler::kNearJump, out_reg, TMP);
+  } else if (locs()->call_on_shared_slow_path()) {
+    auto object_store = compiler->isolate_group()->object_store();
+    const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
+    const auto& stub = Code::ZoneHandle(
+        compiler->zone(),
+        live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
+                      : object_store->allocate_mint_without_fpu_regs_stub());
+
+    ASSERT(!locs()->live_registers()->ContainsRegister(
+        AllocateMintABI::kResultReg));
+    auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
+    compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
+                               locs(), DeoptId::kNone, extended_env);
+  } else {
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
+                                    out_reg, TMP);
+  }
+
+  __ StoreFieldToOffset(value_lo, out_reg,
+                        compiler::target::Mint::value_offset());
+  __ StoreFieldToOffset(
+      value_hi, out_reg,
+      compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+  __ Bind(&done);
+#else
+  Register in = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+  if (ValueFitsSmi()) {
+    __ SmiTag(out, in);
+    return;
+  }
+  ASSERT(kSmiTag == 0);
+  compiler::Label done;
+
+  ASSERT(out != in);
+  __ SmiTag(out, in);
+  __ SmiUntag(TMP, out);
+  __ beq(in, TMP, &done);  // No overflow.
+
+  if (compiler->intrinsic_mode()) {
+    __ TryAllocate(compiler->mint_class(),
+                   compiler->intrinsic_slow_path_label(),
+                   compiler::Assembler::kNearJump, out, TMP);
+  } else if (locs()->call_on_shared_slow_path()) {
+    auto object_store = compiler->isolate_group()->object_store();
+    const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
+    const auto& stub = Code::ZoneHandle(
+        compiler->zone(),
+        live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
+                      : object_store->allocate_mint_without_fpu_regs_stub());
+
+    ASSERT(!locs()->live_registers()->ContainsRegister(
+        AllocateMintABI::kResultReg));
+    auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
+    compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
+                               locs(), DeoptId::kNone, extended_env);
+  } else {
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+                                    TMP);
+  }
+
+  __ StoreToOffset(in, out, Mint::value_offset() - kHeapObjectTag);
+  __ Bind(&done);
+#endif
+}
+
+#if XLEN == 32
+static void LoadInt32FromMint(FlowGraphCompiler* compiler,
+                              Register mint,
+                              Register result,
+                              compiler::Label* deopt) {
+  __ LoadFieldFromOffset(result, mint, compiler::target::Mint::value_offset());
+  if (deopt != NULL) {
+    __ LoadFieldFromOffset(
+        TMP, mint,
+        compiler::target::Mint::value_offset() + compiler::target::kWordSize);
+    __ srai(TMP2, result, XLEN - 1);
+    __ bne(TMP, TMP2, deopt);
+  }
+}
+#endif
+
+LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  compiler::Label* deopt =
+      CanDeoptimize()
+          ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger)
+          : NULL;
+  compiler::Label* out_of_range = !is_truncating() ? deopt : NULL;
+  ASSERT(value != out);
+
+  if (value_cid == kSmiCid) {
+    __ SmiUntag(out, value);
+  } else if (value_cid == kMintCid) {
+    LoadInt32FromMint(compiler, value, out, out_of_range);
+  } else if (!CanDeoptimize()) {
+    compiler::Label done;
+    __ SmiUntag(out, value);
+    __ BranchIfSmi(value, &done);
+    LoadInt32FromMint(compiler, value, out, NULL);
+    __ Bind(&done);
+  } else {
+    compiler::Label done;
+    __ SmiUntag(out, value);
+    __ BranchIfSmi(value, &done);
+    __ CompareClassId(value, kMintCid, TMP);
+    __ BranchIf(NE, deopt);
+    LoadInt32FromMint(compiler, value, out, out_of_range);
+    __ Bind(&done);
+  }
+#elif XLEN == 64
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register out = locs()->out(0).reg();
+  const Register value = locs()->in(0).reg();
+  compiler::Label* deopt =
+      CanDeoptimize()
+          ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger)
+          : NULL;
+
+  if (value_cid == kSmiCid) {
+    __ SmiUntag(out, value);
+  } else if (value_cid == kMintCid) {
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
+  } else if (!CanDeoptimize()) {
+    // Type information is not conclusive, but range analysis found
+    // the value to be in int64 range. Therefore it must be a smi
+    // or mint value.
+    ASSERT(is_truncating());
+    compiler::Label done;
+    __ SmiUntag(out, value);
+    __ BranchIfSmi(value, &done);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
+    __ Bind(&done);
+  } else {
+    compiler::Label done;
+    __ SmiUntag(out, value);
+    __ BranchIfSmi(value, &done);
+    __ CompareClassId(value, kMintCid, TMP);
+    __ BranchIf(NE, deopt);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset());
+    __ Bind(&done);
+  }
+
+  // TODO(vegorov): as it is implemented right now truncating unboxing would
+  // leave "garbage" in the higher word.
+  if (!is_truncating() && (deopt != NULL)) {
+    ASSERT(representation() == kUnboxedInt32);
+    __ sextw(TMP, out);
+    __ bne(TMP, out, deopt);
+  }
+#endif
+}
+
+LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const FRegister left = locs()->in(0).fpu_reg();
+  const FRegister right = locs()->in(1).fpu_reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  switch (op_kind()) {
+    case Token::kADD:
+      __ faddd(result, left, right);
+      break;
+    case Token::kSUB:
+      __ fsubd(result, left, right);
+      break;
+    case Token::kMUL:
+      __ fmuld(result, left, right);
+      break;
+    case Token::kDIV:
+      __ fdivd(result, left, right);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                BranchLabels labels) {
+  ASSERT(compiler->is_optimizing());
+  const FRegister value = locs()->in(0).fpu_reg();
+
+  __ fclassd(TMP, value);
+  if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
+    __ TestImmediate(TMP, kFClassSignallingNan | kFClassQuietNan);
+  } else if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
+    __ TestImmediate(TMP, kFClassNegInfinity | kFClassPosInfinity);
+  } else {
+    UNREACHABLE();
+  }
+  return kind() == Token::kEQ ? NOT_ZERO : ZERO;
+}
+
+// SIMD
+
+#define DEFINE_EMIT(Name, Args)                                                \
+  static void Emit##Name(FlowGraphCompiler* compiler, SimdOpInstr* instr,      \
+                         PP_APPLY(PP_UNPACK, Args))
+
+#define SIMD_OP_FLOAT_ARITH(V, Name, op)                                       \
+  V(Float32x4##Name, op##s)                                                    \
+  V(Float64x2##Name, op##d)
+
+#define SIMD_OP_SIMPLE_BINARY(V)                                               \
+  SIMD_OP_FLOAT_ARITH(V, Add, vadd)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Sub, vsub)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Mul, vmul)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Div, vdiv)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Min, vmin)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Max, vmax)                                            \
+  V(Int32x4Add, vaddw)                                                         \
+  V(Int32x4Sub, vsubw)                                                         \
+  V(Int32x4BitAnd, vand)                                                       \
+  V(Int32x4BitOr, vorr)                                                        \
+  V(Int32x4BitXor, veor)                                                       \
+  V(Float32x4Equal, vceqs)                                                     \
+  V(Float32x4GreaterThan, vcgts)                                               \
+  V(Float32x4GreaterThanOrEqual, vcges)
+
+DEFINE_EMIT(SimdBinaryOp, (FRegister result, FRegister left, FRegister right)) {
+  UNIMPLEMENTED();
+}
+
+#define SIMD_OP_SIMPLE_UNARY(V)                                                \
+  SIMD_OP_FLOAT_ARITH(V, Sqrt, vsqrt)                                          \
+  SIMD_OP_FLOAT_ARITH(V, Negate, vneg)                                         \
+  SIMD_OP_FLOAT_ARITH(V, Abs, vabs)                                            \
+  V(Float32x4Reciprocal, VRecps)                                               \
+  V(Float32x4ReciprocalSqrt, VRSqrts)
+
+DEFINE_EMIT(SimdUnaryOp, (FRegister result, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4GetSignMask,
+            (Register out, FRegister value, Temp<Register> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Float32x4FromDoubles,
+    (FRegister r, FRegister v0, FRegister v1, FRegister v2, FRegister v3)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Float32x4Clamp,
+    (FRegister result, FRegister value, FRegister lower, FRegister upper)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float32x4With,
+            (FRegister result, FRegister replacement, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4ToSimd32x4, (SameAsFirstInput, FRegister value)) {
+  // TODO(dartbug.com/30949) these operations are essentially nop and should
+  // not generate any code. They should be removed from the graph before
+  // code generation.
+}
+
+DEFINE_EMIT(SimdZero, (FRegister v)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2GetSignMask, (Register out, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2With,
+            (SameAsFirstInput, FRegister left, FRegister right)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Int32x4FromInts,
+    (FRegister result, Register v0, Register v1, Register v2, Register v3)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4FromBools,
+            (FRegister result,
+             Register v0,
+             Register v1,
+             Register v2,
+             Register v3,
+             Temp<Register> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4GetFlag, (Register result, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4Select,
+            (FRegister out,
+             FRegister mask,
+             FRegister trueValue,
+             FRegister falseValue,
+             Temp<FRegister> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4WithFlag,
+            (SameAsFirstInput, FRegister mask, Register flag)) {
+  UNIMPLEMENTED();
+}
+
+// Map SimdOpInstr::Kind-s to corresponding emit functions. Uses the following
+// format:
+//
+//     CASE(OpA) CASE(OpB) ____(Emitter) - Emitter is used to emit OpA and OpB.
+//     SIMPLE(OpA) - Emitter with name OpA is used to emit OpA.
+//
+#define SIMD_OP_VARIANTS(CASE, ____)                                           \
+  SIMD_OP_SIMPLE_BINARY(CASE)                                                  \
+  CASE(Float32x4ShuffleMix)                                                    \
+  CASE(Int32x4ShuffleMix)                                                      \
+  CASE(Float32x4NotEqual)                                                      \
+  CASE(Float32x4LessThan)                                                      \
+  CASE(Float32x4LessThanOrEqual)                                               \
+  CASE(Float32x4Scale)                                                         \
+  CASE(Float64x2FromDoubles)                                                   \
+  CASE(Float64x2Scale)                                                         \
+  ____(SimdBinaryOp)                                                           \
+  SIMD_OP_SIMPLE_UNARY(CASE)                                                   \
+  CASE(Float32x4ShuffleX)                                                      \
+  CASE(Float32x4ShuffleY)                                                      \
+  CASE(Float32x4ShuffleZ)                                                      \
+  CASE(Float32x4ShuffleW)                                                      \
+  CASE(Int32x4Shuffle)                                                         \
+  CASE(Float32x4Shuffle)                                                       \
+  CASE(Float32x4Splat)                                                         \
+  CASE(Float64x2GetX)                                                          \
+  CASE(Float64x2GetY)                                                          \
+  CASE(Float64x2Splat)                                                         \
+  CASE(Float64x2ToFloat32x4)                                                   \
+  CASE(Float32x4ToFloat64x2)                                                   \
+  ____(SimdUnaryOp)                                                            \
+  CASE(Float32x4GetSignMask)                                                   \
+  CASE(Int32x4GetSignMask)                                                     \
+  ____(Simd32x4GetSignMask)                                                    \
+  CASE(Float32x4FromDoubles)                                                   \
+  ____(Float32x4FromDoubles)                                                   \
+  CASE(Float32x4Zero)                                                          \
+  CASE(Float64x2Zero)                                                          \
+  ____(SimdZero)                                                               \
+  CASE(Float32x4Clamp)                                                         \
+  ____(Float32x4Clamp)                                                         \
+  CASE(Float32x4WithX)                                                         \
+  CASE(Float32x4WithY)                                                         \
+  CASE(Float32x4WithZ)                                                         \
+  CASE(Float32x4WithW)                                                         \
+  ____(Float32x4With)                                                          \
+  CASE(Float32x4ToInt32x4)                                                     \
+  CASE(Int32x4ToFloat32x4)                                                     \
+  ____(Simd32x4ToSimd32x4)                                                     \
+  CASE(Float64x2GetSignMask)                                                   \
+  ____(Float64x2GetSignMask)                                                   \
+  CASE(Float64x2WithX)                                                         \
+  CASE(Float64x2WithY)                                                         \
+  ____(Float64x2With)                                                          \
+  CASE(Int32x4FromInts)                                                        \
+  ____(Int32x4FromInts)                                                        \
+  CASE(Int32x4FromBools)                                                       \
+  ____(Int32x4FromBools)                                                       \
+  CASE(Int32x4GetFlagX)                                                        \
+  CASE(Int32x4GetFlagY)                                                        \
+  CASE(Int32x4GetFlagZ)                                                        \
+  CASE(Int32x4GetFlagW)                                                        \
+  ____(Int32x4GetFlag)                                                         \
+  CASE(Int32x4Select)                                                          \
+  ____(Int32x4Select)                                                          \
+  CASE(Int32x4WithFlagX)                                                       \
+  CASE(Int32x4WithFlagY)                                                       \
+  CASE(Int32x4WithFlagZ)                                                       \
+  CASE(Int32x4WithFlagW)                                                       \
+  ____(Int32x4WithFlag)
+
+LocationSummary* SimdOpInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name)                                                             \
+  return MakeLocationSummaryFromEmitter(zone, this, &Emit##Name);
+    SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+    case kIllegalSimdOp:
+      UNREACHABLE();
+      break;
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name)                                                             \
+  InvokeEmitter(compiler, this, &Emit##Name);                                  \
+  break;
+    SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+    case kIllegalSimdOp:
+      UNREACHABLE();
+      break;
+  }
+}
+
+#undef DEFINE_EMIT
+
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    const FRegister val = locs()->in(0).fpu_reg();
+    const FRegister result = locs()->out(0).fpu_reg();
+    __ fsqrtd(result, val);
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    const FRegister val = locs()->in(0).fpu_reg();
+    const FRegister result = locs()->out(0).fpu_reg();
+    __ fmuld(result, val, val);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
+    Zone* zone,
+    bool opt) const {
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(A0));
+  summary->set_in(1, Location::RegisterLocation(A1));
+  summary->set_in(2, Location::RegisterLocation(A2));
+  // Can't specify A3 because it is blocked in register allocation as TMP.
+  summary->set_in(3, Location::Any());
+  summary->set_out(0, Location::RegisterLocation(A0));
+  return summary;
+}
+
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (compiler->intrinsic_mode()) {
+    // Would also need to preserve CODE_REG and ARGS_DESC_REG.
+    UNIMPLEMENTED();
+  }
+
+  if (locs()->in(3).IsRegister()) {
+    __ mv(A3, locs()->in(3).reg());
+  } else if (locs()->in(3).IsStackSlot()) {
+    __ lx(A3, LocationToStackSlotAddress(locs()->in(3)));
+  } else {
+    UNIMPLEMENTED();
+  }
+  // PP is a C volatile register.
+  // SP will be aligned to the C stack alignment.
+  __ mv(CALLEE_SAVED_TEMP, PP);
+  __ mv(CALLEE_SAVED_TEMP2, SP);
+
+  // Call the function.
+  ASSERT(TargetFunction().is_leaf());  // No deopt info needed.
+  __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
+
+  __ mv(PP, CALLEE_SAVED_TEMP);
+  __ mv(SP, CALLEE_SAVED_TEMP2);
+}
+
+LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  if (result_cid() == kDoubleCid) {
+    const intptr_t kNumInputs = 2;
+    const intptr_t kNumTemps = 0;
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresFpuRegister());
+    summary->set_in(1, Location::RequiresFpuRegister());
+    // Reuse the left register so that code can be made shorter.
+    summary->set_out(0, Location::SameAsFirstInput());
+    return summary;
+  }
+  ASSERT(result_cid() == kSmiCid);
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  // Reuse the left register so that code can be made shorter.
+  summary->set_out(0, Location::SameAsFirstInput());
+  return summary;
+}
+
+void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
+         (op_kind() == MethodRecognizer::kMathMax));
+  const bool is_min = (op_kind() == MethodRecognizer::kMathMin);
+  if (result_cid() == kDoubleCid) {
+    compiler::Label done, returns_nan, are_equal;
+    const FRegister left = locs()->in(0).fpu_reg();
+    const FRegister right = locs()->in(1).fpu_reg();
+    const FRegister result = locs()->out(0).fpu_reg();
+    if (is_min) {
+      __ fmind(result, left, right);
+    } else {
+      __ fmaxd(result, left, right);
+    }
+    return;
+  }
+
+  ASSERT(result_cid() == kSmiCid);
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  const Register result = locs()->out(0).reg();
+  compiler::Label choose_right, done;
+  if (is_min) {
+    __ bgt(left, right, &choose_right, compiler::Assembler::kNearJump);
+  } else {
+    __ blt(left, right, &choose_right, compiler::Assembler::kNearJump);
+  }
+  __ mv(result, left);
+  __ j(&done, compiler::Assembler::kNearJump);
+  __ Bind(&choose_right);
+  __ mv(result, right);
+  __ Bind(&done);
+}
+
+LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  switch (op_kind()) {
+    case Token::kNEGATE: {
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
+      __ neg(result, value);
+      ASSERT(result != value);
+      __ beq(result, value, deopt);  // Overflow.
+      break;
+    }
+    case Token::kBIT_NOT:
+      __ not_(result, value);
+      __ andi(result, result, ~kSmiTagMask);  // Remove inverted smi-tag.
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const FRegister result = locs()->out(0).fpu_reg();
+  const FRegister value = locs()->in(0).fpu_reg();
+  __ fnegd(result, value);
+}
+
+LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  __ fcvtdw(result, value);
+}
+
+LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  __ SmiUntag(TMP, value);
+#if XLEN == 32
+  __ fcvtdw(result, TMP);
+#else
+  __ fcvtdl(result, TMP);
+#endif
+}
+
+LocationSummary* Int64ToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+#if XLEN == 32
+  UNIMPLEMENTED();
+  return NULL;
+#else
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+#endif
+}
+
+void Int64ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  UNIMPLEMENTED();
+#else
+  const Register value = locs()->in(0).reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  __ fcvtdl(result, value);
+#endif
+}
+
+LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresRegister());
+  return result;
+}
+
+void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register result = locs()->out(0).reg();
+  const FRegister value_double = locs()->in(0).fpu_reg();
+
+  DoubleToIntegerSlowPath* slow_path =
+      new DoubleToIntegerSlowPath(this, value_double);
+  compiler->AddSlowPathCode(slow_path);
+
+  RoundingMode rounding;
+  switch (recognized_kind()) {
+    case MethodRecognizer::kDoubleToInteger:
+      rounding = RTZ;
+      break;
+    case MethodRecognizer::kDoubleFloorToInt:
+      rounding = RDN;
+      break;
+    case MethodRecognizer::kDoubleCeilToInt:
+      rounding = RUP;
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+#if XLEN == 32
+  __ fcvtwd(TMP, value_double, rounding);
+#else
+  __ fcvtld(TMP, value_double, rounding);
+#endif
+  // Underflow -> minint -> Smi tagging fails
+  // Overflow, NaN -> maxint -> Smi tagging fails
+
+  // Check for overflow and that it fits into Smi.
+  __ SmiTag(result, TMP);
+  __ SmiUntag(TMP2, result);
+  __ bne(TMP, TMP2, slow_path->entry_label());
+  __ Bind(slow_path->exit_label());
+}
+
+LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresRegister());
+  return result;
+}
+
+void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  compiler::Label* deopt =
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
+  const Register result = locs()->out(0).reg();
+  const FRegister value = locs()->in(0).fpu_reg();
+
+#if XLEN == 32
+  __ fcvtwd(TMP, value, RTZ);  // Round To Zero (truncation).
+#else
+  __ fcvtld(TMP, value, RTZ);  // Round To Zero (truncation).
+#endif
+  // Underflow -> minint -> Smi tagging fails
+  // Overflow, NaN -> maxint -> Smi tagging fails
+
+  // Check for overflow and that it fits into Smi.
+  __ SmiTag(result, TMP);
+  __ SmiUntag(TMP2, result);
+  __ bne(TMP, TMP2, deopt);
+}
+
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const FRegister value = locs()->in(0).fpu_reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  __ fcvtsd(result, value);
+}
+
+LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const FRegister value = locs()->in(0).fpu_reg();
+  const FRegister result = locs()->out(0).fpu_reg();
+  __ fcvtds(result, value);
+}
+
+LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
+                                                               bool opt) const {
+  ASSERT((InputCount() == 1) || (InputCount() == 2));
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
+  result->set_in(0, Location::FpuRegisterLocation(FA0));
+  if (InputCount() == 2) {
+    result->set_in(1, Location::FpuRegisterLocation(FA1));
+  }
+  result->set_out(0, Location::FpuRegisterLocation(FA0));
+  return result;
+}
+
+void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (compiler->intrinsic_mode()) {
+    // Would also need to preserve CODE_REG and ARGS_DESC_REG.
+    UNIMPLEMENTED();
+  }
+
+  // PP is a C volatile register.
+  // SP will be aligned to the C stack alignment.
+  __ mv(CALLEE_SAVED_TEMP, PP);
+  __ mv(CALLEE_SAVED_TEMP2, SP);
+
+  ASSERT(TargetFunction().is_leaf());  // No deopt info needed.
+  __ CallRuntime(TargetFunction(), InputCount());
+
+  __ mv(PP, CALLEE_SAVED_TEMP);
+  __ mv(SP, CALLEE_SAVED_TEMP2);
+
+  // TODO(riscv): Special case pow?
+}
+
+LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone,
+                                                            bool opt) const {
+  // Only use this instruction in optimized code.
+  ASSERT(opt);
+  const intptr_t kNumInputs = 1;
+  LocationSummary* summary =
+      new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
+  if (representation() == kUnboxedDouble) {
+    if (index() == 0) {
+      summary->set_in(
+          0, Location::Pair(Location::RequiresFpuRegister(), Location::Any()));
+    } else {
+      ASSERT(index() == 1);
+      summary->set_in(
+          0, Location::Pair(Location::Any(), Location::RequiresFpuRegister()));
+    }
+    summary->set_out(0, Location::RequiresFpuRegister());
+  } else {
+    ASSERT(representation() == kTagged);
+    if (index() == 0) {
+      summary->set_in(
+          0, Location::Pair(Location::RequiresRegister(), Location::Any()));
+    } else {
+      ASSERT(index() == 1);
+      summary->set_in(
+          0, Location::Pair(Location::Any(), Location::RequiresRegister()));
+    }
+    summary->set_out(0, Location::RequiresRegister());
+  }
+  return summary;
+}
+
+void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(locs()->in(0).IsPairLocation());
+  PairLocation* pair = locs()->in(0).AsPairLocation();
+  Location in_loc = pair->At(index());
+  if (representation() == kUnboxedDouble) {
+    const FRegister out = locs()->out(0).fpu_reg();
+    const FRegister in = in_loc.fpu_reg();
+    __ fmvd(out, in);
+  } else {
+    ASSERT(representation() == kTagged);
+    const Register out = locs()->out(0).reg();
+    const Register in = in_loc.reg();
+    __ mv(out, in);
+  }
+}
+
+LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
+                                                       bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  // Output is a pair of registers.
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+  return summary;
+}
+
+void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(CanDeoptimize());
+  compiler::Label* deopt =
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  ASSERT(locs()->out(0).IsPairLocation());
+  const PairLocation* pair = locs()->out(0).AsPairLocation();
+  const Register result_div = pair->At(0).reg();
+  const Register result_mod = pair->At(1).reg();
+  if (RangeUtils::CanBeZero(divisor_range())) {
+    // Handle divide by zero in runtime.
+    __ beqz(right, deopt);
+  }
+
+  __ SmiUntag(TMP, left);
+  __ SmiUntag(TMP2, right);
+
+  // Macro-op fusion: DIV immediately before REM.
+  __ div(result_div, TMP, TMP2);
+  __ rem(result_mod, TMP, TMP2);
+
+  // Correct MOD result:
+  //  res = left % right;
+  //  if (res < 0) {
+  //    if (right < 0) {
+  //      res = res - right;
+  //    } else {
+  //      res = res + right;
+  //    }
+  //  }
+  compiler::Label done, adjust;
+  __ bgez(result_mod, &done, compiler::Assembler::kNearJump);
+  // Result is negative, adjust it.
+  if (RangeUtils::IsNegative(divisor_range())) {
+    __ sub(result_mod, result_mod, TMP2);
+  } else if (RangeUtils::IsPositive(divisor_range())) {
+    __ add(result_mod, result_mod, TMP2);
+  } else {
+    __ bgez(right, &adjust, compiler::Assembler::kNearJump);
+    __ sub(result_mod, result_mod, TMP2);
+    __ j(&done, compiler::Assembler::kNearJump);
+    __ Bind(&adjust);
+    __ add(result_mod, result_mod, TMP2);
+  }
+  __ Bind(&done);
+
+  if (RangeUtils::Overlaps(divisor_range(), -1, -1)) {
+    // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+    // case we cannot tag the result.
+    __ mv(TMP, result_div);
+    __ SmiTag(result_div);
+    __ SmiTag(result_mod);
+    __ SmiUntag(TMP2, result_div);
+    __ bne(TMP, TMP2, deopt);
+  } else {
+    __ SmiTag(result_div);
+    __ SmiTag(result_mod);
+  }
+}
+
+LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  comparison()->InitializeLocationSummary(zone, opt);
+  // Branches don't produce a result.
+  comparison()->locs()->set_out(0, Location::NoLocation());
+  return comparison()->locs();
+}
+
+void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  comparison()->EmitBranchCode(compiler, this);
+}
+
+LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone,
+                                                      bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const bool need_mask_temp = IsBitTest();
+  const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  if (!IsNullCheck()) {
+    summary->set_temp(0, Location::RequiresRegister());
+    if (need_mask_temp) {
+      summary->set_temp(1, Location::RequiresRegister());
+    }
+  }
+  return summary;
+}
+
+void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler,
+                                    compiler::Label* deopt) {
+  if (IsDeoptIfNull()) {
+    __ beq(locs()->in(0).reg(), NULL_REG, deopt);
+  } else if (IsDeoptIfNotNull()) {
+    __ bne(locs()->in(0).reg(), NULL_REG, deopt);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler,
+                                  intptr_t min,
+                                  intptr_t max,
+                                  intptr_t mask,
+                                  compiler::Label* deopt) {
+  Register biased_cid = locs()->temp(0).reg();
+  __ AddImmediate(biased_cid, -min);
+  __ CompareImmediate(biased_cid, max - min);
+  __ BranchIf(HI, deopt);
+
+  Register bit_reg = locs()->temp(1).reg();
+  __ LoadImmediate(bit_reg, 1);
+  __ sll(bit_reg, bit_reg, biased_cid);
+  __ TestImmediate(bit_reg, mask);
+  __ BranchIf(EQ, deopt);
+}
+
+int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler,
+                                  int bias,
+                                  intptr_t cid_start,
+                                  intptr_t cid_end,
+                                  bool is_last,
+                                  compiler::Label* is_ok,
+                                  compiler::Label* deopt,
+                                  bool use_near_jump) {
+  Register biased_cid = locs()->temp(0).reg();
+  Condition no_match, match;
+  if (cid_start == cid_end) {
+    __ CompareImmediate(biased_cid, cid_start - bias);
+    no_match = NE;
+    match = EQ;
+  } else {
+    // For class ID ranges use a subtract followed by an unsigned
+    // comparison to check both ends of the ranges with one comparison.
+    __ AddImmediate(biased_cid, bias - cid_start);
+    bias = cid_start;
+    __ CompareImmediate(biased_cid, cid_end - cid_start);
+    no_match = HI;  // Unsigned higher.
+    match = LS;     // Unsigned lower or same.
+  }
+  if (is_last) {
+    __ BranchIf(no_match, deopt);
+  } else {
+    __ BranchIf(match, is_ok);
+  }
+  return bias;
+}
+
+LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister()
+                                         : Location::WritableRegister());
+  return summary;
+}
+
+void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register value = locs()->in(0).reg();
+  compiler::Label* deopt =
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
+  if (cids_.IsSingleCid()) {
+    __ CompareImmediate(value, Smi::RawValue(cids_.cid_start));
+    __ BranchIf(NE, deopt);
+  } else {
+    __ AddImmediate(value, -Smi::RawValue(cids_.cid_start));
+    __ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start));
+    __ BranchIf(HI, deopt);  // Unsigned higher.
+  }
+}
+
+LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone,
+                                                    bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  return summary;
+}
+
+void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register value = locs()->in(0).reg();
+  compiler::Label* deopt = compiler->AddDeoptStub(
+      deopt_id(), ICData::kDeoptCheckSmi, licm_hoisted_ ? ICData::kHoisted : 0);
+  __ BranchIfNotSmi(value, deopt);
+}
+
+void CheckNullInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ThrowErrorSlowPathCode* slow_path = new NullErrorSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  Register value_reg = locs()->in(0).reg();
+  // TODO(dartbug.com/30480): Consider passing `null` literal as an argument
+  // in order to be able to allocate it on register.
+  __ CompareObject(value_reg, Object::null_object());
+  __ BranchIf(EQUAL, slow_path->entry_label());
+}
+
+LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(kLengthPos, LocationRegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, LocationRegisterOrSmiConstant(index()));
+  return locs;
+}
+
+void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  uint32_t flags = generalized_ ? ICData::kGeneralized : 0;
+  flags |= licm_hoisted_ ? ICData::kHoisted : 0;
+  compiler::Label* deopt =
+      compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+
+  const intptr_t index_cid = index()->Type()->ToCid();
+  if (length_loc.IsConstant() && index_loc.IsConstant()) {
+    // TODO(srdjan): remove this code once failures are fixed.
+    if ((Smi::Cast(length_loc.constant()).Value() >
+         Smi::Cast(index_loc.constant()).Value()) &&
+        (Smi::Cast(index_loc.constant()).Value() >= 0)) {
+      // This CheckArrayBoundInstr should have been eliminated.
+      return;
+    }
+    ASSERT((Smi::Cast(length_loc.constant()).Value() <=
+            Smi::Cast(index_loc.constant()).Value()) ||
+           (Smi::Cast(index_loc.constant()).Value() < 0));
+    // Unconditionally deoptimize for constant bounds checks because they
+    // only occur only when index is out-of-bounds.
+    __ j(deopt);
+    return;
+  }
+
+  if (index_loc.IsConstant()) {
+    const Register length = length_loc.reg();
+    const Smi& index = Smi::Cast(index_loc.constant());
+    __ CompareObject(length, index);
+    __ BranchIf(LS, deopt);
+  } else if (length_loc.IsConstant()) {
+    const Smi& length = Smi::Cast(length_loc.constant());
+    const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
+    if (length.Value() == Smi::kMaxValue) {
+      __ bltz(index, deopt);
+    } else {
+      __ CompareObject(index, length);
+      __ BranchIf(CS, deopt);
+    }
+  } else {
+    const Register length = length_loc.reg();
+    const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
+    __ CompareObjectRegisters(index, length);
+    __ BranchIf(CS, deopt);
+  }
+}
+
+class Int64DivideSlowPath : public ThrowErrorSlowPathCode {
+ public:
+  Int64DivideSlowPath(BinaryInt64OpInstr* instruction,
+                      Register divisor,
+                      Range* divisor_range,
+                      Register tmp,
+                      Register out)
+      : ThrowErrorSlowPathCode(instruction,
+                               kIntegerDivisionByZeroExceptionRuntimeEntry),
+        is_mod_(instruction->op_kind() == Token::kMOD),
+        divisor_(divisor),
+        divisor_range_(divisor_range),
+        tmp_(tmp),
+        out_(out),
+        adjust_sign_label_() {}
+
+  void EmitNativeCode(FlowGraphCompiler* compiler) override {
+    // Handle modulo/division by zero, if needed. Use superclass code.
+    if (has_divide_by_zero()) {
+      ThrowErrorSlowPathCode::EmitNativeCode(compiler);
+    } else {
+      __ Bind(entry_label());  // not used, but keeps destructor happy
+      if (compiler::Assembler::EmittingComments()) {
+        __ Comment("slow path %s operation (no throw)", name());
+      }
+    }
+    // Adjust modulo for negative sign, optimized for known ranges.
+    // if (divisor < 0)
+    //   out -= divisor;
+    // else
+    //   out += divisor;
+    if (has_adjust_sign()) {
+      __ Bind(adjust_sign_label());
+      if (RangeUtils::Overlaps(divisor_range_, -1, 1)) {
+        // General case.
+        compiler::Label adjust, done;
+        __ bgez(divisor_, &adjust, compiler::Assembler::kNearJump);
+        __ sub(out_, out_, divisor_);
+        __ j(&done, compiler::Assembler::kNearJump);
+        __ Bind(&adjust);
+        __ add(out_, out_, divisor_);
+        __ Bind(&done);
+      } else if (divisor_range_->IsPositive()) {
+        // Always positive.
+        __ add(out_, out_, divisor_);
+      } else {
+        // Always negative.
+        __ sub(out_, out_, divisor_);
+      }
+      __ j(exit_label());
+    }
+  }
+
+  const char* name() override { return "int64 divide"; }
+
+  bool has_divide_by_zero() { return RangeUtils::CanBeZero(divisor_range_); }
+
+  bool has_adjust_sign() { return is_mod_; }
+
+  bool is_needed() { return has_divide_by_zero() || has_adjust_sign(); }
+
+  compiler::Label* adjust_sign_label() {
+    ASSERT(has_adjust_sign());
+    return &adjust_sign_label_;
+  }
+
+ private:
+  bool is_mod_;
+  Register divisor_;
+  Range* divisor_range_;
+  Register tmp_;
+  Register out_;
+  compiler::Label adjust_sign_label_;
+};
+
+#if XLEN == 64
+static void EmitInt64ModTruncDiv(FlowGraphCompiler* compiler,
+                                 BinaryInt64OpInstr* instruction,
+                                 Token::Kind op_kind,
+                                 Register left,
+                                 Register right,
+                                 Register tmp,
+                                 Register out) {
+  ASSERT(op_kind == Token::kMOD || op_kind == Token::kTRUNCDIV);
+
+  // TODO(riscv): Is it worth copying the magic constant optimization from the
+  // other architectures?
+
+  // Prepare a slow path.
+  Range* right_range = instruction->right()->definition()->range();
+  Int64DivideSlowPath* slow_path =
+      new (Z) Int64DivideSlowPath(instruction, right, right_range, tmp, out);
+
+  // Handle modulo/division by zero exception on slow path.
+  if (slow_path->has_divide_by_zero()) {
+    __ beqz(right, slow_path->entry_label());
+  }
+
+  // Perform actual operation
+  //   out = left % right
+  // or
+  //   out = left / right.
+  if (op_kind == Token::kMOD) {
+    __ rem(out, left, right);
+    // For the % operator, the rem instruction does not
+    // quite do what we want. Adjust for sign on slow path.
+    __ bltz(out, slow_path->adjust_sign_label());
+  } else {
+    __ div(out, left, right);
+  }
+
+  if (slow_path->is_needed()) {
+    __ Bind(slow_path->exit_label());
+    compiler->AddSlowPathCode(slow_path);
+  }
+}
+#endif
+
+LocationSummary* BinaryInt64OpInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+#if XLEN == 32
+  // TODO(riscv): Allow constants for the RHS of bitwise operators if both
+  // hi and lo components are IType immediates.
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+  return summary;
+#else
+  switch (op_kind()) {
+    case Token::kMOD:
+    case Token::kTRUNCDIV: {
+      const intptr_t kNumInputs = 2;
+      const intptr_t kNumTemps = (op_kind() == Token::kMOD) ? 1 : 0;
+      LocationSummary* summary = new (zone) LocationSummary(
+          zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+      summary->set_in(0, Location::RequiresRegister());
+      summary->set_in(1, Location::RequiresRegister());
+      summary->set_out(0, Location::RequiresRegister());
+      if (kNumTemps == 1) {
+        summary->set_temp(0, Location::RequiresRegister());
+      }
+      return summary;
+    }
+    default: {
+      const intptr_t kNumInputs = 2;
+      const intptr_t kNumTemps = 0;
+      LocationSummary* summary = new (zone) LocationSummary(
+          zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      summary->set_in(0, Location::RequiresRegister());
+      summary->set_in(1, LocationRegisterOrConstant(right()));
+      summary->set_out(0, Location::RequiresRegister());
+      return summary;
+    }
+  }
+#endif
+}
+
+void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* right_pair = locs()->in(1).AsPairLocation();
+  Register right_lo = right_pair->At(0).reg();
+  Register right_hi = right_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(!can_overflow());
+  ASSERT(!CanDeoptimize());
+
+  switch (op_kind()) {
+    case Token::kBIT_AND: {
+      __ and_(out_lo, left_lo, right_lo);
+      __ and_(out_hi, left_hi, right_hi);
+      break;
+    }
+    case Token::kBIT_OR: {
+      __ or_(out_lo, left_lo, right_lo);
+      __ or_(out_hi, left_hi, right_hi);
+      break;
+    }
+    case Token::kBIT_XOR: {
+      __ xor_(out_lo, left_lo, right_lo);
+      __ xor_(out_hi, left_hi, right_hi);
+      break;
+    }
+    case Token::kADD: {
+      __ add(out_hi, left_hi, right_hi);
+      __ add(out_lo, left_lo, right_lo);
+      __ sltu(TMP, out_lo, right_lo);  // Carry
+      __ add(out_hi, out_hi, TMP);
+      break;
+    }
+    case Token::kSUB: {
+      __ sltu(TMP, left_lo, right_lo);  // Borrow
+      __ sub(out_hi, left_hi, right_hi);
+      __ sub(out_hi, out_hi, TMP);
+      __ sub(out_lo, left_lo, right_lo);
+      break;
+    }
+    case Token::kMUL: {
+      // TODO(riscv): Fix ordering for macro-op fusion.
+      __ mul(out_lo, right_lo, left_hi);
+      __ mulhu(out_hi, right_lo, left_lo);
+      __ add(out_lo, out_lo, out_hi);
+      __ mul(out_hi, right_hi, left_lo);
+      __ add(out_hi, out_hi, out_lo);
+      __ mul(out_lo, right_lo, left_lo);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+#else
+  ASSERT(!can_overflow());
+  ASSERT(!CanDeoptimize());
+
+  const Register left = locs()->in(0).reg();
+  const Location right = locs()->in(1);
+  const Register out = locs()->out(0).reg();
+
+  if (op_kind() == Token::kMOD || op_kind() == Token::kTRUNCDIV) {
+    Register tmp =
+        (op_kind() == Token::kMOD) ? locs()->temp(0).reg() : kNoRegister;
+    EmitInt64ModTruncDiv(compiler, this, op_kind(), left, right.reg(), tmp,
+                         out);
+    return;
+  } else if (op_kind() == Token::kMUL) {
+    Register r = TMP;
+    if (right.IsConstant()) {
+      int64_t value;
+      const bool ok = compiler::HasIntegerValue(right.constant(), &value);
+      RELEASE_ASSERT(ok);
+      __ LoadImmediate(r, value);
+    } else {
+      r = right.reg();
+    }
+    __ mul(out, left, r);
+    return;
+  }
+
+  if (right.IsConstant()) {
+    int64_t value;
+    const bool ok = compiler::HasIntegerValue(right.constant(), &value);
+    RELEASE_ASSERT(ok);
+    switch (op_kind()) {
+      case Token::kADD:
+        __ AddImmediate(out, left, value);
+        break;
+      case Token::kSUB:
+        __ AddImmediate(out, left, -value);
+        break;
+      case Token::kBIT_AND:
+        __ AndImmediate(out, left, value);
+        break;
+      case Token::kBIT_OR:
+        __ OrImmediate(out, left, value);
+        break;
+      case Token::kBIT_XOR:
+        __ XorImmediate(out, left, value);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    switch (op_kind()) {
+      case Token::kADD:
+        __ add(out, left, right.reg());
+        break;
+      case Token::kSUB:
+        __ sub(out, left, right.reg());
+        break;
+      case Token::kBIT_AND:
+        __ and_(out, left, right.reg());
+        break;
+      case Token::kBIT_OR:
+        __ or_(out, left, right.reg());
+        break;
+      case Token::kBIT_XOR:
+        __ xor_(out, left, right.reg());
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+#endif
+}
+
+#if XLEN == 32
+static void EmitShiftInt64ByConstant(FlowGraphCompiler* compiler,
+                                     Token::Kind op_kind,
+                                     Register out_lo,
+                                     Register out_hi,
+                                     Register left_lo,
+                                     Register left_hi,
+                                     const Object& right) {
+  const int64_t shift = Integer::Cast(right).AsInt64Value();
+  ASSERT(shift >= 0);
+
+  switch (op_kind) {
+    case Token::kSHR: {
+      if (shift < 32) {
+        __ slli(out_lo, left_hi, 32 - shift);
+        __ srli(TMP, left_lo, shift);
+        __ or_(out_lo, out_lo, TMP);
+        __ srai(out_hi, left_hi, shift);
+      } else {
+        if (shift == 32) {
+          __ mv(out_lo, left_hi);
+        } else if (shift < 64) {
+          __ srai(out_lo, left_hi, shift - 32);
+        } else {
+          __ srai(out_lo, left_hi, 31);
+        }
+        __ srai(out_hi, left_hi, 31);
+      }
+      break;
+    }
+    case Token::kUSHR: {
+      ASSERT(shift < 64);
+      if (shift < 32) {
+        __ slli(out_lo, left_hi, 32 - shift);
+        __ srli(TMP, left_lo, shift);
+        __ or_(out_lo, out_lo, TMP);
+        __ srli(out_hi, left_hi, shift);
+      } else {
+        if (shift == 32) {
+          __ mv(out_lo, left_hi);
+        } else {
+          __ srli(out_lo, left_hi, shift - 32);
+        }
+        __ li(out_hi, 0);
+      }
+      break;
+    }
+    case Token::kSHL: {
+      ASSERT(shift >= 0);
+      ASSERT(shift < 64);
+      if (shift < 32) {
+        __ srli(out_hi, left_lo, 32 - shift);
+        __ slli(TMP, left_hi, shift);
+        __ or_(out_hi, out_hi, TMP);
+        __ slli(out_lo, left_lo, shift);
+      } else {
+        if (shift == 32) {
+          __ mv(out_hi, left_lo);
+        } else {
+          __ slli(out_hi, left_lo, shift - 32);
+        }
+        __ li(out_lo, 0);
+      }
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+#else
+static void EmitShiftInt64ByConstant(FlowGraphCompiler* compiler,
+                                     Token::Kind op_kind,
+                                     Register out,
+                                     Register left,
+                                     const Object& right) {
+  const int64_t shift = Integer::Cast(right).AsInt64Value();
+  ASSERT(shift >= 0);
+  switch (op_kind) {
+    case Token::kSHR: {
+      __ srai(out, left, Utils::Minimum<int64_t>(shift, XLEN - 1));
+      break;
+    }
+    case Token::kUSHR: {
+      ASSERT(shift < 64);
+      __ srli(out, left, shift);
+      break;
+    }
+    case Token::kSHL: {
+      ASSERT(shift < 64);
+      __ slli(out, left, shift);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+#endif
+
+#if XLEN == 32
+static void EmitShiftInt64ByRegister(FlowGraphCompiler* compiler,
+                                     Token::Kind op_kind,
+                                     Register out_lo,
+                                     Register out_hi,
+                                     Register left_lo,
+                                     Register left_hi,
+                                     Register right) {
+  // TODO(riscv): Review.
+  switch (op_kind) {
+    case Token::kSHR: {
+      compiler::Label big_shift, done;
+      __ li(TMP, 32);
+      __ bge(right, TMP, &big_shift, compiler::Assembler::kNearJump);
+
+      // 0 <= right < 32
+      __ srl(out_lo, left_lo, right);
+      __ sra(out_hi, left_hi, right);
+      __ beqz(right, &done, compiler::Assembler::kNearJump);
+      __ sub(TMP, TMP, right);
+      __ sll(TMP2, left_hi, TMP);
+      __ or_(out_lo, out_lo, TMP2);
+      __ j(&done);
+
+      // 32 <= right < 64
+      __ Bind(&big_shift);
+      __ sub(TMP, right, TMP);
+      __ sra(out_lo, left_hi, TMP);
+      __ srai(out_hi, left_hi, XLEN - 1);  // SignFill
+      __ Bind(&done);
+      break;
+    }
+    case Token::kUSHR: {
+      compiler::Label big_shift, done;
+      __ li(TMP, 32);
+      __ bge(right, TMP, &big_shift, compiler::Assembler::kNearJump);
+
+      // 0 <= right < 32
+      __ srl(out_lo, left_lo, right);
+      __ srl(out_hi, left_hi, right);
+      __ beqz(right, &done, compiler::Assembler::kNearJump);
+      __ sub(TMP, TMP, right);
+      __ sll(TMP2, left_hi, TMP);
+      __ or_(out_lo, out_lo, TMP2);
+      __ j(&done);
+
+      // 32 <= right < 64
+      __ Bind(&big_shift);
+      __ sub(TMP, right, TMP);
+      __ srl(out_lo, left_hi, TMP);
+      __ li(out_hi, 0);
+      __ Bind(&done);
+      break;
+    }
+    case Token::kSHL: {
+      compiler::Label big_shift, done;
+      __ li(TMP, 32);
+      __ bge(right, TMP, &big_shift, compiler::Assembler::kNearJump);
+
+      // 0 <= right < 32
+      __ sll(out_lo, left_lo, right);
+      __ sll(out_hi, left_hi, right);
+      __ beqz(right, &done, compiler::Assembler::kNearJump);
+      __ sub(TMP, TMP, right);
+      __ srl(TMP2, left_lo, TMP);
+      __ or_(out_hi, out_hi, TMP2);
+      __ j(&done);
+
+      // 32 <= right < 64
+      __ Bind(&big_shift);
+      __ sub(TMP, right, TMP);
+      __ sll(out_hi, left_lo, TMP);
+      __ li(out_lo, 0);
+      __ Bind(&done);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+#else
+static void EmitShiftInt64ByRegister(FlowGraphCompiler* compiler,
+                                     Token::Kind op_kind,
+                                     Register out,
+                                     Register left,
+                                     Register right) {
+  switch (op_kind) {
+    case Token::kSHR: {
+      __ sra(out, left, right);
+      break;
+    }
+    case Token::kUSHR: {
+      __ srl(out, left, right);
+      break;
+    }
+    case Token::kSHL: {
+      __ sll(out, left, right);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+#endif
+
+static void EmitShiftUint32ByConstant(FlowGraphCompiler* compiler,
+                                      Token::Kind op_kind,
+                                      Register out,
+                                      Register left,
+                                      const Object& right) {
+  const int64_t shift = Integer::Cast(right).AsInt64Value();
+  ASSERT(shift >= 0);
+  if (shift >= 32) {
+    __ li(out, 0);
+  } else {
+    switch (op_kind) {
+      case Token::kSHR:
+      case Token::kUSHR:
+#if XLEN == 32
+        __ srli(out, left, shift);
+#else
+        __ srliw(out, left, shift);
+#endif
+        break;
+      case Token::kSHL:
+#if XLEN == 32
+        __ slli(out, left, shift);
+#else
+        __ slliw(out, left, shift);
+#endif
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+}
+
+static void EmitShiftUint32ByRegister(FlowGraphCompiler* compiler,
+                                      Token::Kind op_kind,
+                                      Register out,
+                                      Register left,
+                                      Register right) {
+  switch (op_kind) {
+    case Token::kSHR:
+    case Token::kUSHR:
+#if XLEN == 32
+      __ srl(out, left, right);
+#else
+      __ srlw(out, left, right);
+#endif
+      break;
+    case Token::kSHL:
+#if XLEN == 32
+      __ sll(out, left, right);
+#else
+      __ sllw(out, left, right);
+#endif
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+class ShiftInt64OpSlowPath : public ThrowErrorSlowPathCode {
+ public:
+  explicit ShiftInt64OpSlowPath(ShiftInt64OpInstr* instruction)
+      : ThrowErrorSlowPathCode(instruction,
+                               kArgumentErrorUnboxedInt64RuntimeEntry) {}
+
+  const char* name() override { return "int64 shift"; }
+
+  void EmitCodeAtSlowPathEntry(FlowGraphCompiler* compiler) override {
+#if XLEN == 32
+    PairLocation* left_pair = instruction()->locs()->in(0).AsPairLocation();
+    Register left_hi = left_pair->At(1).reg();
+    PairLocation* right_pair = instruction()->locs()->in(1).AsPairLocation();
+    Register right_lo = right_pair->At(0).reg();
+    Register right_hi = right_pair->At(1).reg();
+    PairLocation* out_pair = instruction()->locs()->out(0).AsPairLocation();
+    Register out_lo = out_pair->At(0).reg();
+    Register out_hi = out_pair->At(1).reg();
+
+    compiler::Label throw_error;
+    __ bltz(right_hi, &throw_error);
+
+    switch (instruction()->AsShiftInt64Op()->op_kind()) {
+      case Token::kSHR:
+        __ srai(out_hi, left_hi, compiler::target::kBitsPerWord - 1);
+        __ mv(out_lo, out_hi);
+        break;
+      case Token::kUSHR:
+      case Token::kSHL: {
+        __ li(out_lo, 0);
+        __ li(out_hi, 0);
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+
+    __ j(exit_label());
+
+    __ Bind(&throw_error);
+
+    // Can't pass unboxed int64 value directly to runtime call, as all
+    // arguments are expected to be tagged (boxed).
+    // The unboxed int64 argument is passed through a dedicated slot in Thread.
+    // TODO(dartbug.com/33549): Clean this up when unboxed values
+    // could be passed as arguments.
+    __ StoreToOffset(
+        right_lo, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset());
+    __ StoreToOffset(
+        right_hi, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset() +
+            compiler::target::kWordSize);
+#else
+    const Register left = instruction()->locs()->in(0).reg();
+    const Register right = instruction()->locs()->in(1).reg();
+    const Register out = instruction()->locs()->out(0).reg();
+    ASSERT((out != left) && (out != right));
+
+    compiler::Label throw_error;
+    __ bltz(right, &throw_error);
+
+    switch (instruction()->AsShiftInt64Op()->op_kind()) {
+      case Token::kSHR:
+        __ srai(out, left, XLEN - 1);
+        break;
+      case Token::kUSHR:
+      case Token::kSHL:
+        __ mv(out, ZR);
+        break;
+      default:
+        UNREACHABLE();
+    }
+    __ j(exit_label());
+
+    __ Bind(&throw_error);
+
+    // Can't pass unboxed int64 value directly to runtime call, as all
+    // arguments are expected to be tagged (boxed).
+    // The unboxed int64 argument is passed through a dedicated slot in Thread.
+    // TODO(dartbug.com/33549): Clean this up when unboxed values
+    // could be passed as arguments.
+    __ sx(right,
+          compiler::Address(THR, Thread::unboxed_int64_runtime_arg_offset()));
+#endif
+  }
+};
+
+LocationSummary* ShiftInt64OpInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+#if XLEN == 32
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  if (RangeUtils::IsPositive(shift_range()) &&
+      right()->definition()->IsConstant()) {
+    ConstantInstr* constant = right()->definition()->AsConstant();
+    summary->set_in(1, Location::Constant(constant));
+  } else {
+    summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+  }
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+#else
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, RangeUtils::IsPositive(shift_range())
+                         ? LocationRegisterOrConstant(right())
+                         : Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+#endif
+  return summary;
+}
+
+void ShiftInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(!can_overflow());
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftInt64ByConstant(compiler, op_kind(), out_lo, out_hi, left_lo,
+                             left_hi, locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount (or constant that throws).
+    PairLocation* right_pair = locs()->in(1).AsPairLocation();
+    Register right_lo = right_pair->At(0).reg();
+    Register right_hi = right_pair->At(1).reg();
+
+    // Jump to a slow path if shift is larger than 63 or less than 0.
+    ShiftInt64OpSlowPath* slow_path = NULL;
+    if (!IsShiftCountInRange()) {
+      slow_path = new (Z) ShiftInt64OpSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+      __ CompareImmediate(right_hi, 0);
+      __ BranchIf(NE, slow_path->entry_label());
+      __ CompareImmediate(right_lo, kShiftCountLimit);
+      __ BranchIf(HI, slow_path->entry_label());
+    }
+
+    EmitShiftInt64ByRegister(compiler, op_kind(), out_lo, out_hi, left_lo,
+                             left_hi, right_lo);
+
+    if (slow_path != NULL) {
+      __ Bind(slow_path->exit_label());
+    }
+  }
+#else
+  const Register left = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  ASSERT(!can_overflow());
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftInt64ByConstant(compiler, op_kind(), out, left,
+                             locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount (or constant that throws).
+    Register shift = locs()->in(1).reg();
+
+    // Jump to a slow path if shift is larger than 63 or less than 0.
+    ShiftInt64OpSlowPath* slow_path = NULL;
+    if (!IsShiftCountInRange()) {
+      slow_path = new (Z) ShiftInt64OpSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+      __ CompareImmediate(shift, kShiftCountLimit);
+      __ BranchIf(HI, slow_path->entry_label());
+    }
+
+    EmitShiftInt64ByRegister(compiler, op_kind(), out, left, shift);
+
+    if (slow_path != NULL) {
+      __ Bind(slow_path->exit_label());
+    }
+  }
+#endif
+}
+
+LocationSummary* SpeculativeShiftInt64OpInstr::MakeLocationSummary(
+    Zone* zone,
+    bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+#if XLEN == 32
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_in(1, LocationWritableRegisterOrSmiConstant(right()));
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+#else
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
+  summary->set_out(0, Location::RequiresRegister());
+#endif
+  return summary;
+}
+
+void SpeculativeShiftInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(!can_overflow());
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftInt64ByConstant(compiler, op_kind(), out_lo, out_hi, left_lo,
+                             left_hi, locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount.
+    Register shift = locs()->in(1).reg();
+    __ SmiUntag(shift);
+
+    // Deopt if shift is larger than 63 or less than 0 (or not a smi).
+    if (!IsShiftCountInRange()) {
+      ASSERT(CanDeoptimize());
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+
+      __ CompareImmediate(shift, kShiftCountLimit);
+      __ BranchIf(HI, deopt);
+    }
+
+    EmitShiftInt64ByRegister(compiler, op_kind(), out_lo, out_hi, left_lo,
+                             left_hi, shift);
+  }
+#else
+  const Register left = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  ASSERT(!can_overflow());
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftInt64ByConstant(compiler, op_kind(), out, left,
+                             locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount.
+    Register shift = locs()->in(1).reg();
+
+    // Untag shift count.
+    __ SmiUntag(TMP, shift);
+    shift = TMP;
+
+    // Deopt if shift is larger than 63 or less than 0 (or not a smi).
+    if (!IsShiftCountInRange()) {
+      ASSERT(CanDeoptimize());
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+
+      __ CompareImmediate(shift, kShiftCountLimit);
+      __ BranchIf(HI, deopt);
+    }
+
+    EmitShiftInt64ByRegister(compiler, op_kind(), out, left, shift);
+  }
+#endif
+}
+
+class ShiftUint32OpSlowPath : public ThrowErrorSlowPathCode {
+ public:
+  explicit ShiftUint32OpSlowPath(ShiftUint32OpInstr* instruction)
+      : ThrowErrorSlowPathCode(instruction,
+                               kArgumentErrorUnboxedInt64RuntimeEntry) {}
+
+  const char* name() override { return "uint32 shift"; }
+
+  void EmitCodeAtSlowPathEntry(FlowGraphCompiler* compiler) override {
+#if XLEN == 32
+    PairLocation* right_pair = instruction()->locs()->in(1).AsPairLocation();
+    Register right_lo = right_pair->At(0).reg();
+    Register right_hi = right_pair->At(1).reg();
+    Register out = instruction()->locs()->out(0).reg();
+
+    compiler::Label throw_error;
+    __ bltz(right_hi, &throw_error, compiler::Assembler::kNearJump);
+    __ li(out, 0);
+    __ j(exit_label());
+
+    __ Bind(&throw_error);
+    // Can't pass unboxed int64 value directly to runtime call, as all
+    // arguments are expected to be tagged (boxed).
+    // The unboxed int64 argument is passed through a dedicated slot in Thread.
+    // TODO(dartbug.com/33549): Clean this up when unboxed values
+    // could be passed as arguments.
+    __ StoreToOffset(
+        right_lo, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset());
+    __ StoreToOffset(
+        right_hi, THR,
+        compiler::target::Thread::unboxed_int64_runtime_arg_offset() +
+            compiler::target::kWordSize);
+#else
+    const Register right = instruction()->locs()->in(1).reg();
+
+    // Can't pass unboxed int64 value directly to runtime call, as all
+    // arguments are expected to be tagged (boxed).
+    // The unboxed int64 argument is passed through a dedicated slot in Thread.
+    // TODO(dartbug.com/33549): Clean this up when unboxed values
+    // could be passed as arguments.
+    __ sx(right,
+          compiler::Address(THR, Thread::unboxed_int64_runtime_arg_offset()));
+#endif
+  }
+};
+
+LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresRegister());
+  if (RangeUtils::IsPositive(shift_range()) &&
+      right()->definition()->IsConstant()) {
+    ConstantInstr* constant = right()->definition()->AsConstant();
+    summary->set_in(1, Location::Constant(constant));
+  } else {
+#if XLEN == 32
+    summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+#else
+    summary->set_in(1, Location::RequiresRegister());
+#endif
+  }
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  Register left = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+
+  ASSERT(left != out);
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftUint32ByConstant(compiler, op_kind(), out, left,
+                              locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount (or constant that throws).
+    PairLocation* right_pair = locs()->in(1).AsPairLocation();
+    Register right_lo = right_pair->At(0).reg();
+    Register right_hi = right_pair->At(1).reg();
+
+    // Jump to a slow path if shift count is > 31 or negative.
+    ShiftUint32OpSlowPath* slow_path = NULL;
+    if (!IsShiftCountInRange(kUint32ShiftCountLimit)) {
+      slow_path = new (Z) ShiftUint32OpSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ CompareImmediate(right_hi, 0);
+      __ BranchIf(NE, slow_path->entry_label());
+      __ CompareImmediate(right_lo, kUint32ShiftCountLimit);
+      __ BranchIf(HI, slow_path->entry_label());
+    }
+
+    EmitShiftUint32ByRegister(compiler, op_kind(), out, left, right_lo);
+
+    if (slow_path != NULL) {
+      __ Bind(slow_path->exit_label());
+    }
+  }
+#else
+  Register left = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftUint32ByConstant(compiler, op_kind(), out, left,
+                              locs()->in(1).constant());
+  } else {
+    // Code for a variable shift amount (or constant that throws).
+    const Register right = locs()->in(1).reg();
+    const bool shift_count_in_range =
+        IsShiftCountInRange(kUint32ShiftCountLimit);
+
+    // Jump to a slow path if shift count is negative.
+    if (!shift_count_in_range) {
+      ShiftUint32OpSlowPath* slow_path = new (Z) ShiftUint32OpSlowPath(this);
+      compiler->AddSlowPathCode(slow_path);
+
+      __ bltz(right, slow_path->entry_label());
+    }
+
+    EmitShiftUint32ByRegister(compiler, op_kind(), out, left, right);
+
+    if (!shift_count_in_range) {
+      // If shift value is > 31, return zero.
+      compiler::Label done;
+      __ CompareImmediate(right, 31);
+      __ BranchIf(LE, &done, compiler::Assembler::kNearJump);
+      __ li(out, 0);
+      __ Bind(&done);
+    }
+  }
+#endif
+}
+
+LocationSummary* SpeculativeShiftUint32OpInstr::MakeLocationSummary(
+    Zone* zone,
+    bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void SpeculativeShiftUint32OpInstr::EmitNativeCode(
+    FlowGraphCompiler* compiler) {
+  Register left = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+
+  if (locs()->in(1).IsConstant()) {
+    EmitShiftUint32ByConstant(compiler, op_kind(), out, left,
+                              locs()->in(1).constant());
+  } else {
+    Register right = locs()->in(1).reg();
+    const bool shift_count_in_range =
+        IsShiftCountInRange(kUint32ShiftCountLimit);
+
+    __ SmiUntag(TMP, right);
+    right = TMP;
+
+    // Jump to a slow path if shift count is negative.
+    if (!shift_count_in_range) {
+      // Deoptimize if shift count is negative.
+      ASSERT(CanDeoptimize());
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+
+      __ bltz(right, deopt);
+    }
+
+    EmitShiftUint32ByRegister(compiler, op_kind(), out, left, right);
+
+    if (!shift_count_in_range) {
+      // If shift value is > 31, return zero.
+      compiler::Label done;
+      __ CompareImmediate(right, 31);
+      __ BranchIf(LE, &done, compiler::Assembler::kNearJump);
+      __ li(out, 0);
+      __ Bind(&done);
+    }
+  }
+}
+
+LocationSummary* UnaryInt64OpInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+#if XLEN == 32
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
+  return summary;
+#else
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+#endif
+}
+
+void UnaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+
+  switch (op_kind()) {
+    case Token::kBIT_NOT:
+      __ not_(out_lo, left_lo);
+      __ not_(out_hi, left_hi);
+      break;
+    case Token::kNEGATE:
+      __ snez(TMP, left_lo);  // Borrow
+      __ neg(out_lo, left_lo);
+      __ neg(out_hi, left_hi);
+      __ sub(out_hi, out_hi, TMP);
+      break;
+    default:
+      UNREACHABLE();
+  }
+#else
+  const Register left = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  switch (op_kind()) {
+    case Token::kBIT_NOT:
+      __ not_(out, left);
+      break;
+    case Token::kNEGATE:
+      __ neg(out, left);
+      break;
+    default:
+      UNREACHABLE();
+  }
+#endif
+}
+
+LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register left = locs()->in(0).reg();
+  Register right = locs()->in(1).reg();
+  Register out = locs()->out(0).reg();
+  switch (op_kind()) {
+    case Token::kBIT_AND:
+      __ and_(out, left, right);
+      break;
+    case Token::kBIT_OR:
+      __ or_(out, left, right);
+      break;
+    case Token::kBIT_XOR:
+      __ xor_(out, left, right);
+      break;
+    case Token::kADD:
+#if XLEN == 32
+      __ add(out, left, right);
+#elif XLEN > 32
+      __ addw(out, left, right);
+#endif
+      break;
+    case Token::kSUB:
+#if XLEN == 32
+      __ sub(out, left, right);
+#elif XLEN > 32
+      __ subw(out, left, right);
+#endif
+      break;
+    case Token::kMUL:
+      __ mul(out, left, right);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register left = locs()->in(0).reg();
+  Register out = locs()->out(0).reg();
+
+  ASSERT(op_kind() == Token::kBIT_NOT);
+  __ not_(out, left);
+}
+
+#if XLEN == 32
+static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler,
+                               BinaryInt32OpInstr* shift_left) {
+  const LocationSummary& locs = *shift_left->locs();
+  const Register left = locs.in(0).reg();
+  const Register result = locs.out(0).reg();
+  compiler::Label* deopt =
+      shift_left->CanDeoptimize()
+          ? compiler->AddDeoptStub(shift_left->deopt_id(),
+                                   ICData::kDeoptBinarySmiOp)
+          : NULL;
+  ASSERT(locs.in(1).IsConstant());
+  const Object& constant = locs.in(1).constant();
+  ASSERT(compiler::target::IsSmi(constant));
+  // Immediate shift operation takes 5 bits for the count.
+  const intptr_t kCountLimit = 0x1F;
+  const intptr_t value = compiler::target::SmiValue(constant);
+  ASSERT((0 < value) && (value < kCountLimit));
+  __ slli(result, left, value);
+  if (shift_left->can_overflow()) {
+    __ srai(TMP, result, value);
+    __ bne(TMP, left, deopt);  // Overflow.
+  }
+}
+
+LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 2;
+  // Calculate number of temporaries.
+  intptr_t num_temps = 0;
+  if (((op_kind() == Token::kSHL) && can_overflow()) ||
+      (op_kind() == Token::kSHR) || (op_kind() == Token::kUSHR) ||
+      (op_kind() == Token::kMUL)) {
+    num_temps = 1;
+  }
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
+  if (num_temps == 1) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  // We make use of 3-operand instructions by not requiring result register
+  // to be identical to first input register as on Intel.
+  summary->set_out(0, Location::RequiresRegister());
+  return summary;
+}
+
+void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (op_kind() == Token::kSHL) {
+    EmitInt32ShiftLeft(compiler, this);
+    return;
+  }
+
+  const Register left = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  compiler::Label* deopt = NULL;
+  if (CanDeoptimize()) {
+    deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
+  }
+
+  if (locs()->in(1).IsConstant()) {
+    const Object& constant = locs()->in(1).constant();
+    ASSERT(compiler::target::IsSmi(constant));
+    const intptr_t value = compiler::target::SmiValue(constant);
+    switch (op_kind()) {
+      case Token::kADD: {
+        if (deopt == NULL) {
+          __ AddImmediate(result, left, value);
+        } else {
+          __ AddImmediateBranchOverflow(result, left, value, deopt);
+        }
+        break;
+      }
+      case Token::kSUB: {
+        if (deopt == NULL) {
+          __ AddImmediate(result, left, -value);
+        } else {
+          // Negating value and using AddImmediateSetFlags would not detect the
+          // overflow when value == kMinInt32.
+          __ SubtractImmediateBranchOverflow(result, left, value, deopt);
+        }
+        break;
+      }
+      case Token::kMUL: {
+        const Register right = locs()->temp(0).reg();
+        __ LoadImmediate(right, value);
+        if (deopt == NULL) {
+          __ mul(result, left, right);
+        } else {
+          __ MultiplyBranchOverflow(result, left, right, deopt);
+        }
+        break;
+      }
+      case Token::kBIT_AND: {
+        // No overflow check.
+        __ AndImmediate(result, left, value);
+        break;
+      }
+      case Token::kBIT_OR: {
+        // No overflow check.
+        __ OrImmediate(result, left, value);
+        break;
+      }
+      case Token::kBIT_XOR: {
+        // No overflow check.
+        __ XorImmediate(result, left, value);
+        break;
+      }
+      case Token::kSHR: {
+        // sarl operation masks the count to 5 bits.
+        const intptr_t kCountLimit = 0x1F;
+        __ srai(result, left, Utils::Minimum(value, kCountLimit));
+        break;
+      }
+      case Token::kUSHR: {
+        UNIMPLEMENTED();
+        break;
+      }
+
+      default:
+        UNREACHABLE();
+        break;
+    }
+    return;
+  }
+
+  const Register right = locs()->in(1).reg();
+  switch (op_kind()) {
+    case Token::kADD: {
+      if (deopt == NULL) {
+        __ add(result, left, right);
+      } else {
+        __ AddBranchOverflow(result, left, right, deopt);
+      }
+      break;
+    }
+    case Token::kSUB: {
+      if (deopt == NULL) {
+        __ sub(result, left, right);
+      } else {
+        __ SubtractBranchOverflow(result, left, right, deopt);
+      }
+      break;
+    }
+    case Token::kMUL: {
+      if (deopt == NULL) {
+        __ mul(result, left, right);
+      } else {
+        __ MultiplyBranchOverflow(result, left, right, deopt);
+      }
+      break;
+    }
+    case Token::kBIT_AND: {
+      // No overflow check.
+      __ and_(result, left, right);
+      break;
+    }
+    case Token::kBIT_OR: {
+      // No overflow check.
+      __ or_(result, left, right);
+      break;
+    }
+    case Token::kBIT_XOR: {
+      // No overflow check.
+      __ xor_(result, left, right);
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+#else
+DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr)
+#endif
+
+LocationSummary* IntConverterInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+#if XLEN == 32
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  if (from() == kUntagged || to() == kUntagged) {
+    ASSERT((from() == kUntagged && to() == kUnboxedInt32) ||
+           (from() == kUntagged && to() == kUnboxedUint32) ||
+           (from() == kUnboxedInt32 && to() == kUntagged) ||
+           (from() == kUnboxedUint32 && to() == kUntagged));
+    ASSERT(!CanDeoptimize());
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_out(0, Location::SameAsFirstInput());
+  } else if (from() == kUnboxedInt64) {
+    ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+    summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+    summary->set_out(0, Location::RequiresRegister());
+  } else if (to() == kUnboxedInt64) {
+    ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32);
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                       Location::RequiresRegister()));
+  } else {
+    ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+    ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32);
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_out(0, Location::SameAsFirstInput());
+  }
+  return summary;
+#else
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  if (from() == kUntagged || to() == kUntagged) {
+    ASSERT((from() == kUntagged && to() == kUnboxedIntPtr) ||
+           (from() == kUnboxedIntPtr && to() == kUntagged));
+    ASSERT(!CanDeoptimize());
+  } else if (from() == kUnboxedInt64) {
+    ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+  } else if (to() == kUnboxedInt64) {
+    ASSERT(from() == kUnboxedInt32 || from() == kUnboxedUint32);
+  } else {
+    ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+    ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32);
+  }
+  summary->set_in(0, Location::RequiresRegister());
+  if (CanDeoptimize()) {
+    summary->set_out(0, Location::RequiresRegister());
+  } else {
+    summary->set_out(0, Location::SameAsFirstInput());
+  }
+  return summary;
+#endif
+}
+
+void IntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if XLEN == 32
+  const bool is_nop_conversion =
+      (from() == kUntagged && to() == kUnboxedInt32) ||
+      (from() == kUntagged && to() == kUnboxedUint32) ||
+      (from() == kUnboxedInt32 && to() == kUntagged) ||
+      (from() == kUnboxedUint32 && to() == kUntagged);
+  if (is_nop_conversion) {
+    ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
+    return;
+  }
+
+  if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
+    const Register out = locs()->out(0).reg();
+    // Representations are bitwise equivalent.
+    ASSERT(out == locs()->in(0).reg());
+  } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
+    const Register out = locs()->out(0).reg();
+    // Representations are bitwise equivalent.
+    ASSERT(out == locs()->in(0).reg());
+    if (CanDeoptimize()) {
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+      __ bltz(out, deopt);
+    }
+  } else if (from() == kUnboxedInt64) {
+    ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+    PairLocation* in_pair = locs()->in(0).AsPairLocation();
+    Register in_lo = in_pair->At(0).reg();
+    Register in_hi = in_pair->At(1).reg();
+    Register out = locs()->out(0).reg();
+    // Copy low word.
+    __ mv(out, in_lo);
+    if (CanDeoptimize()) {
+      compiler::Label* deopt =
+          compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+      ASSERT(to() == kUnboxedInt32);
+      __ srai(TMP, in_lo, XLEN - 1);
+      __ bne(in_hi, TMP, deopt);
+    }
+  } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) {
+    ASSERT(to() == kUnboxedInt64);
+    Register in = locs()->in(0).reg();
+    PairLocation* out_pair = locs()->out(0).AsPairLocation();
+    Register out_lo = out_pair->At(0).reg();
+    Register out_hi = out_pair->At(1).reg();
+    // Copy low word.
+    __ mv(out_lo, in);
+    if (from() == kUnboxedUint32) {
+      __ li(out_hi, 0);
+    } else {
+      ASSERT(from() == kUnboxedInt32);
+      __ srai(out_hi, in, XLEN - 1);
+    }
+  } else {
+    UNREACHABLE();
+  }
+#else
+  ASSERT(from() != to());  // We don't convert from a representation to itself.
+
+  const bool is_nop_conversion =
+      (from() == kUntagged && to() == kUnboxedIntPtr) ||
+      (from() == kUnboxedIntPtr && to() == kUntagged);
+  if (is_nop_conversion) {
+    ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
+    return;
+  }
+
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  compiler::Label* deopt =
+      !CanDeoptimize()
+          ? NULL
+          : compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+  if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
+    if (CanDeoptimize()) {
+      __ slli(TMP, value, 32);
+      __ bltz(TMP, deopt);  // If sign bit is set it won't fit in a uint32.
+    }
+    if (out != value) {
+      __ mv(out, value);  // For positive values the bits are the same.
+    }
+  } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
+    if (CanDeoptimize()) {
+      __ slli(TMP, value, 32);
+      __ bltz(TMP, deopt);  // If high bit is set it won't fit in an int32.
+    }
+    if (out != value) {
+      __ mv(out, value);  // For 31 bit values the bits are the same.
+    }
+  } else if (from() == kUnboxedInt64) {
+    if (to() == kUnboxedInt32) {
+      if (is_truncating() || out != value) {
+        __ sextw(out, value);  // Signed extension 64->32.
+      }
+    } else {
+      ASSERT(to() == kUnboxedUint32);
+      if (is_truncating() || out != value) {
+        // Unsigned extension 64->32.
+        // TODO(riscv): Might be a shorter way to do this.
+        __ slli(out, value, 32);
+        __ srli(out, out, 32);
+      }
+    }
+    if (CanDeoptimize()) {
+      ASSERT(to() == kUnboxedInt32);
+      __ CompareRegisters(out, value);
+      __ BranchIf(NE, deopt);  // Value cannot be held in Int32, deopt.
+    }
+  } else if (to() == kUnboxedInt64) {
+    if (from() == kUnboxedUint32) {
+      // TODO(riscv): Might be a shorter way to do this.
+      __ slli(out, value, 32);
+      __ srli(out, out, 32);
+    } else {
+      ASSERT(from() == kUnboxedInt32);
+      __ sextw(out, value);  // Signed extension 32->64.
+    }
+  } else {
+    UNREACHABLE();
+  }
+#endif
+}
+
+LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  LocationSummary* summary =
+      new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+                                 /*num_temps=*/0, LocationSummary::kNoCall);
+  switch (from()) {
+    case kUnboxedInt32:
+      summary->set_in(0, Location::RequiresRegister());
+      break;
+    case kUnboxedInt64:
+#if XLEN == 32
+      summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                        Location::RequiresRegister()));
+#else
+      summary->set_in(0, Location::RequiresRegister());
+#endif
+      break;
+    case kUnboxedFloat:
+    case kUnboxedDouble:
+      summary->set_in(0, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  switch (to()) {
+    case kUnboxedInt32:
+      summary->set_out(0, Location::RequiresRegister());
+      break;
+    case kUnboxedInt64:
+#if XLEN == 32
+      summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                         Location::RequiresRegister()));
+#else
+      summary->set_out(0, Location::RequiresRegister());
+#endif
+      break;
+    case kUnboxedFloat:
+    case kUnboxedDouble:
+      summary->set_out(0, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+  }
+  return summary;
+}
+
+void BitCastInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
+}
+
+void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ Stop(message());
+}
+
+void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  BlockEntryInstr* entry = normal_entry();
+  if (entry != nullptr) {
+    if (!compiler->CanFallThroughTo(entry)) {
+      FATAL("Checked function entry must have no offset");
+    }
+  } else {
+    entry = osr_entry();
+    if (!compiler->CanFallThroughTo(entry)) {
+      __ j(compiler->GetJumpLabel(entry));
+    }
+  }
+}
+
+LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
+}
+
+void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (!compiler->is_optimizing()) {
+    if (FLAG_reorder_basic_blocks) {
+      compiler->EmitEdgeCounter(block()->preorder_number());
+    }
+    // Add a deoptimization descriptor for deoptimizing instructions that
+    // may be inserted before this instruction.
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
+  }
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
+
+  // We can fall through if the successor is the next block in the list.
+  // Otherwise, we need a jump.
+  if (!compiler->CanFallThroughTo(successor())) {
+    __ j(compiler->GetJumpLabel(successor()));
+  }
+}
+
+LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone,
+                                                        bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 2;
+
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+  summary->set_temp(1, Location::RequiresRegister());
+
+  return summary;
+}
+
+void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register index_reg = locs()->in(0).reg();
+  Register target_address_reg = locs()->temp(0).reg();
+  Register offset_reg = locs()->temp(1).reg();
+
+  ASSERT(RequiredInputRepresentation(0) == kTagged);
+  __ LoadObject(offset_reg, offsets_);
+  const auto element_address = __ ElementAddressForRegIndex(
+      /*is_external=*/false, kTypedDataInt32ArrayCid,
+      /*index_scale=*/4,
+      /*index_unboxed=*/false, offset_reg, index_reg, TMP);
+  __ lw(offset_reg, element_address);
+
+  const intptr_t entry_offset = __ CodeSize();
+  intx_t imm = -entry_offset;
+  intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+  intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+  __ auipc(target_address_reg, hi);
+  __ add(target_address_reg, target_address_reg, offset_reg);
+  __ jr(target_address_reg, lo);
+}
+
+LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  if (needs_number_check()) {
+    LocationSummary* locs = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+    locs->set_in(0, Location::RegisterLocation(A0));
+    locs->set_in(1, Location::RegisterLocation(A1));
+    locs->set_out(0, Location::RegisterLocation(A0));
+    return locs;
+  }
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, LocationRegisterOrConstant(left()));
+  // Only one of the inputs can be a constant. Choose register if the first one
+  // is a constant.
+  locs->set_in(1, locs->in(0).IsConstant()
+                      ? Location::RequiresRegister()
+                      : LocationRegisterOrConstant(right()));
+  locs->set_out(0, Location::RequiresRegister());
+  return locs;
+}
+
+Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
+    FlowGraphCompiler* compiler,
+    BranchLabels labels,
+    Register reg,
+    const Object& obj) {
+  return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
+                                               source(), deopt_id());
+}
+
+void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  compiler::Label is_true, is_false;
+  BranchLabels labels = {&is_true, &is_false, &is_false};
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+
+  Register result = locs()->out(0).reg();
+  if (is_true.IsLinked() || is_false.IsLinked()) {
+    if (true_condition != kInvalidCondition) {
+      EmitBranchOnCondition(compiler, true_condition, labels);
+    }
+    compiler::Label done;
+    __ Bind(&is_false);
+    __ LoadObject(result, Bool::False());
+    __ j(&done, compiler::Assembler::kNearJump);
+    __ Bind(&is_true);
+    __ LoadObject(result, Bool::True());
+    __ Bind(&done);
+  } else {
+    // If EmitComparisonCode did not use the labels and just returned
+    // a condition we can avoid the branch and use slt to generate the
+    // offsets to true or false.
+    ASSERT(kTrueOffsetFromNull + (1 << kBoolValueBitPosition) ==
+           kFalseOffsetFromNull);
+    __ SetIf(InvertCondition(true_condition), result);
+    __ slli(result, result, kBoolValueBitPosition);
+    __ add(result, result, NULL_REG);
+    __ addi(result, result, kTrueOffsetFromNull);
+  }
+}
+
+void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+                                     BranchInstr* branch) {
+  BranchLabels labels = compiler->CreateBranchLabels(branch);
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  if (true_condition != kInvalidCondition) {
+    EmitBranchOnCondition(compiler, true_condition, labels);
+  }
+}
+
+LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
+                                                         bool opt) const {
+  return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
+}
+
+void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Register input = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  __ xori(result, input, compiler::target::ObjectAlignment::kBoolValueMask);
+}
+
+LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  if (type_arguments() != nullptr) {
+    locs->set_in(kTypeArgumentsPos, Location::RegisterLocation(
+                                        AllocateObjectABI::kTypeArgumentsReg));
+  }
+  locs->set_out(0, Location::RegisterLocation(AllocateObjectABI::kResultReg));
+  return locs;
+}
+
+void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (type_arguments() != nullptr) {
+    TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
+    if (type_usage_info != nullptr) {
+      RegisterTypeArgumentsUse(compiler->function(), type_usage_info, cls_,
+                               type_arguments()->definition());
+    }
+  }
+  const Code& stub = Code::ZoneHandle(
+      compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
+                             locs(), deopt_id(), env());
+}
+
+void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#ifdef PRODUCT
+  UNREACHABLE();
+#else
+  ASSERT(!compiler->is_optimizing());
+  __ JumpAndLinkPatchable(StubCode::DebugStepCheck());
+  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, source());
+  compiler->RecordSafepoint(locs());
+#endif
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 5d332bc..caa35ac 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -94,10 +94,6 @@
 
 FlowGraph* TestPipeline::RunPasses(
     std::initializer_list<CompilerPass::Id> passes) {
-  // The table dispatch transformation needs a precompiler, which is not
-  // available in the test pipeline.
-  SetFlagScope<bool> sfs(&FLAG_use_table_dispatch, false);
-
   auto thread = Thread::Current();
   auto zone = thread->zone();
   const bool optimized = true;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 378537a..c966f53 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -560,22 +560,9 @@
       __ LoadObject(destination.reg(), value_);
     }
   } else if (destination.IsFpuRegister()) {
-    if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0)) {
-      __ xorps(destination.fpu_reg(), destination.fpu_reg());
-    } else {
-      ASSERT(tmp != kNoRegister);
-      __ LoadObject(tmp, value_);
-      __ movsd(destination.fpu_reg(),
-               compiler::FieldAddress(tmp, Double::value_offset()));
-    }
+    __ LoadDImmediate(destination.fpu_reg(), Double::Cast(value_).value());
   } else if (destination.IsDoubleStackSlot()) {
-    if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0)) {
-      __ xorps(FpuTMP, FpuTMP);
-    } else {
-      ASSERT(tmp != kNoRegister);
-      __ LoadObject(tmp, value_);
-      __ movsd(FpuTMP, compiler::FieldAddress(tmp, Double::value_offset()));
-    }
+    __ LoadDImmediate(FpuTMP, Double::Cast(value_).value());
     __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
   } else {
     ASSERT(destination.IsStackSlot());
@@ -4217,9 +4204,13 @@
   compiler::Label done;
 #if !defined(DART_COMPRESSED_POINTERS)
   ASSERT(value == result);
+  // Optimistically untag value.
   __ SmiUntag(value);
   __ j(NOT_CARRY, &done, compiler::Assembler::kNearJump);
-  __ movsxd(result, compiler::Address(value, TIMES_2, Mint::value_offset()));
+  // Undo untagging by multiplying value by 2.
+  // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
+  __ movsxd(result,
+            compiler::Address(value, value, TIMES_1, Mint::value_offset()));
 #else
   ASSERT(value != result);
   // Cannot speculatively untag with value == result because it erases the
@@ -4237,9 +4228,13 @@
   compiler::Label done;
 #if !defined(DART_COMPRESSED_POINTERS)
   ASSERT(value == result);
+  // Optimistically untag value.
   __ SmiUntag(value);
   __ j(NOT_CARRY, &done, compiler::Assembler::kNearJump);
-  __ movq(result, compiler::Address(value, TIMES_2, Mint::value_offset()));
+  // Undo untagging by multiplying value by 2.
+  // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
+  __ movq(result,
+          compiler::Address(value, value, TIMES_1, Mint::value_offset()));
 #else
   ASSERT(value != result);
   // Cannot speculatively untag with value == result because it erases the
@@ -4285,9 +4280,13 @@
     ASSERT(is_truncating());
     compiler::Label done;
 #if !defined(DART_COMPRESSED_POINTERS)
+    // Optimistically untag value.
     __ SmiUntag(value);
     __ j(NOT_CARRY, &done, compiler::Assembler::kNearJump);
-    __ movq(value, compiler::Address(value, TIMES_2, Mint::value_offset()));
+    // Undo untagging by multiplying value by 2.
+    // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
+    __ movq(value,
+            compiler::Address(value, value, TIMES_1, Mint::value_offset()));
 #else
     // Cannot speculatively untag because it erases the upper bits needed to
     // dereference when it is a Mint.
@@ -4306,8 +4305,10 @@
     // Optimistically untag value.
     __ SmiUntagOrCheckClass(value, kMintCid, &done);
     __ j(NOT_EQUAL, deopt);
-    // Undo untagging by multiplying value with 2.
-    __ movq(value, compiler::Address(value, TIMES_2, Mint::value_offset()));
+    // Undo untagging by multiplying value by 2.
+    // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
+    __ movq(value,
+            compiler::Address(value, value, TIMES_1, Mint::value_offset()));
 #else
     // Cannot speculatively untag because it erases the upper bits needed to
     // dereference when it is a Mint.
@@ -5438,13 +5439,11 @@
   XmmRegister base = locs->in(0).fpu_reg();
   XmmRegister exp = locs->in(1).fpu_reg();
   XmmRegister result = locs->out(0).fpu_reg();
-  Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg();
   XmmRegister zero_temp =
       locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg();
 
   __ xorps(zero_temp, zero_temp);
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)));
-  __ movsd(result, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(result, 1.0);
 
   compiler::Label check_base, skip_call;
   // exponent == 0.0 -> return 1.0;
@@ -5458,15 +5457,13 @@
   __ j(EQUAL, &return_base, compiler::Assembler::kNearJump);
 
   // exponent == 2.0 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)));
-  __ movsd(XMM0, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(XMM0, 2.0);
   __ comisd(exp, XMM0);
   compiler::Label return_base_times_2;
   __ j(EQUAL, &return_base_times_2, compiler::Assembler::kNearJump);
 
   // exponent == 3.0 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)));
-  __ movsd(XMM0, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(XMM0, 3.0);
   __ comisd(exp, XMM0);
   __ j(NOT_EQUAL, &check_base);
 
@@ -5500,22 +5497,19 @@
   __ j(PARITY_ODD, &try_sqrt, compiler::Assembler::kNearJump);
   // Return NaN.
   __ Bind(&return_nan);
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)));
-  __ movsd(result, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(result, NAN);
   __ jmp(&skip_call);
 
   compiler::Label do_pow, return_zero;
   __ Bind(&try_sqrt);
   // Before calling pow, check if we could use sqrt instead of pow.
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(kNegInfinity)));
-  __ movsd(result, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(result, kNegInfinity);
   // base == -Infinity -> call pow;
   __ comisd(base, result);
   __ j(EQUAL, &do_pow, compiler::Assembler::kNearJump);
 
   // exponent == 0.5 ?
-  __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)));
-  __ movsd(result, compiler::FieldAddress(temp, Double::value_offset()));
+  __ LoadDImmediate(result, 0.5);
   __ comisd(exp, result);
   __ j(NOT_EQUAL, &do_pow, compiler::Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 38de868..dd1e62c 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1040,7 +1040,8 @@
 
     // Abort if the inlinable bit on the function is low.
     if (!function.CanBeInlined()) {
-      TRACE_INLINING(THR_Print("     Bailout: not inlinable\n"));
+      TRACE_INLINING(THR_Print(
+          "     Bailout: not inlinable due to !function.CanBeInlined()\n"));
       PRINT_INLINING_TREE("Not inlinable", &call_data->caller, &function,
                           call_data->call);
       return false;
@@ -1165,6 +1166,9 @@
             // As a side effect of parsing the function, it may be marked
             // as not inlinable. This happens for async and async* functions
             // when causal stack traces are being tracked.
+            TRACE_INLINING(
+                THR_Print("     Bailout: not inlinable due to "
+                          "!function.CanBeInlined()\n"));
             return false;
           }
         }
diff --git a/runtime/vm/compiler/backend/inliner_test.cc b/runtime/vm/compiler/backend/inliner_test.cc
index 4760a70..168018d 100644
--- a/runtime/vm/compiler/backend/inliner_test.cc
+++ b/runtime/vm/compiler/backend/inliner_test.cc
@@ -230,7 +230,6 @@
 
       // Loop body
       kMatchAndMoveTargetEntry,
-      kWordSize == 4 ? kMatchAndMoveBoxInt64 : kNop,
       kMatchAndMoveBoxInt64,
       kMatchAndMoveStoreIndexed,
       kMatchAndMoveBinaryInt64Op,
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 56c5604..b9988948 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -533,7 +533,7 @@
  public:
   SmallSet() : data_(0) {}
 
-  explicit SmallSet(intptr_t data) : data_(data) {}
+  explicit SmallSet(uintptr_t data) : data_(data) {}
 
   bool Contains(T value) const { return (data_ & ToMask(value)) != 0; }
 
@@ -545,15 +545,15 @@
 
   void Clear() { data_ = 0; }
 
-  intptr_t data() const { return data_; }
+  uintptr_t data() const { return data_; }
 
  private:
-  static intptr_t ToMask(T value) {
-    ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte));
-    return 1 << static_cast<intptr_t>(value);
+  static uintptr_t ToMask(T value) {
+    ASSERT(static_cast<uintptr_t>(value) < (kWordSize * kBitsPerByte));
+    return static_cast<uintptr_t>(1) << static_cast<uintptr_t>(value);
   }
 
-  intptr_t data_;
+  uintptr_t data_;
 };
 
 class RegisterSet : public ValueObject {
@@ -564,8 +564,8 @@
     ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte));
   }
 
-  explicit RegisterSet(intptr_t cpu_register_mask,
-                       intptr_t fpu_register_mask = 0)
+  explicit RegisterSet(uintptr_t cpu_register_mask,
+                       uintptr_t fpu_register_mask = 0)
       : RegisterSet() {
     AddTaggedRegisters(cpu_register_mask, fpu_register_mask);
   }
@@ -620,8 +620,8 @@
 #endif
   }
 
-  void AddTaggedRegisters(intptr_t cpu_register_mask,
-                          intptr_t fpu_register_mask) {
+  void AddTaggedRegisters(uintptr_t cpu_register_mask,
+                          uintptr_t fpu_register_mask) {
     for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
       if (Utils::TestBit(cpu_register_mask, i)) {
         const Register reg = static_cast<Register>(i);
@@ -694,12 +694,12 @@
   intptr_t FpuRegisterCount() const { return RegisterCount(fpu_registers()); }
 
   static intptr_t RegisterCount(intptr_t registers);
-  static bool Contains(intptr_t register_set, intptr_t reg) {
-    return (register_set & (1 << reg)) != 0;
+  static bool Contains(uintptr_t register_set, intptr_t reg) {
+    return (register_set & (static_cast<uintptr_t>(1) << reg)) != 0;
   }
 
-  intptr_t cpu_registers() const { return cpu_registers_.data(); }
-  intptr_t fpu_registers() const { return fpu_registers_.data(); }
+  uintptr_t cpu_registers() const { return cpu_registers_.data(); }
+  uintptr_t fpu_registers() const { return fpu_registers_.data(); }
 
   void Clear() {
     cpu_registers_.Clear();
diff --git a/runtime/vm/compiler/backend/locations_helpers.h b/runtime/vm/compiler/backend/locations_helpers.h
index 6b62e40..fefd212 100644
--- a/runtime/vm/compiler/backend/locations_helpers.h
+++ b/runtime/vm/compiler/backend/locations_helpers.h
@@ -434,6 +434,10 @@
 #include "vm/compiler/backend/locations_helpers_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 
+#elif defined(TARGET_ARCH_RISCV32)
+
+#elif defined(TARGET_ARCH_RISCV64)
+
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/compiler/backend/loops_test.cc b/runtime/vm/compiler/backend/loops_test.cc
index 1722f3b..dec8c01 100644
--- a/runtime/vm/compiler/backend/loops_test.cc
+++ b/runtime/vm/compiler/backend/loops_test.cc
@@ -387,15 +387,7 @@
   const char* expected =
       "  [0\n"
       "  LIN(9223372036854775806 + 1 * i)\n"  // phi
-#if !defined(TARGET_ARCH_IS_64_BIT)
-      "  LIN(9223372036854775806 + 1 * i)\n"  // (un)boxing
-      "  LIN(9223372036854775806 + 1 * i)\n"
-      "  LIN(9223372036854775806 + 1 * i)\n"
-#endif                                        // !defined(TARGET_ARCH_IS_64_BIT)
       "  LIN(9223372036854775807 + 1 * i)\n"  // add
-#if !defined(TARGET_ARCH_IS_64_BIT)
-      "  LIN(9223372036854775807 + 1 * i)\n"  // unbox
-#endif                                        // !defined(TARGET_ARCH_IS_64_BIT)
       "  ]\n";
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
@@ -434,15 +426,7 @@
   const char* expected =
       "  [0\n"
       "  LIN(-9223372036854775807 + -1 * i)\n"  // phi
-#if !defined(TARGET_ARCH_IS_64_BIT)
-      "  LIN(-9223372036854775807 + -1 * i)\n"  // (un)boxing
-      "  LIN(-9223372036854775807 + -1 * i)\n"
-      "  LIN(-9223372036854775807 + -1 * i)\n"
-#endif  // !defined(TARGET_ARCH_IS_64_BIT)
       "  LIN(-9223372036854775808 + -1 * i)\n"  // sub
-#if !defined(TARGET_ARCH_IS_64_BIT)
-      "  LIN(-9223372036854775808 + -1 * i)\n"  // unbox
-#endif  // !defined(TARGET_ARCH_IS_64_BIT)
       "  ]\n";
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 7d02f87..d2824a2 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -1643,16 +1643,10 @@
     Value* left = op->left()->CopyWithType();
     Value* right = op->right()->CopyWithType();
     intptr_t deopt_id = op->DeoptimizationTarget();
-    if (def->IsBinaryInt64Op()) {
-      return new (Z) BinaryUint32OpInstr(op_kind, left, right, deopt_id);
-    } else if (def->IsShiftInt64Op()) {
-      return new (Z) ShiftUint32OpInstr(op_kind, left, right, deopt_id);
-    } else if (def->IsSpeculativeShiftInt64Op()) {
-      return new (Z)
-          SpeculativeShiftUint32OpInstr(op_kind, left, right, deopt_id);
-    } else {
-      UNREACHABLE();
-    }
+    return BinaryIntegerOpInstr::Make(
+        kUnboxedUint32, op_kind, left, right, deopt_id,
+        def->IsSpeculativeShiftInt64Op() ? Instruction::kGuardInputs
+                                         : Instruction::kNotSpeculative);
   } else if (def->IsBoxInt64()) {
     Value* value = def->AsBoxInt64()->value()->CopyWithType();
     return new (Z) BoxUint32Instr(value);
@@ -2082,6 +2076,10 @@
   return OnlyGreaterThanOrEqualTo(0);
 }
 
+bool Range::IsNegative() const {
+  return OnlyLessThanOrEqualTo(-1);
+}
+
 bool Range::OnlyLessThanOrEqualTo(int64_t val) const {
   const RangeBoundary upper_bound = max().UpperBound();
   return !upper_bound.IsPositiveInfinity() &&
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index b0037f4..aa247c7 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -413,6 +413,9 @@
   // [0, +inf]
   bool IsPositive() const;
 
+  // [-inf, -1]
+  bool IsNegative() const;
+
   // [-inf, val].
   bool OnlyLessThanOrEqualTo(int64_t val) const;
 
@@ -560,6 +563,9 @@
   static bool IsPositive(Range* range) {
     return !Range::IsUnknown(range) && range->IsPositive();
   }
+  static bool IsNegative(Range* range) {
+    return !Range::IsUnknown(range) && range->IsNegative();
+  }
 
   static bool Overlaps(Range* range, intptr_t min, intptr_t max) {
     return Range::IsUnknown(range) || range->Overlaps(min, max);
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 2d42347..ce2d3d5 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/backend/il_test_helper.h"
 #include "vm/unit_test.h"
 
 namespace dart {
@@ -640,4 +641,53 @@
           .IsMaximumOrAbove(size));
 }
 
+#if defined(DART_PRECOMPILER) && defined(TARGET_ARCH_IS_64_BIT)
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48153.
+ISOLATE_UNIT_TEST_CASE(RangeAnalysis_ShiftUint32Op) {
+  const char* kScript = R"(
+    @pragma('vm:never-inline')
+    int foo(int hash) {
+      return 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
+    }
+    void main() {
+      foo(42);
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+
+  Invoke(root_library, "main");
+
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kAOT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true,
+                   ParallelMovesHandling::kSkip);
+
+  ShiftUint32OpInstr* shift = nullptr;
+
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMoveGlob,
+      kMatchAndMoveBinaryUint32Op,
+      kMoveGlob,
+      {kMatchAndMoveShiftUint32Op, &shift},
+      kMoveGlob,
+      kMatchAndMoveBinaryUint32Op,
+      kMoveGlob,
+      kMatchAndMoveBinaryUint32Op,
+      kMoveGlob,
+      kMatchReturn,
+  }));
+
+  EXPECT(shift->shift_range() != nullptr);
+  EXPECT(shift->shift_range()->min().ConstantValue() == 10);
+  EXPECT(shift->shift_range()->max().ConstantValue() == 10);
+}
+
+#endif  // defined(DART_PRECOMPILER) && defined(TARGET_ARCH_IS_64_BIT)
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index e356875..35070d4 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1837,6 +1837,12 @@
     }
   }
 
+  bool CanForwardLoadTo(Definition* load, Definition* replacement) {
+    // Loads which check initialization status can only be replaced if
+    // we can guarantee that forwarded value is not a sentinel.
+    return !(CallsInitializer(load) && replacement->Type()->can_be_sentinel());
+  }
+
   // Returns true if given instruction stores the sentinel value.
   // Such a store doesn't initialize corresponding field.
   bool IsSentinelStore(Instruction* instr) {
@@ -2259,16 +2265,18 @@
           ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL));
 
           Definition* replacement = (*out_values)[place_id];
-          graph_->EnsureSSATempIndex(defn, replacement);
-          if (FLAG_trace_optimization) {
-            THR_Print("Replacing load v%" Pd " with v%" Pd "\n",
-                      defn->ssa_temp_index(), replacement->ssa_temp_index());
-          }
+          if (CanForwardLoadTo(defn, replacement)) {
+            graph_->EnsureSSATempIndex(defn, replacement);
+            if (FLAG_trace_optimization) {
+              THR_Print("Replacing load v%" Pd " with v%" Pd "\n",
+                        defn->ssa_temp_index(), replacement->ssa_temp_index());
+            }
 
-          ReplaceLoad(defn, replacement);
-          instr_it.RemoveCurrentFromGraph();
-          forwarded_ = true;
-          continue;
+            ReplaceLoad(defn, replacement);
+            instr_it.RemoveCurrentFromGraph();
+            forwarded_ = true;
+            continue;
+          }
         } else if (!kill->Contains(place_id)) {
           // This is an exposed load: it is the first representative of a
           // given expression id and it is not killed on the path from
@@ -2630,7 +2638,7 @@
         // as replaced and store a pointer to the replacement.
         replacement = replacement->Replacement();
 
-        if (load != replacement) {
+        if ((load != replacement) && CanForwardLoadTo(load, replacement)) {
           graph_->EnsureSSATempIndex(load, replacement);
 
           if (FLAG_trace_optimization) {
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index 557139a..9b8891e 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -85,62 +85,6 @@
   EXPECT(load_indexed->InputAt(0)->definition() == load_untagged);
 }
 
-// This test asserts that we are not inlining accesses to typed data interfaces
-// (e.g. Uint8List) if there are instantiated 3rd party classes (e.g.
-// UnmodifiableUint8ListView).
-ISOLATE_UNIT_TEST_CASE(IRTest_TypedDataAOT_NotInlining) {
-  const char* kScript =
-      R"(
-      import 'dart:typed_data';
-
-      createThirdPartyUint8List() => UnmodifiableUint8ListView(Uint8List(10));
-
-      void foo(Uint8List list, int from) {
-        if (from >= list.length) {
-          list[from];
-        }
-      }
-      )";
-
-  const auto& root_library = Library::Handle(LoadTestScript(kScript));
-
-  // Firstly we ensure a non internal/external/view Uint8List is allocated.
-  Invoke(root_library, "createThirdPartyUint8List");
-
-  // Now we ensure that we don't perform the inlining of the `list[from]`
-  // access.
-  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
-  TestPipeline pipeline(function, CompilerPass::kAOT);
-  FlowGraph* flow_graph = pipeline.RunPasses({});
-
-  auto entry = flow_graph->graph_entry()->normal_entry();
-  EXPECT(entry != nullptr);
-
-  InstanceCallInstr* length_call = nullptr;
-  PushArgumentInstr* pusharg1 = nullptr;
-  PushArgumentInstr* pusharg2 = nullptr;
-  InstanceCallInstr* index_get_call = nullptr;
-
-  ILMatcher cursor(flow_graph, entry);
-  RELEASE_ASSERT(cursor.TryMatch({
-      kMoveGlob,
-      {kMatchAndMoveInstanceCall, &length_call},
-      kMoveGlob,
-      kMatchAndMoveBranchTrue,
-      kMoveGlob,
-      {kMatchAndMovePushArgument, &pusharg1},
-      {kMatchAndMovePushArgument, &pusharg2},
-      {kMatchAndMoveInstanceCall, &index_get_call},
-      kMoveGlob,
-      kMatchReturn,
-  }));
-
-  EXPECT(length_call->Selector() == Symbols::GetLength().ptr());
-  EXPECT(pusharg1->InputAt(0)->definition()->IsParameter());
-  EXPECT(pusharg2->InputAt(0)->definition()->IsParameter());
-  EXPECT(index_get_call->Selector() == Symbols::IndexToken().ptr());
-}
-
 // This test asserts that we are inlining get:length, [] and []= for all typed
 // data interfaces.  It also ensures that the asserted IR actually works by
 // exercising it.
@@ -151,7 +95,7 @@
 
       void reverse%s(%s list) {
         final length = list.length;
-        final halfLength = length ~/ 2;
+        final halfLength = length >> 1;
         for (int i = 0; i < halfLength; ++i) {
           final tmp = list[length-i-1];
           list[length-i-1] = list[i];
@@ -448,51 +392,6 @@
   }
 }
 
-ISOLATE_UNIT_TEST_CASE(IRTest_TypedDataAOT_Regress43534) {
-  const char* kScript =
-      R"(
-      import 'dart:typed_data';
-
-      @pragma('vm:never-inline')
-      void callWith<T>(void Function(T arg) fun, T arg) {
-        fun(arg);
-      }
-
-      void test() {
-        callWith<Uint8List>((Uint8List list) {
-          if (list[0] != 0) throw 'a';
-        }, Uint8List(10));
-      }
-      )";
-
-  const auto& root_library = Library::Handle(LoadTestScript(kScript));
-  Invoke(root_library, "test");
-  const auto& test_function =
-      Function::Handle(GetFunction(root_library, "test"));
-
-  const auto& function = Function::Handle(
-      ClosureFunctionsCache::GetUniqueInnerClosure(test_function));
-  RELEASE_ASSERT(function.IsFunction());
-
-  TestPipeline pipeline(function, CompilerPass::kAOT);
-  FlowGraph* flow_graph = pipeline.RunPasses({});
-
-  auto entry = flow_graph->graph_entry()->normal_entry();
-  EXPECT(entry != nullptr);
-  ILMatcher cursor(flow_graph, entry, /*trace=*/true);
-  RELEASE_ASSERT(cursor.TryMatch(
-      {
-          kMatchAndMoveLoadField,
-          kMatchAndMoveGenericCheckBound,
-          kMatchAndMoveLoadUntagged,
-          kMatchAndMoveLoadIndexed,
-          kMatchAndMoveBranchFalse,
-          kMoveGlob,
-          kMatchReturn,
-      },
-      kMoveGlob));
-}
-
 #endif  // defined(DART_PRECOMPILER)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 0f9e5ea..1faa8d3 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -470,9 +470,7 @@
 });
 
 COMPILER_PASS(UseTableDispatch, {
-  if (FLAG_use_table_dispatch) {
-    state->call_specializer->ReplaceInstanceCallsWithDispatchTableCalls();
-  }
+  state->call_specializer->ReplaceInstanceCallsWithDispatchTableCalls();
 });
 
 COMPILER_PASS_REPEAT(CSE, { return DominatorBasedCSE::Optimize(flow_graph); });
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 1005791..ace9914 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -18,6 +18,7 @@
   "asm_intrinsifier_arm.cc",
   "asm_intrinsifier_arm64.cc",
   "asm_intrinsifier_ia32.cc",
+  "asm_intrinsifier_riscv.cc",
   "asm_intrinsifier_x64.cc",
   "assembler/assembler.h",
   "assembler/assembler_arm.cc",
@@ -28,6 +29,8 @@
   "assembler/assembler_base.h",
   "assembler/assembler_ia32.cc",
   "assembler/assembler_ia32.h",
+  "assembler/assembler_riscv.cc",
+  "assembler/assembler_riscv.h",
   "assembler/assembler_x64.cc",
   "assembler/assembler_x64.h",
   "assembler/object_pool_builder.h",
@@ -52,6 +55,7 @@
   "backend/flow_graph_compiler_arm.cc",
   "backend/flow_graph_compiler_arm64.cc",
   "backend/flow_graph_compiler_ia32.cc",
+  "backend/flow_graph_compiler_riscv.cc",
   "backend/flow_graph_compiler_x64.cc",
   "backend/il.cc",
   "backend/il.h",
@@ -60,6 +64,7 @@
   "backend/il_ia32.cc",
   "backend/il_printer.cc",
   "backend/il_printer.h",
+  "backend/il_riscv.cc",
   "backend/il_x64.cc",
   "backend/inliner.cc",
   "backend/inliner.h",
@@ -141,6 +146,7 @@
   "stub_code_compiler_arm.cc",
   "stub_code_compiler_arm64.cc",
   "stub_code_compiler_ia32.cc",
+  "stub_code_compiler_riscv.cc",
   "stub_code_compiler_x64.cc",
   "write_barrier_elimination.cc",
   "write_barrier_elimination.h",
@@ -151,6 +157,7 @@
   "assembler/assembler_arm64_test.cc",
   "assembler/assembler_arm_test.cc",
   "assembler/assembler_ia32_test.cc",
+  "assembler/assembler_riscv_test.cc",
   "assembler/assembler_test.cc",
   "assembler/assembler_x64_test.cc",
   "assembler/disassembler_test.cc",
@@ -193,6 +200,7 @@
   "assembler/disassembler.h",
   "assembler/disassembler_arm.cc",
   "assembler/disassembler_arm64.cc",
+  "assembler/disassembler_riscv.cc",
   "assembler/disassembler_x86.cc",
 ]
 
diff --git a/runtime/vm/compiler/ffi/abi.cc b/runtime/vm/compiler/ffi/abi.cc
index c902a89..1652c720 100644
--- a/runtime/vm/compiler/ffi/abi.cc
+++ b/runtime/vm/compiler/ffi/abi.cc
@@ -22,7 +22,8 @@
   uint64_t i;
 };
 
-#if defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64)
+#if defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64) ||                      \
+    defined(HOST_ARCH_RISCV64)
 static_assert(offsetof(AbiAlignmentDouble, d) == 8,
               "FFI transformation alignment");
 static_assert(offsetof(AbiAlignmentUint64, i) == 8,
@@ -81,6 +82,12 @@
 #elif defined(TARGET_ARCH_ARM64)
 #define TARGET_ARCH_NAME Arm64
 #define TARGET_ARCH_NAME_LC arm64
+#elif defined(TARGET_ARCH_RISCV32)
+#define TARGET_ARCH_NAME Riscv32
+#define TARGET_ARCH_NAME_LC riscv32
+#elif defined(TARGET_ARCH_RISCV64)
+#define TARGET_ARCH_NAME Riscv64
+#define TARGET_ARCH_NAME_LC riscv64
 #else
 #error Unknown arch
 #endif
diff --git a/runtime/vm/compiler/ffi/abi.h b/runtime/vm/compiler/ffi/abi.h
index 81b76d9..b693ef8 100644
--- a/runtime/vm/compiler/ffi/abi.h
+++ b/runtime/vm/compiler/ffi/abi.h
@@ -33,6 +33,8 @@
   kLinuxArm64,
   kLinuxIA32,
   kLinuxX64,
+  kLinuxRiscv32,
+  kLinuxRiscv64,
   kMacOSArm64,
   kMacOSX64,
   kWindowsArm64,
@@ -47,9 +49,9 @@
 // - runtime/vm/compiler/frontend/kernel_to_il.cc
 static_assert(static_cast<int64_t>(Abi::kAndroidArm) == 0,
               "Enum value unexpected.");
-static_assert(static_cast<int64_t>(Abi::kWindowsX64) == 17,
+static_assert(static_cast<int64_t>(Abi::kWindowsX64) == 19,
               "Enum value unexpected.");
-static_assert(num_abis == 18, "Enum value unexpected.");
+static_assert(num_abis == 20, "Enum value unexpected.");
 
 // The target ABI. Defines sizes and alignment of native types.
 Abi TargetAbi();
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc
index 0d81047..e30a518 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention.cc
@@ -94,8 +94,22 @@
       if (CallingConventions::kArgumentIntRegXorFpuReg) {
         cpu_regs_used++;
       }
-      return *new (zone_) NativeFpuRegistersLocation(payload_type, payload_type,
-                                                     kind, reg_index);
+#if defined(TARGET_ARCH_ARM)
+      if (kind == kSingleFpuReg) {
+        return *new (zone_)
+            NativeFpuRegistersLocation(payload_type, payload_type, kind,
+                                       static_cast<SRegister>(reg_index));
+      }
+      if (kind == kDoubleFpuReg) {
+        return *new (zone_)
+            NativeFpuRegistersLocation(payload_type, payload_type, kind,
+                                       static_cast<DRegister>(reg_index));
+      }
+#endif
+      ASSERT(kind == kQuadFpuReg);
+      FpuRegister reg = CallingConventions::FpuArgumentRegisters[reg_index];
+      return *new (zone_)
+          NativeFpuRegistersLocation(payload_type, payload_type, reg);
     }
 
     BlockAllFpuRegisters();
@@ -252,24 +266,24 @@
         return AllocateStack(payload_type);
       }
     } else {
-      const intptr_t chunck_size = payload_type.AlignmentInBytesStack();
-      ASSERT(chunck_size == 4 || chunck_size == 8);
+      const intptr_t chunk_size = payload_type.AlignmentInBytesStack();
+      ASSERT(chunk_size == 4 || chunk_size == 8);
       const intptr_t size_rounded =
-          Utils::RoundUp(payload_type.SizeInBytes(), chunck_size);
-      const intptr_t num_chuncks = size_rounded / chunck_size;
+          Utils::RoundUp(payload_type.SizeInBytes(), chunk_size);
+      const intptr_t num_chunks = size_rounded / chunk_size;
       const auto& chuck_type =
-          *new (zone_) NativePrimitiveType(chunck_size == 4 ? kInt32 : kInt64);
+          *new (zone_) NativePrimitiveType(chunk_size == 4 ? kInt32 : kInt64);
 
       NativeLocations& multiple_locations =
-          *new (zone_) NativeLocations(zone_, num_chuncks);
-      for (int i = 0; i < num_chuncks; i++) {
+          *new (zone_) NativeLocations(zone_, num_chunks);
+      for (int i = 0; i < num_chunks; i++) {
         const auto& allocated_chunk = &AllocateArgument(chuck_type);
         // The last chunk should not be 8 bytes, if the struct only has 4
         // remaining bytes to be allocated.
-        if (i == num_chuncks - 1 && chunck_size == 8 &&
+        if (i == num_chunks - 1 && chunk_size == 8 &&
             Utils::RoundUp(payload_type.SizeInBytes(), 4) % 8 == 4) {
           const auto& small_chuck_type = *new (zone_) NativePrimitiveType(
-              chunck_size == 4 ? kInt32 : kInt64);
+              chunk_size == 4 ? kInt32 : kInt64);
           multiple_locations.Add(&allocated_chunk->WithOtherNativeType(
               zone_, small_chuck_type, small_chuck_type));
         } else {
@@ -324,13 +338,13 @@
       if (regs_available) {
         const intptr_t size_rounded =
             Utils::RoundUp(payload_type.SizeInBytes(), 8);
-        const intptr_t num_chuncks = size_rounded / 8;
-        const auto& chuck_type = *new (zone_) NativePrimitiveType(kInt64);
+        const intptr_t num_chunks = size_rounded / 8;
+        const auto& chunk_type = *new (zone_) NativePrimitiveType(kInt64);
 
         NativeLocations& multiple_locations =
-            *new (zone_) NativeLocations(zone_, num_chuncks);
-        for (int i = 0; i < num_chuncks; i++) {
-          const auto& allocated_chunk = &AllocateArgument(chuck_type);
+            *new (zone_) NativeLocations(zone_, num_chunks);
+        for (int i = 0; i < num_chunks; i++) {
+          const auto& allocated_chunk = &AllocateArgument(chunk_type);
           multiple_locations.Add(allocated_chunk);
         }
         return *new (zone_)
@@ -350,6 +364,36 @@
   }
 #endif  // defined(TARGET_ARCH_ARM64)
 
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+  // If total size is <= XLEN, passed like an XLEN scalar: use a register if
+  // available or pass by value on the stack.
+  // If total size is <= 2*XLEN, passed like two XLEN scalars: use registers
+  // if available or pass by value on the stack. If only one register is
+  // available, pass the low part by register and the high part on the stack.
+  // Otherwise, passed by reference.
+  const NativeLocation& AllocateCompound(
+      const NativeCompoundType& payload_type) {
+    const auto& pointer_type = *new (zone_) NativePrimitiveType(kFfiIntPtr);
+    const auto& compound_type = payload_type.AsCompound();
+    const intptr_t size = compound_type.SizeInBytes();
+    if (size <= target::kWordSize) {
+      return AllocateArgument(pointer_type);
+    } else if (size <= 2 * target::kWordSize) {
+      NativeLocations& multiple_locations =
+          *new (zone_) NativeLocations(zone_, 2);
+      multiple_locations.Add(&AllocateArgument(pointer_type));
+      multiple_locations.Add(&AllocateArgument(pointer_type));
+      return *new (zone_)
+          MultipleNativeLocations(compound_type, multiple_locations);
+    } else {
+      const auto& pointer_type = *new (zone_) NativePrimitiveType(kFfiIntPtr);
+      const auto& pointer_location = AllocateArgument(pointer_type);
+      return *new (zone_)
+          PointerToMemoryLocation(pointer_location, compound_type);
+    }
+  }
+#endif
+
   static FpuRegisterKind FpuRegKind(const NativeType& payload_type) {
 #if defined(TARGET_ARCH_ARM)
     return FpuRegisterKindFromSize(payload_type.SizeInBytes());
@@ -666,6 +710,22 @@
 }
 #endif  // defined(TARGET_ARCH_ARM64)
 
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+static const NativeLocation& CompoundResultLocation(
+    Zone* zone,
+    const NativeCompoundType& payload_type) {
+  // First or first and second argument registers if it fits, otherwise a
+  // pointer to the result location is passed in.
+  ArgumentAllocator frame_state(zone);
+  const auto& location_as_argument = frame_state.AllocateArgument(payload_type);
+  if (!location_as_argument.IsStack() &&
+      !location_as_argument.IsPointerToMemory()) {
+    return location_as_argument;
+  }
+  return PointerToMemoryResultLocation(zone, payload_type);
+}
+#endif  // defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
 // Location for the result of a C signature function.
 static const NativeLocation& ResultLocation(Zone* zone,
                                             const NativeType& payload_type) {
diff --git a/runtime/vm/compiler/ffi/native_calling_convention_test.cc b/runtime/vm/compiler/ffi/native_calling_convention_test.cc
index 328c0ca..dc0d522 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention_test.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention_test.cc
@@ -11,6 +11,9 @@
 namespace compiler {
 namespace ffi {
 
+// TODO(https://github.com/dart-lang/sdk/issues/48164)
+#if !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 const NativeCallingConvention& RunSignatureTest(
     dart::Zone* zone,
     const char* name,
@@ -625,6 +628,8 @@
   RunSignatureTest(Z, "struct12bytesFloatx6", arguments, int64_type);
 }
 
+#endif  // !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 }  // namespace ffi
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi/native_location_test.cc b/runtime/vm/compiler/ffi/native_location_test.cc
index 8ba10d9..8eecc54 100644
--- a/runtime/vm/compiler/ffi/native_location_test.cc
+++ b/runtime/vm/compiler/ffi/native_location_test.cc
@@ -10,6 +10,9 @@
 namespace compiler {
 namespace ffi {
 
+// TODO(https://github.com/dart-lang/sdk/issues/48164)
+#if !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 UNIT_TEST_CASE_WITH_ZONE(NativeStackLocation) {
   const auto& native_type = *new (Z) NativePrimitiveType(kInt8);
 
@@ -35,6 +38,8 @@
   EXPECT_EQ(4, half_1.offset_in_bytes());
 }
 
+#endif  // !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 }  // namespace ffi
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc
index ac49f39..8902c9b 100644
--- a/runtime/vm/compiler/ffi/native_type.cc
+++ b/runtime/vm/compiler/ffi/native_type.cc
@@ -368,8 +368,6 @@
     case kFfiInt64Cid:
     case kFfiUint64Cid:
       return kInt64;
-    case kFfiIntPtrCid:
-      return compiler::target::kWordSize == 4 ? kInt32 : kInt64;
     case kFfiFloatCid:
       return kFloat;
     case kFfiDoubleCid:
diff --git a/runtime/vm/compiler/ffi/native_type_test.cc b/runtime/vm/compiler/ffi/native_type_test.cc
index d132b91..aa3b00c 100644
--- a/runtime/vm/compiler/ffi/native_type_test.cc
+++ b/runtime/vm/compiler/ffi/native_type_test.cc
@@ -12,6 +12,9 @@
 namespace compiler {
 namespace ffi {
 
+// TODO(https://github.com/dart-lang/sdk/issues/48164)
+#if !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 const NativeCompoundType& RunStructTest(dart::Zone* zone,
                                         const char* name,
                                         const NativeTypes& member_types,
@@ -339,6 +342,8 @@
   EXPECT(union_type.ContainsUnalignedMembers());
 }
 
+#endif  // !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 }  // namespace ffi
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi/native_type_vm_test.cc b/runtime/vm/compiler/ffi/native_type_vm_test.cc
index 50a1e07..28e2b42 100644
--- a/runtime/vm/compiler/ffi/native_type_vm_test.cc
+++ b/runtime/vm/compiler/ffi/native_type_vm_test.cc
@@ -11,6 +11,9 @@
 namespace compiler {
 namespace ffi {
 
+// TODO(https://github.com/dart-lang/sdk/issues/48164)
+#if !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 ISOLATE_UNIT_TEST_CASE(Ffi_NativeType_Primitive_FromAbstractType) {
   Zone* Z = thread->zone();
 
@@ -86,6 +89,8 @@
             native_type.members()[1]->SizeInBytes());
 }
 
+#endif  // !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
+
 }  // namespace ffi
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/ffi/recognized_method.cc b/runtime/vm/compiler/ffi/recognized_method.cc
index 323fcc8..a0a6594 100644
--- a/runtime/vm/compiler/ffi/recognized_method.cc
+++ b/runtime/vm/compiler/ffi/recognized_method.cc
@@ -30,9 +30,6 @@
       return kTypedDataInt64ArrayCid;
     case kFfiUint64Cid:
       return kTypedDataUint64ArrayCid;
-    case kFfiIntPtrCid:
-      return target::kWordSize == 4 ? kTypedDataInt32ArrayCid
-                                    : kTypedDataInt64ArrayCid;
     case kPointerCid:
       return target::kWordSize == 4 ? kTypedDataUint32ArrayCid
                                     : kTypedDataUint64ArrayCid;
@@ -78,7 +75,7 @@
   case MethodRecognizer::kFfiLoad##type:                                       \
   case MethodRecognizer::kFfiStore##type:                                      \
     return kFfi##type##Cid;
-    CLASS_LIST_FFI_NUMERIC(LOAD_STORE)
+    CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(LOAD_STORE)
 #undef LOAD_STORE
     case MethodRecognizer::kFfiLoadFloatUnaligned:
     case MethodRecognizer::kFfiStoreFloatUnaligned:
@@ -105,7 +102,7 @@
   case MethodRecognizer::kFfiLoad##type:                                       \
   case MethodRecognizer::kFfiStore##type:                                      \
     return kAlignedAccess;
-    CLASS_LIST_FFI_NUMERIC(LOAD_STORE)
+    CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(LOAD_STORE)
     LOAD_STORE(Pointer)
 #undef LOAD_STORE
     case MethodRecognizer::kFfiLoadFloatUnaligned:
diff --git a/runtime/vm/compiler/ffi/unit_test.cc b/runtime/vm/compiler/ffi/unit_test.cc
index b58e59f..138fe36 100644
--- a/runtime/vm/compiler/ffi/unit_test.cc
+++ b/runtime/vm/compiler/ffi/unit_test.cc
@@ -18,6 +18,10 @@
 const char* kArch = "ia32";
 #elif defined(TARGET_ARCH_X64)
 const char* kArch = "x64";
+#elif defined(TARGET_ARCH_RISCV32)
+const char* kArch = "riscv32";
+#elif defined(TARGET_ARCH_RISCV64)
+const char* kArch = "riscv64";
 #endif
 
 #if defined(DART_TARGET_OS_ANDROID)
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index dba179a..08ff0cc 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -833,7 +833,6 @@
     case MethodRecognizer::kFfiLoadUint16:
     case MethodRecognizer::kFfiLoadUint32:
     case MethodRecognizer::kFfiLoadUint64:
-    case MethodRecognizer::kFfiLoadIntPtr:
     case MethodRecognizer::kFfiLoadFloat:
     case MethodRecognizer::kFfiLoadFloatUnaligned:
     case MethodRecognizer::kFfiLoadDouble:
@@ -847,7 +846,6 @@
     case MethodRecognizer::kFfiStoreUint16:
     case MethodRecognizer::kFfiStoreUint32:
     case MethodRecognizer::kFfiStoreUint64:
-    case MethodRecognizer::kFfiStoreIntPtr:
     case MethodRecognizer::kFfiStoreFloat:
     case MethodRecognizer::kFfiStoreFloatUnaligned:
     case MethodRecognizer::kFfiStoreDouble:
@@ -928,7 +926,8 @@
       if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
 #if defined(TARGET_ARCH_X64)
       return CompilerState::Current().is_aot() || FLAG_target_unknown_cpu;
-#elif defined(TARGET_ARCH_ARM64)
+#elif defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV32) ||            \
+    defined(TARGET_ARCH_RISCV64)
       return true;
 #else
       return false;
@@ -1352,7 +1351,6 @@
     case MethodRecognizer::kFfiLoadUint16:
     case MethodRecognizer::kFfiLoadUint32:
     case MethodRecognizer::kFfiLoadUint64:
-    case MethodRecognizer::kFfiLoadIntPtr:
     case MethodRecognizer::kFfiLoadFloat:
     case MethodRecognizer::kFfiLoadFloatUnaligned:
     case MethodRecognizer::kFfiLoadDouble:
@@ -1431,7 +1429,6 @@
     case MethodRecognizer::kFfiStoreUint16:
     case MethodRecognizer::kFfiStoreUint32:
     case MethodRecognizer::kFfiStoreUint64:
-    case MethodRecognizer::kFfiStoreIntPtr:
     case MethodRecognizer::kFfiStoreFloat:
     case MethodRecognizer::kFfiStoreFloatUnaligned:
     case MethodRecognizer::kFfiStoreDouble:
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 86b49ff..15f48ef 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -740,6 +740,13 @@
 
 Type& TranslationHelper::GetDeclarationType(const Class& klass) {
   ASSERT(!klass.IsNull());
+  // Forward expression evaluation class to a real class when
+  // creating types.
+  if (GetExpressionEvaluationClass().ptr() == klass.ptr()) {
+    ASSERT(GetExpressionEvaluationRealClass().ptr() != klass.ptr());
+    return GetDeclarationType(GetExpressionEvaluationRealClass());
+  }
+  ASSERT(klass.id() != kIllegalCid);
   // Note that if cls is _Closure, the returned type will be _Closure,
   // and not the signature type.
   Type& type = Type::ZoneHandle(Z);
@@ -3556,6 +3563,14 @@
 
 const Type& TypeTranslator::ReceiverType(const Class& klass) {
   ASSERT(!klass.IsNull());
+  // Forward expression evaluation class to a real class when
+  // creating types.
+  if (translation_helper_.GetExpressionEvaluationClass().ptr() == klass.ptr()) {
+    ASSERT(translation_helper_.GetExpressionEvaluationRealClass().ptr() !=
+           klass.ptr());
+    return ReceiverType(translation_helper_.GetExpressionEvaluationRealClass());
+  }
+  ASSERT(klass.id() != kIllegalCid);
   // Note that if klass is _Closure, the returned type will be _Closure,
   // and not the signature type.
   Type& type = Type::ZoneHandle(Z);
@@ -3636,10 +3651,7 @@
   const auto unboxing_info =
       unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);
 
-  // TODO(dartbug.com/32292): accept unboxed parameters and return value
-  // when FLAG_use_table_dispatch == false.
-  if (FLAG_precompiled_mode && unboxing_info != nullptr &&
-      FLAG_use_table_dispatch) {
+  if (FLAG_precompiled_mode && unboxing_info != nullptr) {
     for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
       SetupUnboxingInfoOfParameter(function, i, unboxing_info);
     }
@@ -3655,10 +3667,7 @@
   const auto unboxing_info =
       unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);
 
-  // TODO(dartbug.com/32292): accept unboxed parameters and return value
-  // when FLAG_use_table_dispatch == false.
-  if (FLAG_precompiled_mode && unboxing_info != nullptr &&
-      FLAG_use_table_dispatch) {
+  if (FLAG_precompiled_mode && unboxing_info != nullptr) {
     if (field_accessor.IsImplicitSetterFunction()) {
       for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
         SetupUnboxingInfoOfParameter(field_accessor, i, unboxing_info);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 35b2647..315e468 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -209,14 +209,27 @@
     }
     return *expression_evaluation_function_;
   }
+  void SetExpressionEvaluationClass(const Class& cls) {
+    ASSERT(expression_evaluation_class_ == nullptr);
+    ASSERT(!cls.IsNull());
+    expression_evaluation_class_ = &Class::Handle(zone_, cls.ptr());
+  }
+  const Class& GetExpressionEvaluationClass() {
+    if (expression_evaluation_class_ == nullptr) {
+      return Class::null_class();
+    }
+    return *expression_evaluation_class_;
+  }
   void SetExpressionEvaluationRealClass(const Class& real_class) {
     ASSERT(expression_evaluation_real_class_ == nullptr);
     ASSERT(!real_class.IsNull());
     expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.ptr());
   }
-  ClassPtr GetExpressionEvaluationRealClass() {
-    ASSERT(expression_evaluation_real_class_ != nullptr);
-    return expression_evaluation_real_class_->ptr();
+  const Class& GetExpressionEvaluationRealClass() {
+    if (expression_evaluation_real_class_ == nullptr) {
+      return Class::null_class();
+    }
+    return *expression_evaluation_real_class_;
   }
 
  private:
@@ -250,6 +263,14 @@
   Smi& name_index_handle_;
   GrowableObjectArray* potential_extension_libraries_ = nullptr;
   Function* expression_evaluation_function_ = nullptr;
+
+  // A temporary class needed to contain the function to which an eval
+  // expression is compiled. This is a fresh class so loading the kernel
+  // isn't a no-op. It should be unreachable after the eval function is loaded.
+  Class* expression_evaluation_class_ = nullptr;
+
+  // The original class that is the scope in which the eval expression is
+  // evaluated.
   Class* expression_evaluation_real_class_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TranslationHelper);
@@ -796,6 +817,7 @@
     kIsNonNullableByDefault = 1 << 1,
     kNonNullableByDefaultCompiledModeBit1 = 1 << 2,
     kNonNullableByDefaultCompiledModeBit2 = 1 << 3,
+    kUnsupported = 1 << 4,
   };
 
   explicit LibraryHelper(KernelReaderHelper* helper, uint32_t binary_version)
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index ff96abb..5dacd56 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -83,7 +83,6 @@
             "Trace only optimizing compiler operations.");
 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
 
-DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 
 static void PrecompilationModeHandler(bool value) {
@@ -488,7 +487,7 @@
   // true. use_far_branches is always false on ia32 and x64.
   volatile bool done = false;
   // volatile because the variable may be clobbered by a longjmp.
-  volatile bool use_far_branches = false;
+  volatile intptr_t far_branch_level = 0;
 
   // In the JIT case we allow speculative inlining and have no need for a
   // suppression, since we don't restart optimization.
@@ -572,7 +571,7 @@
       ASSERT(pass_state.inline_id_to_function.length() ==
              pass_state.caller_inline_id.length());
       compiler::ObjectPoolBuilder object_pool_builder;
-      compiler::Assembler assembler(&object_pool_builder, use_far_branches);
+      compiler::Assembler assembler(&object_pool_builder, far_branch_level);
       FlowGraphCompiler graph_compiler(
           &assembler, flow_graph, *parsed_function(), optimized(),
           &speculative_policy, pass_state.inline_id_to_function,
@@ -647,8 +646,8 @@
         // Compilation failed due to an out of range branch offset in the
         // assembler. We try again (done = false) with far branches enabled.
         done = false;
-        ASSERT(!use_far_branches);
-        use_far_branches = true;
+        RELEASE_ASSERT(far_branch_level < 2);
+        far_branch_level++;
       } else if (error.ptr() == Object::speculative_inlining_error().ptr()) {
         // Can only happen with precompilation.
         UNREACHABLE();
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index caa0903..36966c9 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -171,10 +171,18 @@
  public:
   explicit NoBackgroundCompilerScope(Thread* thread)
       : StackResource(thread), isolate_group_(thread->isolate_group()) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    UNREACHABLE();
+#else
     isolate_group_->background_compiler()->Disable();
+#endif
   }
   ~NoBackgroundCompilerScope() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    UNREACHABLE();
+#else
     isolate_group_->background_compiler()->Enable();
+#endif
   }
 
  private:
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
index e1f2f1f..2cb48c9 100644
--- a/runtime/vm/compiler/offsets_extractor.cc
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -25,6 +25,10 @@
 #define ARCH_DEF_CPU "defined(TARGET_ARCH_IA32)"
 #elif defined(TARGET_ARCH_ARM64)
 #define ARCH_DEF_CPU "defined(TARGET_ARCH_ARM64)"
+#elif defined(TARGET_ARCH_RISCV32)
+#define ARCH_DEF_CPU "defined(TARGET_ARCH_RISCV32)"
+#elif defined(TARGET_ARCH_RISCV64)
+#define ARCH_DEF_CPU "defined(TARGET_ARCH_RISCV64)"
 #else
 #error Unknown architecture
 #endif
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 5cb46fc..9dc2df9 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -99,16 +99,16 @@
   V(::, max, MathMax, 0xead7161a)                                              \
   V(::, _doublePow, MathDoublePow, 0x989f3334)                                 \
   V(::, _intPow, MathIntPow, 0x68b6021e)                                       \
-  V(::, _sin, MathSin, 0x17dacdc4)                                             \
-  V(::, _cos, MathCos, 0xf4948106)                                             \
-  V(::, _tan, MathTan, 0xeb1a58f8)                                             \
-  V(::, _asin, MathAsin, 0x29e4d95f)                                           \
-  V(::, _acos, MathAcos, 0x200aa49c)                                           \
-  V(::, _atan, MathAtan, 0x10fa64b3)                                           \
-  V(::, _atan2, MathAtan2, 0x58d4f514)                                         \
-  V(::, _sqrt, MathSqrt, 0x03183751)                                           \
-  V(::, _exp, MathExp, 0x00f50391)                                             \
-  V(::, _log, MathLog, 0x09ae8823)                                             \
+  V(::, _sin, MathSin, 0x17daca03)                                             \
+  V(::, _cos, MathCos, 0xf4947d45)                                             \
+  V(::, _tan, MathTan, 0xeb1a5537)                                             \
+  V(::, _asin, MathAsin, 0x29e4d59e)                                           \
+  V(::, _acos, MathAcos, 0x200aa0db)                                           \
+  V(::, _atan, MathAtan, 0x10fa60f2)                                           \
+  V(::, _atan2, MathAtan2, 0x58d4f153)                                         \
+  V(::, _sqrt, MathSqrt, 0x03183390)                                           \
+  V(::, _exp, MathExp, 0x00f4ffd0)                                             \
+  V(::, _log, MathLog, 0x09ae8462)                                             \
   V(Float32x4, _Float32x4FromDoubles, Float32x4FromDoubles, 0x1845792b)        \
   V(Float32x4, Float32x4.zero, Float32x4Zero, 0xd3b64002)                      \
   V(Float32x4, _Float32x4Splat, Float32x4Splat, 0x13a552c3)                    \
@@ -187,7 +187,7 @@
   V(_WeakProperty, get:value, WeakProperty_getValue, 0xd2f28aae)               \
   V(_WeakProperty, set:value, WeakProperty_setValue, 0x8b2bafab)               \
   V(::, _classRangeCheck, ClassRangeCheck, 0x00269620)                         \
-  V(::, _abi, FfiAbi, 0x7c4ab775)                                              \
+  V(::, _abi, FfiAbi, 0x7c4ab3b4)                                              \
   V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x92ae104f)                \
   V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x3ff5ae9c)        \
   V(::, _nativeEffect, NativeEffect, 0x61e00b59)                               \
@@ -201,7 +201,6 @@
   V(::, _loadUint16, FfiLoadUint16, 0x0cd660ab)                                \
   V(::, _loadUint32, FfiLoadUint32, 0xf66e9416)                                \
   V(::, _loadUint64, FfiLoadUint64, 0x0506018d)                                \
-  V(::, _loadIntPtr, FfiLoadIntPtr, 0xebd9b43e)                                \
   V(::, _loadFloat, FfiLoadFloat, 0xf8d9845d)                                  \
   V(::, _loadFloatUnaligned, FfiLoadFloatUnaligned, 0xc8c8dfff)                \
   V(::, _loadDouble, FfiLoadDouble, 0xf70cc619)                                \
@@ -217,7 +216,6 @@
   V(::, _storeUint16, FfiStoreUint16, 0xe2fdae9f)                              \
   V(::, _storeUint32, FfiStoreUint32, 0xe5d7ec86)                              \
   V(::, _storeUint64, FfiStoreUint64, 0xe2d935fa)                              \
-  V(::, _storeIntPtr, FfiStoreIntPtr, 0x080266a8)                              \
   V(::, _storeFloat, FfiStoreFloat, 0x6484f07e)                                \
   V(::, _storeFloatUnaligned, FfiStoreFloatUnaligned, 0x600a9203)              \
   V(::, _storeDouble, FfiStoreDouble, 0x42998c64)                              \
@@ -236,13 +234,13 @@
   V(::, _asExternalTypedDataFloat, FfiAsExternalTypedDataFloat, 0x6f465e0c)    \
   V(::, _asExternalTypedDataDouble, FfiAsExternalTypedDataDouble, 0x40cdd9e1)  \
   V(::, _getNativeField, GetNativeField, 0xa0139b85)                           \
-  V(::, reachabilityFence, ReachabilityFence, 0x619235c1)                      \
+  V(::, reachabilityFence, ReachabilityFence, 0x730f2b7f)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x1dcaf73d)                          \
   V(_Future, timeout, FutureTimeout, 0x73041520)                               \
   V(Future, wait, FutureWait, 0x495c83cd)                                      \
   V(_RootZone, runUnary, RootZoneRunUnary, 0xb607f8bf)                         \
   V(_FutureListener, handleValue, FutureListenerHandleValue, 0x438115a8)       \
-  V(::, has63BitSmis, Has63BitSmis, 0xf61b5ab2)                                \
+  V(::, has63BitSmis, Has63BitSmis, 0xf61b56f1)                                \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
diff --git a/runtime/vm/compiler/relocation_test.cc b/runtime/vm/compiler/relocation_test.cc
index f361bd8..4aec712 100644
--- a/runtime/vm/compiler/relocation_test.cc
+++ b/runtime/vm/compiler/relocation_test.cc
@@ -33,6 +33,10 @@
   static const intptr_t kOffsetOfCall = 4;
 #elif defined(TARGET_ARCH_ARM)
   static const intptr_t kOffsetOfCall = 4;
+#elif defined(TARGET_ARCH_RISCV32)
+  static const intptr_t kOffsetOfCall = 4;
+#elif defined(TARGET_ARCH_RISCV64)
+  static const intptr_t kOffsetOfCall = 4;
 #else
   static const intptr_t kOffsetOfCall = 0;
 #endif
@@ -85,6 +89,8 @@
                                    compiler::Address::PairPreIndex)));
 #elif defined(TARGET_ARCH_ARM)
       SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ PushList((1 << LR)));
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+          __ PushRegister(RA);
 #endif
       __ GenerateUnRelocatedPcRelativeCall();
       AddPcRelativeCallTargetAt(__ CodeSize(), code, target);
@@ -95,6 +101,8 @@
                                    compiler::Address::PairPostIndex)));
 #elif defined(TARGET_ARCH_ARM)
       RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ PopList((1 << LR)));
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+          __ PopRegister(RA);
 #endif
       __ Ret();
     });
@@ -107,6 +115,8 @@
       __ LoadImmediate(RAX, 42);
 #elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
       __ LoadImmediate(R0, 42);
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+          __ LoadImmediate(A0, 42);
 #endif
       __ Ret();
     });
@@ -129,6 +139,10 @@
       instructions ^= OldPage::ToExecutable(instructions.ptr());
       code.set_instructions(instructions);
     }
+    if (FLAG_disassemble) {
+      OS::PrintErr("Disassemble:\n");
+      code.Disassemble();
+    }
   }
 
   void AddPcRelativeCallTargetAt(intptr_t offset,
@@ -192,9 +206,9 @@
     typedef intptr_t (*Fun)() DART_UNUSED;
 #if defined(TARGET_ARCH_X64)
     EXPECT_EQ(42, reinterpret_cast<Fun>(entrypoint)());
-#elif defined(TARGET_ARCH_ARM)
+#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_RISCV32)
     EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Fun, entrypoint));
-#elif defined(TARGET_ARCH_ARM64)
+#elif defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV64)
     EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Fun, entrypoint));
 #endif
   }
@@ -275,8 +289,8 @@
   // instruction is emitted (not taking into account that the next instruction
   // might actually make some of those unresolved calls resolved).
   helper.CreateInstructions({
-      16,  // caller (call instruction @helper.kOffsetOfCall)
-      fmax - (16 - helper.kOffsetOfCall) - 8,  // 8 bytes less than maximum gap
+      20,  // caller (call instruction @helper.kOffsetOfCall)
+      fmax - (20 - helper.kOffsetOfCall) - 8,  // 8 bytes less than maximum gap
       8                                        // forward call target
   });
   helper.EmitPcRelativeCallFunction(0, 2);
@@ -301,8 +315,8 @@
   const intptr_t fmax = FLAG_upper_pc_relative_call_distance;
 
   helper.CreateInstructions({
-      16,  // caller (call instruction @helper.kOffsetOfCall)
-      fmax - (16 - helper.kOffsetOfCall) + 4,  // 4 bytes above maximum gap
+      20,  // caller (call instruction @helper.kOffsetOfCall)
+      fmax - (20 - helper.kOffsetOfCall) + 4,  // 4 bytes above maximum gap
       8                                        // forwards call target
   });
   helper.EmitPcRelativeCallFunction(0, 2);
@@ -333,7 +347,7 @@
   helper.CreateInstructions({
       8,                                // backwards call target
       bmax - 8 - helper.kOffsetOfCall,  // maximize out backwards call range
-      16  // caller (call instruction @helper.kOffsetOfCall)
+      20  // caller (call instruction @helper.kOffsetOfCall)
   });
   helper.EmitReturn42Function(0);
   helper.EmitPcRelativeCallFunction(2, 0);
@@ -360,8 +374,8 @@
   helper.CreateInstructions({
       8,                                    // backward call target
       bmax - 8 - helper.kOffsetOfCall + 4,  // 4 bytes exceeding backwards range
-      16,  // caller (call instruction @helper.kOffsetOfCall)
-      fmax - (16 - helper.kOffsetOfCall) -
+      20,  // caller (call instruction @helper.kOffsetOfCall)
+      fmax - (20 - helper.kOffsetOfCall) -
           4,  // 4 bytes less than forward range
       4,
       4,  // out-of-range, so trampoline has to be inserted before this
@@ -399,7 +413,7 @@
   helper.CreateInstructions({
       8,                                    // backwards call target
       bmax - 8 - helper.kOffsetOfCall + 4,  // 4 bytes exceeding backwards range
-      16,  // caller (call instruction @helper.kOffsetOfCall)
+      20,  // caller (call instruction @helper.kOffsetOfCall)
       4,
   });
   helper.EmitReturn42Function(0);
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index bc2daf8..a0cca50 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -101,6 +101,11 @@
   if (obj.IsNull()) {
     return kNullIdentityHash;
   }
+  // TypeArguments should be handled before Instance as TypeArguments extends
+  // Instance and TypeArguments::CanonicalizeHash just returns 0.
+  if (obj.IsTypeArguments()) {
+    return TypeArguments::Cast(obj).Hash();
+  }
   if (obj.IsInstance()) {
     return Instance::Cast(obj).CanonicalizeHash();
   }
@@ -121,6 +126,10 @@
   return obj.GetClassId();
 }
 
+const char* ObjectToCString(const Object& obj) {
+  return obj.ToCString();
+}
+
 void SetToNull(Object* obj) {
   *obj = Object::null();
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index c7fd307..af57f4ef 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -181,6 +181,9 @@
 // or canonical hash.
 intptr_t ObjectHash(const Object& obj);
 
+// Prints the given object into a C string.
+const char* ObjectToCString(const Object& obj);
+
 // If the given object represents a Dart integer returns true and sets [value]
 // to the value of the integer.
 bool HasIntegerValue(const dart::Object& obj, int64_t* value);
@@ -1176,6 +1179,7 @@
   static word deoptimize_stub_offset();
   static word enter_safepoint_stub_offset();
   static word exit_safepoint_stub_offset();
+  static word exit_safepoint_ignore_unwind_in_progress_stub_offset();
   static word call_native_through_safepoint_stub_offset();
   static word call_native_through_safepoint_entry_point_offset();
 
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 5d764cf..adeab04 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -219,11 +219,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    152;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 108;
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    172;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -242,93 +243,95 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 380;
+    Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    752;
+    760;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    756;
+    764;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 272;
+    Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 288;
+    Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 292;
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 296;
+    Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 204;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 792;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 800;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 276;
+    Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 816;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 824;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 796;
+    Thread_double_truncate_round_supported_offset = 804;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    320;
+    324;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     236;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    360;
+    364;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 356;
+    Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    772;
+    780;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 264;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 324;
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 372;
+    Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 368;
+    Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    364;
+    368;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 376;
+    Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    760;
+    768;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    788;
+    796;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 828;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -340,13 +343,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 308;
+    Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 312;
+    Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -369,27 +372,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 764;
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 772;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 768;
+    Thread_saved_shadow_call_stack_offset = 776;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    776;
+    784;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 332;
+    Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -406,17 +409,17 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 268;
+    Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     32;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 780;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 788;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 784;
-static constexpr dart::compiler::target::word Thread_random_offset = 800;
+    Thread_callback_stack_return_offset = 792;
+static constexpr dart::compiler::target::word Thread_random_offset = 808;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 808;
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 816;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -485,7 +488,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        720, 724, 728, 732, 736, -1, 740, -1, 744, 748, -1, -1, -1, -1, -1, -1};
+        728, 732, 736, 740, 744, -1, 748, -1, 752, 756, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -782,12 +785,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -807,95 +810,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1592;
+    Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -907,13 +912,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -936,27 +941,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1528;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1536;
+    Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -973,18 +978,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word Thread_random_offset = 1600;
+    Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1624;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -1055,8 +1060,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -1351,11 +1356,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    152;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 108;
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    172;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -1374,93 +1380,95 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 380;
+    Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
+    728;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    724;
+    732;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 272;
+    Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 288;
+    Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 292;
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 296;
+    Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 204;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 768;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 276;
+    Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 784;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 792;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 764;
+    Thread_double_truncate_round_supported_offset = 772;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    320;
+    324;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     236;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    360;
+    364;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 356;
+    Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    748;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 264;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 324;
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 372;
+    Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 368;
+    Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    364;
+    368;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 376;
+    Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    756;
+    764;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 796;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -1472,13 +1480,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 308;
+    Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 312;
+    Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -1501,27 +1509,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 740;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 744;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    752;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 332;
+    Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -1538,17 +1546,17 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 268;
+    Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     32;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 756;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 752;
-static constexpr dart::compiler::target::word Thread_random_offset = 768;
+    Thread_callback_stack_return_offset = 760;
+static constexpr dart::compiler::target::word Thread_random_offset = 776;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 776;
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 784;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -1911,12 +1919,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -1936,95 +1944,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1704;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1656;
+    Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1640;
+    1656;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -2036,13 +2046,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -2065,27 +2075,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1592;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1608;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1600;
+    Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1616;
+    1632;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -2102,18 +2112,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word Thread_random_offset = 1664;
+    Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1688;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -2184,9 +2194,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -2481,12 +2491,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2506,95 +2516,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1592;
+    Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -2606,13 +2618,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -2635,27 +2647,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1528;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1536;
+    Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -2672,18 +2684,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word Thread_random_offset = 1600;
+    Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1624;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -2754,8 +2766,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -3050,12 +3062,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -3075,95 +3087,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1704;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1656;
+    Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1640;
+    1656;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -3175,13 +3189,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -3204,27 +3218,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1592;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1608;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1600;
+    Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1616;
+    1632;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -3241,18 +3255,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word Thread_random_offset = 1664;
+    Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1688;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -3323,9 +3337,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -3418,6 +3432,1146 @@
     WeakSerializationReference_InstanceSize = 16;
 #endif  // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
 
+#if defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    72;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 16;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
+static constexpr dart::compiler::target::word Array_element_size = 4;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
+static constexpr dart::compiler::target::word Code_elements_start_offset = 96;
+static constexpr dart::compiler::target::word Code_element_size = 4;
+static constexpr dart::compiler::target::word Context_elements_start_offset =
+    12;
+static constexpr dart::compiler::target::word Context_element_size = 4;
+static constexpr dart::compiler::target::word
+    ContextScope_elements_start_offset = 12;
+static constexpr dart::compiler::target::word ContextScope_element_size = 32;
+static constexpr dart::compiler::target::word
+    ExceptionHandlers_elements_start_offset = 12;
+static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
+    12;
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    8;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word
+    OneByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word OneByteString_element_size = 1;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 20;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
+static constexpr dart::compiler::target::word
+    TwoByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word TwoByteString_element_size = 2;
+static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word Context_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word TypeArguments_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_size_offset =
+    20;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 28;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 24;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word Array_data_offset = 12;
+static constexpr dart::compiler::target::word Array_length_offset = 8;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    52;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    88;
+static constexpr dart::compiler::target::word Class_super_type_offset = 44;
+static constexpr dart::compiler::target::word
+    Class_host_type_arguments_field_offset_in_words_offset = 100;
+static constexpr dart::compiler::target::word
+    SharedClassTable_class_heap_stats_table_offset = 0;
+static constexpr dart::compiler::target::word Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    ClosureData_default_type_arguments_kind_offset = 16;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    24;
+static constexpr dart::compiler::target::word Code_owner_offset = 28;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
+static constexpr dart::compiler::target::word Context_parent_offset = 8;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    Field_initializer_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Field_host_offset_or_field_id_offset = 20;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 44;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 52;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    24;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
+static constexpr dart::compiler::target::word Function_code_offset = 32;
+static constexpr dart::compiler::target::word Function_data_offset = 24;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    4, 8};
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
+static constexpr dart::compiler::target::word Function_packed_fields_offset =
+    83;
+static constexpr dart::compiler::target::word Function_signature_offset = 20;
+static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
+    4;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word OldPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
+static constexpr dart::compiler::target::word ICData_owner_offset = 20;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
+static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
+    20;
+static constexpr dart::compiler::target::word
+    IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ImmutableLinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_deleted_keys_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
+    8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
+    16;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    4;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    12;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
+static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    4;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    8;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::compiler::target::word String_hash_offset = 8;
+static constexpr dart::compiler::target::word String_length_offset = 4;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 384;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    800;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    804;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 292;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 300;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 204;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 840;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
+static constexpr dart::compiler::target::word
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 864;
+static constexpr dart::compiler::target::word
+    Thread_dispatch_table_array_offset = 44;
+static constexpr dart::compiler::target::word
+    Thread_double_truncate_round_supported_offset = 844;
+static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
+    320;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    324;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    236;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    364;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 360;
+static constexpr dart::compiler::target::word Thread_end_offset = 52;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    820;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 260;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 136;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 132;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 372;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    368;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 380;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    808;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 140;
+static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
+    836;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 868;
+static constexpr dart::compiler::target::word Thread_field_table_values_offset =
+    64;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 244;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 252;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 80;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 312;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_entry_offset = 316;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_stub_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_without_fpu_regs_stub_offset = 148;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 164;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 176;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 812;
+static constexpr dart::compiler::target::word
+    Thread_saved_shadow_call_stack_offset = 816;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    824;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_entry_point_offset = 336;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    56;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 60;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    76;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 72;
+static constexpr dart::compiler::target::word Thread_top_offset = 48;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 16;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_double_runtime_arg_offset = 104;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 88;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    124;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 272;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    32;
+static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 828;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 832;
+static constexpr dart::compiler::target::word Thread_random_offset = 848;
+static constexpr dart::compiler::target::word
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 856;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
+    0;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
+    4;
+static constexpr dart::compiler::target::word TsanUtils_exception_pc_offset = 8;
+static constexpr dart::compiler::target::word TsanUtils_exception_sp_offset =
+    12;
+static constexpr dart::compiler::target::word TsanUtils_exception_fp_offset =
+    16;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Type_hash_offset = 16;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
+static constexpr dart::compiler::target::word Type_type_state_offset = 22;
+static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
+static constexpr dart::compiler::target::word
+    FunctionType_named_parameter_names_offset = 24;
+static constexpr dart::compiler::target::word FunctionType_nullability_offset =
+    39;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_parameter_counts_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_type_parameter_counts_offset = 36;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
+static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
+    25;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
+static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word
+    UnhandledException_exception_offset = 4;
+static constexpr dart::compiler::target::word
+    UnhandledException_stacktrace_offset = 8;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_expected_cid_offset = 4;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_entrypoint_offset = 8;
+static constexpr dart::compiler::target::word WeakProperty_key_offset = 4;
+static constexpr dart::compiler::target::word WeakProperty_value_offset = 8;
+static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
+    4, 12, 8, 16};
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,  -1,  -1, -1, -1, 728, 732, 736, -1,  -1,  740,
+        744, 748, -1, -1, -1, 752, 756, 760, 764, 768, 772,
+        776, 780, -1, -1, -1, -1,  784, 788, 792, 796};
+static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
+static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
+static constexpr dart::compiler::target::word Array_header_size = 12;
+static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
+static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_ObjectHeaderSize = 4;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word Context_header_size = 12;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word ExternalTypedData_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
+static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 20;
+static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
+static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
+    60;
+static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
+static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_InstanceSize = 28;
+static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word MirrorReference_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_InstanceSize = 12;
+static constexpr dart::compiler::target::word Namespace_InstanceSize = 20;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
+static constexpr dart::compiler::target::word Number_InstanceSize = 4;
+static constexpr dart::compiler::target::word Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
+static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
+static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 20;
+static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
+static constexpr dart::compiler::target::word Script_InstanceSize = 48;
+static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
+static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
+static constexpr dart::compiler::target::word String_InstanceSize = 12;
+static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize = 8;
+static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    TransferableTypedData_InstanceSize = 4;
+static constexpr dart::compiler::target::word Type_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
+static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 20;
+static constexpr dart::compiler::target::word UnhandledException_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word UnlinkedCall_InstanceSize = 16;
+static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12;
+static constexpr dart::compiler::target::word UserTag_InstanceSize = 16;
+static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    WeakSerializationReference_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+
+#if defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    112;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 32;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
+static constexpr dart::compiler::target::word Array_element_size = 8;
+static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
+    0;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
+static constexpr dart::compiler::target::word Code_elements_start_offset = 176;
+static constexpr dart::compiler::target::word Code_element_size = 4;
+static constexpr dart::compiler::target::word Context_elements_start_offset =
+    24;
+static constexpr dart::compiler::target::word Context_element_size = 8;
+static constexpr dart::compiler::target::word
+    ContextScope_elements_start_offset = 16;
+static constexpr dart::compiler::target::word ContextScope_element_size = 64;
+static constexpr dart::compiler::target::word
+    ExceptionHandlers_elements_start_offset = 24;
+static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
+    12;
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    16;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word
+    OneByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word OneByteString_element_size = 1;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 40;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
+static constexpr dart::compiler::target::word
+    TwoByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word TwoByteString_element_size = 2;
+static constexpr dart::compiler::target::word Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word Context_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
+static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word TypeArguments_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    32;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_size_offset =
+    40;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 56;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 48;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word Array_data_offset = 24;
+static constexpr dart::compiler::target::word Array_length_offset = 16;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    104;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    164;
+static constexpr dart::compiler::target::word Class_super_type_offset = 88;
+static constexpr dart::compiler::target::word
+    Class_host_type_arguments_field_offset_in_words_offset = 176;
+static constexpr dart::compiler::target::word
+    SharedClassTable_class_heap_stats_table_offset = 0;
+static constexpr dart::compiler::target::word Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    ClosureData_default_type_arguments_kind_offset = 32;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    48;
+static constexpr dart::compiler::target::word Code_owner_offset = 56;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
+static constexpr dart::compiler::target::word Context_parent_offset = 16;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    Field_initializer_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Field_host_offset_or_field_id_offset = 40;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 80;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 88;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    48;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
+static constexpr dart::compiler::target::word Function_code_offset = 64;
+static constexpr dart::compiler::target::word Function_data_offset = 48;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    8, 16};
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
+static constexpr dart::compiler::target::word Function_packed_fields_offset =
+    123;
+static constexpr dart::compiler::target::word Function_signature_offset = 40;
+static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
+    8;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word OldPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
+static constexpr dart::compiler::target::word ICData_owner_offset = 40;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
+static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
+static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
+    40;
+static constexpr dart::compiler::target::word
+    IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    ImmutableLinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_deleted_keys_offset = 40;
+static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
+    16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
+    32;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    8;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    24;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    360;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    208;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
+static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    16;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::compiler::target::word String_hash_offset = 4;
+static constexpr dart::compiler::target::word String_length_offset = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 744;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    1576;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1584;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 528;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 560;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 576;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 384;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
+    1656;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
+static constexpr dart::compiler::target::word
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1696;
+static constexpr dart::compiler::target::word
+    Thread_dispatch_table_array_offset = 88;
+static constexpr dart::compiler::target::word
+    Thread_double_truncate_round_supported_offset = 1664;
+static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
+    616;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    624;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    448;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    704;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 696;
+static constexpr dart::compiler::target::word Thread_end_offset = 104;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 488;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1616;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 496;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 728;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 720;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    712;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 736;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    1592;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
+    1648;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset =
+    1704;
+static constexpr dart::compiler::target::word Thread_field_table_values_offset =
+    128;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 456;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 464;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 480;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 600;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_entry_offset = 608;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_stub_offset = 408;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_without_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 320;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1600;
+static constexpr dart::compiler::target::word
+    Thread_saved_shadow_call_stack_offset = 1608;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    1624;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_entry_point_offset = 648;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    112;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    152;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 144;
+static constexpr dart::compiler::target::word Thread_top_offset = 96;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 32;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_double_runtime_arg_offset = 192;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 176;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    224;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 520;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    64;
+static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
+static constexpr dart::compiler::target::word Thread_callback_code_offset =
+    1632;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1640;
+static constexpr dart::compiler::target::word Thread_random_offset = 1672;
+static constexpr dart::compiler::target::word
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1680;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
+    0;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
+    8;
+static constexpr dart::compiler::target::word TsanUtils_exception_pc_offset =
+    16;
+static constexpr dart::compiler::target::word TsanUtils_exception_sp_offset =
+    24;
+static constexpr dart::compiler::target::word TsanUtils_exception_fp_offset =
+    32;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
+    16;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
+static constexpr dart::compiler::target::word Type_type_state_offset = 42;
+static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
+static constexpr dart::compiler::target::word
+    FunctionType_named_parameter_names_offset = 48;
+static constexpr dart::compiler::target::word FunctionType_nullability_offset =
+    71;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_parameter_counts_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_type_parameter_counts_offset = 68;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
+static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
+    45;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
+static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word
+    UnhandledException_exception_offset = 8;
+static constexpr dart::compiler::target::word
+    UnhandledException_stacktrace_offset = 16;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_expected_cid_offset = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_entrypoint_offset = 16;
+static constexpr dart::compiler::target::word WeakProperty_key_offset = 8;
+static constexpr dart::compiler::target::word WeakProperty_value_offset = 16;
+static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
+    8, 24, 16, 32};
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,   -1,   -1, -1, -1, 1432, 1440, 1448, -1,   -1,   1456,
+        1464, 1472, -1, -1, -1, 1480, 1488, 1496, 1504, 1512, 1520,
+        1528, 1536, -1, -1, -1, -1,   1544, 1552, 1560, 1568};
+static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
+static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
+static constexpr dart::compiler::target::word Array_header_size = 24;
+static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
+static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word Class_InstanceSize = 192;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_ObjectHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word Context_header_size = 24;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word ExternalTypedData_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
+static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 40;
+static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
+static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
+    120;
+static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
+static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
+static constexpr dart::compiler::target::word LinkedHashBase_InstanceSize = 56;
+static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word MirrorReference_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_InstanceSize = 24;
+static constexpr dart::compiler::target::word Namespace_InstanceSize = 40;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
+static constexpr dart::compiler::target::word Number_InstanceSize = 8;
+static constexpr dart::compiler::target::word Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
+static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
+static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 40;
+static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
+static constexpr dart::compiler::target::word Script_InstanceSize = 80;
+static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
+static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
+static constexpr dart::compiler::target::word String_InstanceSize = 16;
+static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    TransferableTypedData_InstanceSize = 8;
+static constexpr dart::compiler::target::word Type_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 40;
+static constexpr dart::compiler::target::word UnhandledException_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word UnlinkedCall_InstanceSize = 32;
+static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24;
+static constexpr dart::compiler::target::word UserTag_InstanceSize = 32;
+static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    WeakSerializationReference_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+
 #else  // !defined(PRODUCT)
 
 #if defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
@@ -3616,11 +4770,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    152;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 108;
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    172;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -3639,93 +4794,95 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 380;
+    Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    752;
+    760;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    756;
+    764;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 272;
+    Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 288;
+    Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 292;
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 296;
+    Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 204;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 792;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 800;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 276;
+    Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 816;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 824;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 796;
+    Thread_double_truncate_round_supported_offset = 804;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    320;
+    324;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     236;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    360;
+    364;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 356;
+    Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    772;
+    780;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 264;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 324;
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 372;
+    Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 368;
+    Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    364;
+    368;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 376;
+    Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    760;
+    768;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    788;
+    796;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 828;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -3737,13 +4894,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 308;
+    Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 312;
+    Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -3766,27 +4923,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 764;
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 772;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 768;
+    Thread_saved_shadow_call_stack_offset = 776;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    776;
+    784;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 332;
+    Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -3803,17 +4960,17 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 268;
+    Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     32;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 780;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 788;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 784;
-static constexpr dart::compiler::target::word Thread_random_offset = 800;
+    Thread_callback_stack_return_offset = 792;
+static constexpr dart::compiler::target::word Thread_random_offset = 808;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 808;
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 816;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -3882,7 +5039,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        720, 724, 728, 732, 736, -1, 740, -1, 744, 748, -1, -1, -1, -1, -1, -1};
+        728, 732, 736, 740, 744, -1, 748, -1, 752, 756, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -4173,12 +5330,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -4198,95 +5355,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1592;
+    Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -4298,13 +5457,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -4327,27 +5486,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1528;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1536;
+    Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -4364,18 +5523,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word Thread_random_offset = 1600;
+    Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1624;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -4446,8 +5605,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -4736,11 +5895,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    152;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 108;
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    172;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -4759,93 +5919,95 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 380;
+    Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
+    728;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    724;
+    732;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 272;
+    Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 288;
+    Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 292;
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 296;
+    Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 204;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 768;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 276;
+    Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 784;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 792;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 764;
+    Thread_double_truncate_round_supported_offset = 772;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    320;
+    324;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     236;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    360;
+    364;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 356;
+    Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    748;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 264;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 324;
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 372;
+    Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 368;
+    Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    364;
+    368;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 376;
+    Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    756;
+    764;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 796;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -4857,13 +6019,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 308;
+    Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 312;
+    Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -4886,27 +6048,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 740;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 744;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    752;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 332;
+    Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -4923,17 +6085,17 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     124;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 268;
+    Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     32;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 756;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 752;
-static constexpr dart::compiler::target::word Thread_random_offset = 768;
+    Thread_callback_stack_return_offset = 760;
+static constexpr dart::compiler::target::word Thread_random_offset = 776;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 776;
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 784;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -5290,12 +6452,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -5315,95 +6477,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1704;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1656;
+    Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1640;
+    1656;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -5415,13 +6579,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -5444,27 +6608,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1592;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1608;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1600;
+    Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1616;
+    1632;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -5481,18 +6645,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word Thread_random_offset = 1664;
+    Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1688;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -5563,9 +6727,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -5854,12 +7018,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -5879,95 +7043,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1592;
+    Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -5979,13 +7145,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -6008,27 +7174,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1528;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1536;
+    Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -6045,18 +7211,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word Thread_random_offset = 1600;
+    Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1624;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -6127,8 +7293,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -6417,12 +7583,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    304;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 216;
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    344;
+    360;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -6442,95 +7608,97 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 736;
+    Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 520;
+    Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_entry_point_offset = 552;
+    Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_parameterized_entry_point_offset = 560;
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    Thread_allocate_object_slow_entry_point_offset = 568;
+    Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
 static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 528;
+    Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1704;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_double_truncate_round_supported_offset = 1656;
+    Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    616;
+    624;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
     448;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 688;
+    Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 504;
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 624;
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 720;
+    Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 712;
+    Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    704;
+    712;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 728;
+    Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1640;
+    1656;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
 static constexpr dart::compiler::target::word
@@ -6542,13 +7710,13 @@
 static constexpr dart::compiler::target::word
     Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 592;
+    Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    Thread_switchable_call_miss_entry_offset = 600;
+    Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -6571,27 +7739,27 @@
     Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1592;
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1608;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1600;
+    Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1616;
+    1632;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_entry_point_offset = 640;
+    Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
 static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
     112;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
@@ -6608,18 +7776,18 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
     224;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 512;
+    Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     64;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word Thread_random_offset = 1664;
+    Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1688;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
     0;
 static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -6690,9 +7858,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -6785,6 +7953,1134 @@
     WeakSerializationReference_InstanceSize = 16;
 #endif  // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
 
+#if defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    72;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 16;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
+static constexpr dart::compiler::target::word Array_element_size = 4;
+static constexpr dart::compiler::target::word Code_elements_start_offset = 76;
+static constexpr dart::compiler::target::word Code_element_size = 4;
+static constexpr dart::compiler::target::word Context_elements_start_offset =
+    12;
+static constexpr dart::compiler::target::word Context_element_size = 4;
+static constexpr dart::compiler::target::word
+    ContextScope_elements_start_offset = 12;
+static constexpr dart::compiler::target::word ContextScope_element_size = 32;
+static constexpr dart::compiler::target::word
+    ExceptionHandlers_elements_start_offset = 12;
+static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
+    12;
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    8;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word
+    OneByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word OneByteString_element_size = 1;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 20;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
+static constexpr dart::compiler::target::word
+    TwoByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word TwoByteString_element_size = 2;
+static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word Context_kMaxElements = 268435455;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word TypeArguments_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_size_offset =
+    20;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 28;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 24;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word Array_data_offset = 12;
+static constexpr dart::compiler::target::word Array_length_offset = 8;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    48;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    84;
+static constexpr dart::compiler::target::word Class_super_type_offset = 40;
+static constexpr dart::compiler::target::word
+    Class_host_type_arguments_field_offset_in_words_offset = 96;
+static constexpr dart::compiler::target::word Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    ClosureData_default_type_arguments_kind_offset = 16;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    24;
+static constexpr dart::compiler::target::word Code_owner_offset = 28;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
+static constexpr dart::compiler::target::word Context_parent_offset = 8;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    Field_initializer_function_offset = 16;
+static constexpr dart::compiler::target::word
+    Field_host_offset_or_field_id_offset = 20;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 44;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 52;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    24;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
+static constexpr dart::compiler::target::word Function_code_offset = 32;
+static constexpr dart::compiler::target::word Function_data_offset = 24;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    4, 8};
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
+static constexpr dart::compiler::target::word Function_packed_fields_offset =
+    83;
+static constexpr dart::compiler::target::word Function_signature_offset = 20;
+static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
+    4;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word OldPage_card_table_offset = 20;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 8;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word ICData_entries_offset = 12;
+static constexpr dart::compiler::target::word ICData_owner_offset = 20;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
+static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
+static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
+    20;
+static constexpr dart::compiler::target::word
+    IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    ImmutableLinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_deleted_keys_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
+    8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
+    16;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    12;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    4;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    12;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    160;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    180;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    104;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
+static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    4;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    8;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::compiler::target::word String_hash_offset = 8;
+static constexpr dart::compiler::target::word String_length_offset = 4;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 384;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    800;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    804;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 292;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 300;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 204;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 840;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 348;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 120;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 116;
+static constexpr dart::compiler::target::word
+    Thread_bootstrap_native_wrapper_entry_point_offset = 340;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 864;
+static constexpr dart::compiler::target::word
+    Thread_dispatch_table_array_offset = 44;
+static constexpr dart::compiler::target::word
+    Thread_double_truncate_round_supported_offset = 844;
+static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
+    320;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 232;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    324;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    236;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    364;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 360;
+static constexpr dart::compiler::target::word Thread_end_offset = 52;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    820;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 260;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 136;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 132;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 372;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    368;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 380;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    808;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 140;
+static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
+    836;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 868;
+static constexpr dart::compiler::target::word Thread_field_table_values_offset =
+    64;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 244;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 252;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 80;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 312;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_entry_offset = 316;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_stub_offset = 216;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_without_fpu_regs_stub_offset = 148;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 164;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 176;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 812;
+static constexpr dart::compiler::target::word
+    Thread_saved_shadow_call_stack_offset = 816;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    824;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_entry_point_offset = 336;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 28;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    56;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 60;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    76;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 72;
+static constexpr dart::compiler::target::word Thread_top_offset = 48;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 16;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_double_runtime_arg_offset = 104;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 88;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    124;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 272;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    32;
+static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 828;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 832;
+static constexpr dart::compiler::target::word Thread_random_offset = 848;
+static constexpr dart::compiler::target::word
+    Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 856;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
+    0;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
+    4;
+static constexpr dart::compiler::target::word TsanUtils_exception_pc_offset = 8;
+static constexpr dart::compiler::target::word TsanUtils_exception_sp_offset =
+    12;
+static constexpr dart::compiler::target::word TsanUtils_exception_fp_offset =
+    16;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
+static constexpr dart::compiler::target::word Type_arguments_offset = 12;
+static constexpr dart::compiler::target::word Type_hash_offset = 16;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
+static constexpr dart::compiler::target::word Type_type_state_offset = 22;
+static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
+static constexpr dart::compiler::target::word
+    FunctionType_named_parameter_names_offset = 24;
+static constexpr dart::compiler::target::word FunctionType_nullability_offset =
+    39;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_parameter_counts_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_type_parameter_counts_offset = 36;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
+static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
+    25;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
+static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word
+    UnhandledException_exception_offset = 4;
+static constexpr dart::compiler::target::word
+    UnhandledException_stacktrace_offset = 8;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_expected_cid_offset = 4;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_entrypoint_offset = 8;
+static constexpr dart::compiler::target::word WeakProperty_key_offset = 4;
+static constexpr dart::compiler::target::word WeakProperty_value_offset = 8;
+static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
+    4, 12, 8, 16};
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,  -1,  -1, -1, -1, 728, 732, 736, -1,  -1,  740,
+        744, 748, -1, -1, -1, 752, 756, 760, 764, 768, 772,
+        776, 780, -1, -1, -1, -1,  784, 788, 792, 796};
+static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
+static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
+static constexpr dart::compiler::target::word Array_header_size = 12;
+static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
+static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word Class_InstanceSize = 108;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_ObjectHeaderSize = 4;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word Context_header_size = 12;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word ExternalTypedData_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
+static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    8;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 20;
+static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
+static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
+    60;
+static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
+static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_InstanceSize = 28;
+static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word MirrorReference_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_InstanceSize = 12;
+static constexpr dart::compiler::target::word Namespace_InstanceSize = 20;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
+static constexpr dart::compiler::target::word Number_InstanceSize = 4;
+static constexpr dart::compiler::target::word Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
+static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
+static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
+static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
+static constexpr dart::compiler::target::word Script_InstanceSize = 48;
+static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
+static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
+static constexpr dart::compiler::target::word String_InstanceSize = 12;
+static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize = 8;
+static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    TransferableTypedData_InstanceSize = 4;
+static constexpr dart::compiler::target::word Type_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
+static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 20;
+static constexpr dart::compiler::target::word UnhandledException_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word UnlinkedCall_InstanceSize = 16;
+static constexpr dart::compiler::target::word UnwindError_InstanceSize = 12;
+static constexpr dart::compiler::target::word UserTag_InstanceSize = 16;
+static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    WeakSerializationReference_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+
+#if defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word Function_usage_counter_offset =
+    112;
+static constexpr dart::compiler::target::word
+    ICData_receivers_static_type_offset = 32;
+static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
+static constexpr dart::compiler::target::word Array_element_size = 8;
+static constexpr dart::compiler::target::word Code_elements_start_offset = 144;
+static constexpr dart::compiler::target::word Code_element_size = 4;
+static constexpr dart::compiler::target::word Context_elements_start_offset =
+    24;
+static constexpr dart::compiler::target::word Context_element_size = 8;
+static constexpr dart::compiler::target::word
+    ContextScope_elements_start_offset = 16;
+static constexpr dart::compiler::target::word ContextScope_element_size = 64;
+static constexpr dart::compiler::target::word
+    ExceptionHandlers_elements_start_offset = 24;
+static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
+    12;
+static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
+    16;
+static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word
+    OneByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word OneByteString_element_size = 1;
+static constexpr dart::compiler::target::word
+    TypeArguments_elements_start_offset = 40;
+static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
+static constexpr dart::compiler::target::word
+    TwoByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word TwoByteString_element_size = 2;
+static constexpr dart::compiler::target::word Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word Context_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
+static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
+static constexpr dart::compiler::target::word
+    NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::compiler::target::word TypeArguments_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
+    32;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_size_offset =
+    40;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_first_named_entry_offset = 56;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
+    0;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_positional_count_offset = 48;
+static constexpr dart::compiler::target::word
+    ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word Array_data_offset = 24;
+static constexpr dart::compiler::target::word Array_length_offset = 16;
+static constexpr dart::compiler::target::word Array_tags_offset = 0;
+static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word Class_declaration_type_offset =
+    96;
+static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
+    156;
+static constexpr dart::compiler::target::word Class_super_type_offset = 80;
+static constexpr dart::compiler::target::word
+    Class_host_type_arguments_field_offset_in_words_offset = 168;
+static constexpr dart::compiler::target::word Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    ClosureData_default_type_arguments_kind_offset = 32;
+static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word Code_saved_instructions_offset =
+    48;
+static constexpr dart::compiler::target::word Code_owner_offset = 56;
+static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
+static constexpr dart::compiler::target::word Context_parent_offset = 16;
+static constexpr dart::compiler::target::word Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    Field_initializer_function_offset = 32;
+static constexpr dart::compiler::target::word
+    Field_host_offset_or_field_id_offset = 40;
+static constexpr dart::compiler::target::word Field_guarded_cid_offset = 80;
+static constexpr dart::compiler::target::word
+    Field_guarded_list_length_in_object_offset_offset = 88;
+static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
+    48;
+static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
+static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
+static constexpr dart::compiler::target::word Function_code_offset = 64;
+static constexpr dart::compiler::target::word Function_data_offset = 48;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    8, 16};
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
+static constexpr dart::compiler::target::word Function_packed_fields_offset =
+    123;
+static constexpr dart::compiler::target::word Function_signature_offset = 40;
+static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
+    8;
+static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word OldPage_card_table_offset = 40;
+static constexpr dart::compiler::target::word
+    CallSiteData_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word ICData_entries_offset = 24;
+static constexpr dart::compiler::target::word ICData_owner_offset = 40;
+static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
+static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
+static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
+static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
+    40;
+static constexpr dart::compiler::target::word
+    IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    ImmutableLinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_deleted_keys_offset = 40;
+static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
+    16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
+static constexpr dart::compiler::target::word
+    LinkedHashBase_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
+    32;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
+    24;
+static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 32;
+static constexpr dart::compiler::target::word Mint_value_offset = 8;
+static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
+    8;
+static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
+static constexpr dart::compiler::target::word NativeArguments_retval_offset =
+    24;
+static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
+    320;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
+    360;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+    208;
+static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
+static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
+    8;
+static constexpr dart::compiler::target::word
+    SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
+    16;
+static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::compiler::target::word String_hash_offset = 4;
+static constexpr dart::compiler::target::word String_length_offset = 8;
+static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    Thread_AllocateArray_entry_point_offset = 744;
+static constexpr dart::compiler::target::word Thread_active_exception_offset =
+    1576;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1584;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_array_write_barrier_entry_point_offset = 528;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_entry_point_offset = 560;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_entry_point_offset = 568;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_parameterized_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_entry_point_offset = 576;
+static constexpr dart::compiler::target::word
+    Thread_allocate_object_slow_stub_offset = 384;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
+    1656;
+static constexpr dart::compiler::target::word
+    Thread_auto_scope_native_wrapper_entry_point_offset = 672;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 208;
+static constexpr dart::compiler::target::word
+    Thread_bootstrap_native_wrapper_entry_point_offset = 656;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1696;
+static constexpr dart::compiler::target::word
+    Thread_dispatch_table_array_offset = 88;
+static constexpr dart::compiler::target::word
+    Thread_double_truncate_round_supported_offset = 1664;
+static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
+    616;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 440;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    624;
+static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
+    448;
+static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
+    704;
+static constexpr dart::compiler::target::word
+    Thread_double_negate_address_offset = 696;
+static constexpr dart::compiler::target::word Thread_end_offset = 104;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 488;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1616;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 496;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 632;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 248;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 728;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 720;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    712;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 736;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
+    1592;
+static constexpr dart::compiler::target::word
+    Thread_invoke_dart_code_stub_offset = 256;
+static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
+    1648;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset =
+    1704;
+static constexpr dart::compiler::target::word Thread_field_table_values_offset =
+    128;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_return_stub_offset = 456;
+static constexpr dart::compiler::target::word
+    Thread_lazy_deopt_from_throw_stub_offset = 464;
+static constexpr dart::compiler::target::word
+    Thread_lazy_specialize_type_test_stub_offset = 480;
+static constexpr dart::compiler::target::word
+    Thread_marking_stack_block_offset = 160;
+static constexpr dart::compiler::target::word
+    Thread_megamorphic_call_checked_entry_offset = 600;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_entry_offset = 608;
+static constexpr dart::compiler::target::word
+    Thread_switchable_call_miss_stub_offset = 408;
+static constexpr dart::compiler::target::word
+    Thread_no_scope_native_wrapper_entry_point_offset = 664;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word
+    Thread_late_initialization_error_shared_without_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
+static constexpr dart::compiler::target::word
+    Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 320;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_with_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
+static constexpr dart::compiler::target::word
+    Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1600;
+static constexpr dart::compiler::target::word
+    Thread_saved_shadow_call_stack_offset = 1608;
+static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
+    1624;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_stub_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_slow_type_test_entry_point_offset = 648;
+static constexpr dart::compiler::target::word Thread_stack_limit_offset = 56;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    112;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_flags_offset = 120;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
+static constexpr dart::compiler::target::word
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
+static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
+    152;
+static constexpr dart::compiler::target::word
+    Thread_top_exit_frame_info_offset = 144;
+static constexpr dart::compiler::target::word Thread_top_offset = 96;
+static constexpr dart::compiler::target::word Thread_top_resource_offset = 32;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word
+    Thread_unboxed_double_runtime_arg_offset = 192;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 176;
+static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
+    224;
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_entry_point_offset = 520;
+static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
+    64;
+static constexpr dart::compiler::target::word Thread_heap_base_offset = 72;
+static constexpr dart::compiler::target::word Thread_callback_code_offset =
+    1632;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1640;
+static constexpr dart::compiler::target::word Thread_random_offset = 1672;
+static constexpr dart::compiler::target::word
+    Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1680;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
+    0;
+static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
+    8;
+static constexpr dart::compiler::target::word TsanUtils_exception_pc_offset =
+    16;
+static constexpr dart::compiler::target::word TsanUtils_exception_sp_offset =
+    24;
+static constexpr dart::compiler::target::word TsanUtils_exception_fp_offset =
+    32;
+static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
+    16;
+static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
+static constexpr dart::compiler::target::word Type_arguments_offset = 24;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
+static constexpr dart::compiler::target::word Type_type_state_offset = 42;
+static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
+static constexpr dart::compiler::target::word
+    FunctionType_named_parameter_names_offset = 48;
+static constexpr dart::compiler::target::word FunctionType_nullability_offset =
+    71;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_parameter_counts_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_packed_type_parameter_counts_offset = 68;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
+static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
+    45;
+static constexpr dart::compiler::target::word
+    TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
+static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word
+    TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word
+    UnhandledException_exception_offset = 8;
+static constexpr dart::compiler::target::word
+    UnhandledException_stacktrace_offset = 16;
+static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_expected_cid_offset = 8;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_entrypoint_offset = 16;
+static constexpr dart::compiler::target::word WeakProperty_key_offset = 8;
+static constexpr dart::compiler::target::word WeakProperty_value_offset = 16;
+static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
+    8, 24, 16, 32};
+static constexpr dart::compiler::target::word
+    Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,   -1,   -1, -1, -1, 1432, 1440, 1448, -1,   -1,   1456,
+        1464, 1472, -1, -1, -1, 1480, 1488, 1496, 1504, 1512, 1520,
+        1528, 1536, -1, -1, -1, -1,   1544, 1552, 1560, 1568};
+static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
+static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
+static constexpr dart::compiler::target::word Array_header_size = 24;
+static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
+static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word Class_InstanceSize = 184;
+static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_ObjectHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word Context_header_size = 24;
+static constexpr dart::compiler::target::word Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    ExternalOneByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    ExternalTwoByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word ExternalTypedData_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
+static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
+static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
+static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
+    16;
+static constexpr dart::compiler::target::word
+    InstructionsSection_UnalignedHeaderSize = 40;
+static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
+static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
+    120;
+static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
+static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
+static constexpr dart::compiler::target::word LinkedHashBase_InstanceSize = 56;
+static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word MirrorReference_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    MonomorphicSmiableCall_InstanceSize = 24;
+static constexpr dart::compiler::target::word Namespace_InstanceSize = 40;
+static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
+static constexpr dart::compiler::target::word Number_InstanceSize = 8;
+static constexpr dart::compiler::target::word Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
+static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
+static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
+static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
+static constexpr dart::compiler::target::word Script_InstanceSize = 80;
+static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
+static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
+static constexpr dart::compiler::target::word String_InstanceSize = 16;
+static constexpr dart::compiler::target::word SubtypeTestCache_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word LoadingUnit_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    TransferableTypedData_InstanceSize = 8;
+static constexpr dart::compiler::target::word Type_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
+static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 40;
+static constexpr dart::compiler::target::word UnhandledException_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word UnlinkedCall_InstanceSize = 32;
+static constexpr dart::compiler::target::word UnwindError_InstanceSize = 24;
+static constexpr dart::compiler::target::word UserTag_InstanceSize = 32;
+static constexpr dart::compiler::target::word WeakProperty_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    WeakSerializationReference_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+
 #endif  // !defined(PRODUCT)
 
 #if !defined(PRODUCT)
@@ -7013,13 +9309,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 152;
+    AOT_ObjectStore_double_type_offset = 160;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    108;
+    116;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 172;
+    AOT_ObjectStore_string_type_offset = 180;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    104;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -7043,98 +9339,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 380;
+    AOT_Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 752;
+    AOT_Thread_active_exception_offset = 760;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 756;
+    AOT_Thread_active_stacktrace_offset = 764;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 272;
+    AOT_Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 288;
+    AOT_Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 292;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 296;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 204;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    792;
+    800;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     120;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 276;
+    AOT_Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 144;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    816;
+    824;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 796;
+    AOT_Thread_double_truncate_round_supported_offset = 804;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 320;
+    AOT_Thread_deoptimize_entry_offset = 324;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 236;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 360;
+    AOT_Thread_double_abs_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 356;
+    AOT_Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 772;
+    AOT_Thread_execution_state_offset = 780;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 264;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 324;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 372;
+    AOT_Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 368;
+    AOT_Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 364;
+    AOT_Thread_float_not_address_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 376;
+    AOT_Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 760;
+    AOT_Thread_global_object_pool_offset = 768;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 788;
+    AOT_Thread_exit_through_ffi_offset = 796;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    820;
+    828;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 64;
 static constexpr dart::compiler::target::word
@@ -7146,13 +9444,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 308;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 312;
+    AOT_Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -7177,16 +9475,16 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 764;
+    AOT_Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 772;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 768;
+    AOT_Thread_saved_shadow_call_stack_offset = 776;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 776;
+    AOT_Thread_safepoint_state_offset = 784;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 332;
+    AOT_Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     28;
 static constexpr dart::compiler::target::word
@@ -7194,11 +9492,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word
@@ -7216,19 +9514,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 124;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 268;
+    AOT_Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 32;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    780;
+    788;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 784;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 800;
+    AOT_Thread_callback_stack_return_offset = 792;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 808;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 328;
+    AOT_Thread_jump_to_frame_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    808;
+    816;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -7311,7 +9609,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        720, 724, 728, 732, 736, -1, 740, -1, 744, 748, -1, -1, -1, -1, -1, -1};
+        728, 732, 736, 740, 744, -1, 748, -1, 752, 756, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     12;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -7643,13 +9941,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -7673,98 +9971,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1504;
+    AOT_Thread_active_exception_offset = 1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1512;
+    AOT_Thread_active_stacktrace_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1592;
+    AOT_Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1544;
+    AOT_Thread_execution_state_offset = 1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1520;
+    AOT_Thread_global_object_pool_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1576;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -7776,13 +10076,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -7807,17 +10107,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1536;
+    AOT_Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1552;
+    AOT_Thread_safepoint_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -7825,11 +10125,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -7847,19 +10147,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
+    AOT_Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -7943,8 +10243,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8279,13 +10579,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -8309,98 +10609,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1568;
+    AOT_Thread_active_exception_offset = 1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1576;
+    AOT_Thread_active_stacktrace_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1688;
+    1704;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1656;
+    AOT_Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1608;
+    AOT_Thread_execution_state_offset = 1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1584;
+    AOT_Thread_global_object_pool_offset = 1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1640;
+    AOT_Thread_exit_through_ffi_offset = 1656;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -8412,13 +10714,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -8443,17 +10745,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1592;
+    1608;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1600;
+    AOT_Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1616;
+    AOT_Thread_safepoint_state_offset = 1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -8461,11 +10763,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -8483,19 +10785,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
+    AOT_Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1672;
+    1688;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -8579,9 +10881,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8912,13 +11214,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -8942,98 +11244,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1504;
+    AOT_Thread_active_exception_offset = 1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1512;
+    AOT_Thread_active_stacktrace_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1592;
+    AOT_Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1544;
+    AOT_Thread_execution_state_offset = 1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1520;
+    AOT_Thread_global_object_pool_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1576;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -9045,13 +11349,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -9076,17 +11380,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1536;
+    AOT_Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1552;
+    AOT_Thread_safepoint_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -9094,11 +11398,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -9116,19 +11420,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
+    AOT_Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -9212,8 +11516,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -9544,13 +11848,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -9574,98 +11878,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1568;
+    AOT_Thread_active_exception_offset = 1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1576;
+    AOT_Thread_active_stacktrace_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1688;
+    1704;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1656;
+    AOT_Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1608;
+    AOT_Thread_execution_state_offset = 1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1584;
+    AOT_Thread_global_object_pool_offset = 1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1640;
+    AOT_Thread_exit_through_ffi_offset = 1656;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -9677,13 +11983,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -9708,17 +12014,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1592;
+    1608;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1600;
+    AOT_Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1616;
+    AOT_Thread_safepoint_state_offset = 1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -9726,11 +12032,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -9748,19 +12054,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
+    AOT_Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1672;
+    1688;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -9844,9 +12150,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -9953,6 +12259,1275 @@
     AOT_WeakSerializationReference_InstanceSize = 16;
 #endif  // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
 
+#if defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+    28;
+static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_ClassTable_elements_start_offset = 0;
+static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 1;
+static constexpr dart::compiler::target::word AOT_Code_elements_start_offset =
+    88;
+static constexpr dart::compiler::target::word AOT_Code_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_Context_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_Context_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_ContextScope_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_ContextScope_element_size =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_elements_start_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_element_size = 12;
+static constexpr dart::compiler::target::word
+    AOT_ObjectPool_elements_start_offset = 8;
+static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_OneByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_OneByteString_element_size =
+    1;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_elements_start_offset = 20;
+static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_TwoByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_TwoByteString_element_size =
+    2;
+static constexpr dart::compiler::target::word AOT_Array_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word AOT_Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word AOT_Context_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    AOT_NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word AOT_String_kMaxElements =
+    536870911;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult =
+    0;
+static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AOT_AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_size_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_first_named_entry_offset = 28;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_positional_count_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word AOT_Array_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_Array_length_offset = 8;
+static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0;
+static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_Class_declaration_type_offset = 52;
+static constexpr dart::compiler::target::word
+    AOT_Class_num_type_arguments_offset = 72;
+static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 44;
+static constexpr dart::compiler::target::word
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 84;
+static constexpr dart::compiler::target::word
+    AOT_SharedClassTable_class_heap_stats_table_offset = 0;
+static constexpr dart::compiler::target::word AOT_Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word AOT_Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ClosureData_default_type_arguments_kind_offset = 16;
+static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_Code_saved_instructions_offset = 24;
+static constexpr dart::compiler::target::word AOT_Code_owner_offset = 28;
+static constexpr dart::compiler::target::word AOT_Context_num_variables_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_Context_parent_offset = 8;
+static constexpr dart::compiler::target::word AOT_Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Field_initializer_function_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_Field_host_offset_or_field_id_offset = 20;
+static constexpr dart::compiler::target::word AOT_Field_guarded_cid_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_in_object_offset_offset = 44;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_offset = 24;
+static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 42;
+static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 46;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 32;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_Function_entry_point_offset[] = {4, 8};
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 36;
+static constexpr dart::compiler::target::word
+    AOT_Function_packed_fields_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FutureOr_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word AOT_OldPage_card_table_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12;
+static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16;
+static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20;
+static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
+    28;
+static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_object_store_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 20;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_ImmutableLinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_deleted_keys_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_hash_mask_offset = 8;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_used_data_offset = 16;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_buckets_offset = 12;
+static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_argc_tag_offset = 4;
+static constexpr dart::compiler::target::word AOT_NativeArguments_argv_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_retval_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_double_type_offset = 160;
+static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
+    116;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_string_type_offset = 180;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    104;
+static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_Pointer_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_target_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word
+    AOT_StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_String_hash_offset = 8;
+static constexpr dart::compiler::target::word AOT_String_length_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_Thread_AllocateArray_entry_point_offset = 384;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_exception_offset = 800;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_stacktrace_offset = 804;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_code_offset = 128;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 292;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 296;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 200;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 300;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 204;
+static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
+    840;
+static constexpr dart::compiler::target::word
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 348;
+static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
+    120;
+static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
+static constexpr dart::compiler::target::word
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 340;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_stub_offset = 144;
+static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
+    864;
+static constexpr dart::compiler::target::word
+    AOT_Thread_dispatch_table_array_offset = 44;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_truncate_round_supported_offset = 844;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
+    320;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
+    232;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_entry_offset = 324;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_stub_offset = 236;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_abs_address_offset = 364;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_negate_address_offset = 360;
+static constexpr dart::compiler::target::word AOT_Thread_end_offset = 52;
+static constexpr dart::compiler::target::word
+    AOT_Thread_enter_safepoint_stub_offset = 256;
+static constexpr dart::compiler::target::word
+    AOT_Thread_execution_state_offset = 820;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_stub_offset = 260;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 328;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_allocation_stub_code_offset = 136;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_callers_target_code_offset = 132;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_absolute_address_offset = 376;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_negate_address_offset = 372;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_not_address_offset = 368;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_zerow_address_offset = 380;
+static constexpr dart::compiler::target::word
+    AOT_Thread_global_object_pool_offset = 808;
+static constexpr dart::compiler::target::word
+    AOT_Thread_invoke_dart_code_stub_offset = 140;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_through_ffi_offset = 836;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
+    868;
+static constexpr dart::compiler::target::word
+    AOT_Thread_field_table_values_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 240;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 244;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 252;
+static constexpr dart::compiler::target::word
+    AOT_Thread_marking_stack_block_offset = 80;
+static constexpr dart::compiler::target::word
+    AOT_Thread_megamorphic_call_checked_entry_offset = 312;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_entry_offset = 316;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_stub_offset = 216;
+static constexpr dart::compiler::target::word
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_without_fpu_regs_stub_offset =
+        148;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 164;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 176;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
+    112;
+static constexpr dart::compiler::target::word
+    AOT_Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 812;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_shadow_call_stack_offset = 816;
+static constexpr dart::compiler::target::word
+    AOT_Thread_safepoint_state_offset = 824;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_entry_point_offset = 336;
+static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
+    28;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_stack_limit_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_flags_offset = 60;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
+static constexpr dart::compiler::target::word
+    AOT_Thread_store_buffer_block_offset = 76;
+static constexpr dart::compiler::target::word
+    AOT_Thread_top_exit_frame_info_offset = 72;
+static constexpr dart::compiler::target::word AOT_Thread_top_offset = 48;
+static constexpr dart::compiler::target::word AOT_Thread_top_resource_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_double_runtime_arg_offset = 104;
+static constexpr dart::compiler::target::word AOT_Thread_vm_tag_offset = 88;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_code_offset = 124;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_entry_point_offset = 272;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_mask_offset = 32;
+static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 36;
+static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
+    828;
+static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 832;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 848;
+static constexpr dart::compiler::target::word
+    AOT_Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
+    856;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_function_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_buffer_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_pc_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_sp_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_fp_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 12;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 16;
+static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
+    20;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_named_parameter_names_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_nullability_offset = 39;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_parameter_counts_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_type_parameter_counts_offset = 36;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
+    23;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_nullability_offset = 25;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
+    20;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_exception_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_stacktrace_offset = 8;
+static constexpr dart::compiler::target::word AOT_UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_expected_cid_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_entrypoint_offset = 8;
+static constexpr dart::compiler::target::word AOT_WeakProperty_key_offset = 4;
+static constexpr dart::compiler::target::word AOT_WeakProperty_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
+    4, 12, 8, 16};
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,  -1,  -1, -1, -1, 728, 732, 736, -1,  -1,  740,
+        744, 748, -1, -1, -1, 752, 756, 760, 764, 768, 772,
+        776, 780, -1, -1, -1, -1,  784, 788, 792, 796};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
+static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 92;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_ObjectHeaderSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word AOT_Context_header_size = 12;
+static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTypedData_InstanceSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_FfiTrampolineData_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_UnalignedHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsTable_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_KernelProgramInfo_InstanceSize = 60;
+static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_MirrorReference_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_Namespace_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_NativeArguments_StructSize =
+    16;
+static constexpr dart::compiler::target::word AOT_Number_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 8;
+static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_String_InstanceSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_TransferableTypedData_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 12;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word AOT_TypedDataView_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_UnlinkedCall_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word AOT_UnwindError_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_WeakSerializationReference_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+
+#if defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+    56;
+static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_ClassTable_elements_start_offset = 0;
+static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 1;
+static constexpr dart::compiler::target::word AOT_Code_elements_start_offset =
+    152;
+static constexpr dart::compiler::target::word AOT_Code_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_Context_elements_start_offset = 24;
+static constexpr dart::compiler::target::word AOT_Context_element_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_ContextScope_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_ContextScope_element_size =
+    64;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_elements_start_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_element_size = 12;
+static constexpr dart::compiler::target::word
+    AOT_ObjectPool_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_OneByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_OneByteString_element_size =
+    1;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_elements_start_offset = 40;
+static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_TwoByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_TwoByteString_element_size =
+    2;
+static constexpr dart::compiler::target::word AOT_Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word AOT_Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word AOT_Context_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
+static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
+    10;
+static constexpr dart::compiler::target::word
+    AOT_NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word AOT_String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult =
+    0;
+static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AOT_AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_size_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_first_named_entry_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_positional_count_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word AOT_Array_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_Array_length_offset = 16;
+static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0;
+static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_Class_declaration_type_offset = 104;
+static constexpr dart::compiler::target::word
+    AOT_Class_num_type_arguments_offset = 140;
+static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88;
+static constexpr dart::compiler::target::word
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 152;
+static constexpr dart::compiler::target::word
+    AOT_SharedClassTable_class_heap_stats_table_offset = 0;
+static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
+static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Code_saved_instructions_offset = 48;
+static constexpr dart::compiler::target::word AOT_Code_owner_offset = 56;
+static constexpr dart::compiler::target::word AOT_Context_num_variables_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_Context_parent_offset = 16;
+static constexpr dart::compiler::target::word AOT_Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word AOT_Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Field_initializer_function_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_Field_host_offset_or_field_id_offset = 40;
+static constexpr dart::compiler::target::word AOT_Field_guarded_cid_offset = 72;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_in_object_offset_offset = 76;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_offset = 48;
+static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
+static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 64;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_Function_entry_point_offset[] = {8, 16};
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word
+    AOT_Function_packed_fields_offset = 76;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FutureOr_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word AOT_OldPage_card_table_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
+static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
+static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
+static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
+    48;
+static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
+    56;
+static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
+    64;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_object_store_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
+    80;
+static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_ImmutableLinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_hash_mask_offset = 16;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
+    48;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_used_data_offset = 32;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_buckets_offset = 24;
+static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_argc_tag_offset = 8;
+static constexpr dart::compiler::target::word AOT_NativeArguments_argv_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_retval_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_double_type_offset = 320;
+static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
+    232;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_string_type_offset = 360;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    208;
+static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Pointer_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_target_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word
+    AOT_StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_String_hash_offset = 4;
+static constexpr dart::compiler::target::word AOT_String_length_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_exception_offset = 1576;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_stacktrace_offset = 1584;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_code_offset = 232;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 560;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 384;
+static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
+    1656;
+static constexpr dart::compiler::target::word
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
+static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
+    216;
+static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
+static constexpr dart::compiler::target::word
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
+    1696;
+static constexpr dart::compiler::target::word
+    AOT_Thread_dispatch_table_array_offset = 88;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_truncate_round_supported_offset = 1664;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
+    616;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
+    440;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_entry_offset = 624;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_stub_offset = 448;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_abs_address_offset = 704;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_negate_address_offset = 696;
+static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
+static constexpr dart::compiler::target::word
+    AOT_Thread_enter_safepoint_stub_offset = 488;
+static constexpr dart::compiler::target::word
+    AOT_Thread_execution_state_offset = 1616;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_stub_offset = 496;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_allocation_stub_code_offset = 248;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_callers_target_code_offset = 240;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_absolute_address_offset = 728;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_negate_address_offset = 720;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_not_address_offset = 712;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_zerow_address_offset = 736;
+static constexpr dart::compiler::target::word
+    AOT_Thread_global_object_pool_offset = 1592;
+static constexpr dart::compiler::target::word
+    AOT_Thread_invoke_dart_code_stub_offset = 256;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_through_ffi_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
+    1704;
+static constexpr dart::compiler::target::word
+    AOT_Thread_field_table_values_offset = 128;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 456;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 464;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 480;
+static constexpr dart::compiler::target::word
+    AOT_Thread_marking_stack_block_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_stub_offset = 408;
+static constexpr dart::compiler::target::word
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_without_fpu_regs_stub_offset =
+        272;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 320;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
+static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
+    200;
+static constexpr dart::compiler::target::word
+    AOT_Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
+    1600;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_shadow_call_stack_offset = 1608;
+static constexpr dart::compiler::target::word
+    AOT_Thread_safepoint_state_offset = 1624;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_stub_offset = 472;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
+static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
+    56;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_stack_limit_offset = 112;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_flags_offset = 120;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
+static constexpr dart::compiler::target::word
+    AOT_Thread_store_buffer_block_offset = 152;
+static constexpr dart::compiler::target::word
+    AOT_Thread_top_exit_frame_info_offset = 144;
+static constexpr dart::compiler::target::word AOT_Thread_top_offset = 96;
+static constexpr dart::compiler::target::word AOT_Thread_top_resource_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_double_runtime_arg_offset = 192;
+static constexpr dart::compiler::target::word AOT_Thread_vm_tag_offset = 176;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_code_offset = 224;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_entry_point_offset = 520;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_mask_offset = 64;
+static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
+static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
+    1632;
+static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1640;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1672;
+static constexpr dart::compiler::target::word
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
+    1680;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_function_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_buffer_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_pc_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_sp_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_fp_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_TimelineStream_enabled_offset = 16;
+static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
+static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_named_parameter_names_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_nullability_offset = 71;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_parameter_counts_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_type_parameter_counts_offset = 68;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
+    43;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_nullability_offset = 45;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_exception_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_stacktrace_offset = 16;
+static constexpr dart::compiler::target::word AOT_UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_expected_cid_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_entrypoint_offset = 16;
+static constexpr dart::compiler::target::word AOT_WeakProperty_key_offset = 8;
+static constexpr dart::compiler::target::word AOT_WeakProperty_value_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
+    8, 24, 16, 32};
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,   -1,   -1, -1, -1, 1432, 1440, 1448, -1,   -1,   1456,
+        1464, 1472, -1, -1, -1, 1480, 1488, 1496, 1504, 1512, 1520,
+        1528, 1536, -1, -1, -1, -1,   1544, 1552, 1560, 1568};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
+static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 160;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_ObjectHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
+static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTypedData_InstanceSize = 24;
+static constexpr dart::compiler::target::word
+    AOT_FfiTrampolineData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
+static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsTable_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_KernelProgramInfo_InstanceSize = 120;
+static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_InstanceSize =
+    56;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_MirrorReference_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Namespace_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_NativeArguments_StructSize =
+    32;
+static constexpr dart::compiler::target::word AOT_Number_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
+static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_String_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_TransferableTypedData_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word AOT_TypedDataView_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_UnlinkedCall_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word AOT_UnwindError_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_WeakSerializationReference_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+
 #else  // !defined(PRODUCT)
 
 #if defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
@@ -10172,13 +13747,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 152;
+    AOT_ObjectStore_double_type_offset = 160;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    108;
+    116;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 172;
+    AOT_ObjectStore_string_type_offset = 180;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    104;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -10202,98 +13777,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 380;
+    AOT_Thread_AllocateArray_entry_point_offset = 384;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 752;
+    AOT_Thread_active_exception_offset = 760;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 756;
+    AOT_Thread_active_stacktrace_offset = 764;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 272;
+    AOT_Thread_array_write_barrier_entry_point_offset = 276;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 280;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 284;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 288;
+    AOT_Thread_allocate_object_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 196;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 292;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 296;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 296;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 300;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 204;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    792;
+    800;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 344;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 348;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     120;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 336;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 276;
+    AOT_Thread_call_to_runtime_entry_point_offset = 280;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 144;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    816;
+    824;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 796;
+    AOT_Thread_double_truncate_round_supported_offset = 804;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    316;
+    320;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 320;
+    AOT_Thread_deoptimize_entry_offset = 324;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 236;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 360;
+    AOT_Thread_double_abs_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 356;
+    AOT_Thread_double_negate_address_offset = 360;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 52;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 772;
+    AOT_Thread_execution_state_offset = 780;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 260;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 264;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 324;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 328;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 136;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 372;
+    AOT_Thread_float_absolute_address_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 368;
+    AOT_Thread_float_negate_address_offset = 372;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 364;
+    AOT_Thread_float_not_address_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 376;
+    AOT_Thread_float_zerow_address_offset = 380;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 760;
+    AOT_Thread_global_object_pool_offset = 768;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 788;
+    AOT_Thread_exit_through_ffi_offset = 796;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    820;
+    828;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 64;
 static constexpr dart::compiler::target::word
@@ -10305,13 +13882,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 308;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 312;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 312;
+    AOT_Thread_switchable_call_miss_entry_offset = 316;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 216;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 340;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 344;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word
@@ -10336,16 +13913,16 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     112;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 348;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 764;
+    AOT_Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 772;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 768;
+    AOT_Thread_saved_shadow_call_stack_offset = 776;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 776;
+    AOT_Thread_safepoint_state_offset = 784;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 332;
+    AOT_Thread_slow_type_test_entry_point_offset = 336;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     28;
 static constexpr dart::compiler::target::word
@@ -10353,11 +13930,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 60;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 304;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 300;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
 static constexpr dart::compiler::target::word
@@ -10375,19 +13952,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 124;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 268;
+    AOT_Thread_write_barrier_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 32;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    780;
+    788;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 784;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 800;
+    AOT_Thread_callback_stack_return_offset = 792;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 808;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 328;
+    AOT_Thread_jump_to_frame_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    808;
+    816;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -10470,7 +14047,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        720, 724, 728, 732, 736, -1, 740, -1, 744, 748, -1, -1, -1, -1, -1, -1};
+        728, 732, 736, 740, 744, -1, 748, -1, 752, 756, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     12;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -10795,13 +14372,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -10825,98 +14402,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1504;
+    AOT_Thread_active_exception_offset = 1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1512;
+    AOT_Thread_active_stacktrace_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1592;
+    AOT_Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1544;
+    AOT_Thread_execution_state_offset = 1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1520;
+    AOT_Thread_global_object_pool_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1576;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -10928,13 +14507,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -10959,17 +14538,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1536;
+    AOT_Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1552;
+    AOT_Thread_safepoint_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -10977,11 +14556,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -10999,19 +14578,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
+    AOT_Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -11095,8 +14674,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -11424,13 +15003,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -11454,98 +15033,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1568;
+    AOT_Thread_active_exception_offset = 1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1576;
+    AOT_Thread_active_stacktrace_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1688;
+    1704;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1656;
+    AOT_Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1608;
+    AOT_Thread_execution_state_offset = 1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1584;
+    AOT_Thread_global_object_pool_offset = 1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1640;
+    AOT_Thread_exit_through_ffi_offset = 1656;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -11557,13 +15138,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -11588,17 +15169,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1592;
+    1608;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1600;
+    AOT_Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1616;
+    AOT_Thread_safepoint_state_offset = 1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -11606,11 +15187,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -11628,19 +15209,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
+    AOT_Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1672;
+    1688;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -11724,9 +15305,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -12050,13 +15631,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -12080,98 +15661,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1504;
+    AOT_Thread_active_exception_offset = 1520;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1512;
+    AOT_Thread_active_stacktrace_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1592;
+    AOT_Thread_double_truncate_round_supported_offset = 1608;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1544;
+    AOT_Thread_execution_state_offset = 1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1520;
+    AOT_Thread_global_object_pool_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1576;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -12183,13 +15766,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -12214,17 +15797,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1536;
+    AOT_Thread_saved_shadow_call_stack_offset = 1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1552;
+    AOT_Thread_safepoint_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -12232,11 +15815,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -12254,19 +15837,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1568;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
+    AOT_Thread_callback_stack_return_offset = 1584;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -12350,8 +15933,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, -1,   -1,   1448, 1456,
-        1464, 1472, 1480, -1,   1488, 1496, -1,   -1};
+        1432, 1440, 1448, 1456, -1,   -1,   1464, 1472,
+        1480, 1488, 1496, -1,   1504, 1512, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -12675,13 +16258,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 304;
+    AOT_ObjectStore_double_type_offset = 320;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    216;
+    232;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 344;
+    AOT_ObjectStore_string_type_offset = 360;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    192;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -12705,98 +16288,100 @@
 static constexpr dart::compiler::target::word
     AOT_SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_Thread_AllocateArray_entry_point_offset = 736;
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1568;
+    AOT_Thread_active_exception_offset = 1584;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1576;
+    AOT_Thread_active_stacktrace_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
-    AOT_Thread_array_write_barrier_entry_point_offset = 520;
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 536;
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 544;
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_entry_point_offset = 552;
+    AOT_Thread_allocate_object_entry_point_offset = 560;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_stub_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_parameterized_entry_point_offset = 560;
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_parameterized_stub_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_allocate_object_slow_entry_point_offset = 568;
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1648;
+    1664;
 static constexpr dart::compiler::target::word
-    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 664;
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
     216;
 static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
 static constexpr dart::compiler::target::word
-    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 648;
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_to_runtime_entry_point_offset = 528;
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 264;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1688;
+    1704;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_truncate_round_supported_offset = 1656;
+    AOT_Thread_double_truncate_round_supported_offset = 1672;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
-    608;
+    616;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
     440;
 static constexpr dart::compiler::target::word
-    AOT_Thread_deoptimize_entry_offset = 616;
+    AOT_Thread_deoptimize_entry_offset = 624;
 static constexpr dart::compiler::target::word
     AOT_Thread_deoptimize_stub_offset = 448;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_abs_address_offset = 696;
+    AOT_Thread_double_abs_address_offset = 704;
 static constexpr dart::compiler::target::word
-    AOT_Thread_double_negate_address_offset = 688;
+    AOT_Thread_double_negate_address_offset = 696;
 static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1608;
+    AOT_Thread_execution_state_offset = 1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_stub_offset = 504;
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_call_native_through_safepoint_entry_point_offset = 624;
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_allocation_stub_code_offset = 248;
 static constexpr dart::compiler::target::word
     AOT_Thread_fix_callers_target_code_offset = 240;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_absolute_address_offset = 720;
+    AOT_Thread_float_absolute_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_negate_address_offset = 712;
+    AOT_Thread_float_negate_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_not_address_offset = 704;
+    AOT_Thread_float_not_address_offset = 712;
 static constexpr dart::compiler::target::word
-    AOT_Thread_float_zerow_address_offset = 728;
+    AOT_Thread_float_zerow_address_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1584;
+    AOT_Thread_global_object_pool_offset = 1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1640;
+    AOT_Thread_exit_through_ffi_offset = 1656;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1696;
+    1712;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
 static constexpr dart::compiler::target::word
@@ -12808,13 +16393,13 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_marking_stack_block_offset = 160;
 static constexpr dart::compiler::target::word
-    AOT_Thread_megamorphic_call_checked_entry_offset = 592;
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_switchable_call_miss_entry_offset = 600;
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
 static constexpr dart::compiler::target::word
     AOT_Thread_switchable_call_miss_stub_offset = 408;
 static constexpr dart::compiler::target::word
-    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 656;
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
     AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
@@ -12839,17 +16424,17 @@
 static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
     200;
 static constexpr dart::compiler::target::word
-    AOT_Thread_predefined_symbols_address_offset = 672;
+    AOT_Thread_predefined_symbols_address_offset = 680;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1592;
+    1608;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1600;
+    AOT_Thread_saved_shadow_call_stack_offset = 1616;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1616;
+    AOT_Thread_safepoint_state_offset = 1632;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
-    AOT_Thread_slow_type_test_entry_point_offset = 640;
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -12857,11 +16442,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_flags_offset = 120;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 584;
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
 static constexpr dart::compiler::target::word
-    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 576;
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
 static constexpr dart::compiler::target::word
     AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
 static constexpr dart::compiler::target::word
@@ -12879,19 +16464,19 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    AOT_Thread_write_barrier_entry_point_offset = 512;
+    AOT_Thread_write_barrier_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 64;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1624;
+    1640;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1632;
-static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
+    AOT_Thread_callback_stack_return_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1680;
 static constexpr dart::compiler::target::word
-    AOT_Thread_jump_to_frame_entry_point_offset = 632;
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
 static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
-    1672;
+    1688;
 static constexpr dart::compiler::target::word
     AOT_TsanUtils_setjmp_function_offset = 0;
 static constexpr dart::compiler::target::word
@@ -12975,9 +16560,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496,
-        1504, 1512, 1520, 1528, -1,   -1,   -1,   -1,   1536, 1544, -1,
-        -1,   1552, 1560, 1568, -1,   -1,   -1,   -1,   -1,   -1};
+        1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1496, 1504, 1512,
+        1520, 1528, 1536, 1544, -1,   -1,   -1,   -1,   1552, 1560, -1,
+        -1,   1568, 1576, 1584, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -13084,6 +16669,1261 @@
     AOT_WeakSerializationReference_InstanceSize = 16;
 #endif  // defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
 
+#if defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+    28;
+static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
+static constexpr dart::compiler::target::word AOT_Code_elements_start_offset =
+    64;
+static constexpr dart::compiler::target::word AOT_Code_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_Context_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_Context_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_ContextScope_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_ContextScope_element_size =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_elements_start_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_element_size = 12;
+static constexpr dart::compiler::target::word
+    AOT_ObjectPool_elements_start_offset = 8;
+static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_OneByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_OneByteString_element_size =
+    1;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_elements_start_offset = 20;
+static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_TwoByteString_elements_start_offset = 12;
+static constexpr dart::compiler::target::word AOT_TwoByteString_element_size =
+    2;
+static constexpr dart::compiler::target::word AOT_Array_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word AOT_Array_kMaxNewSpaceElements =
+    65533;
+static constexpr dart::compiler::target::word AOT_Context_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 = 9;
+static constexpr dart::compiler::target::word
+    AOT_NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word AOT_String_kMaxElements =
+    536870911;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult =
+    0;
+static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements =
+    268435455;
+static constexpr dart::compiler::target::word
+    AOT_AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_size_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_first_named_entry_offset = 28;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_positional_count_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::compiler::target::word AOT_Array_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_Array_length_offset = 8;
+static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0;
+static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_Class_declaration_type_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_Class_num_type_arguments_offset = 60;
+static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 72;
+static constexpr dart::compiler::target::word AOT_Closure_context_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::compiler::target::word AOT_Closure_function_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_Closure_function_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_ClosureData_default_type_arguments_kind_offset = 16;
+static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_Code_saved_instructions_offset = 24;
+static constexpr dart::compiler::target::word AOT_Code_owner_offset = 28;
+static constexpr dart::compiler::target::word AOT_Context_num_variables_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_Context_parent_offset = 8;
+static constexpr dart::compiler::target::word AOT_Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Field_initializer_function_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_Field_host_offset_or_field_id_offset = 20;
+static constexpr dart::compiler::target::word AOT_Field_guarded_cid_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_in_object_offset_offset = 44;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_offset = 24;
+static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 42;
+static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 46;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 32;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_Function_entry_point_offset[] = {4, 8};
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 36;
+static constexpr dart::compiler::target::word
+    AOT_Function_packed_fields_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FutureOr_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_length_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word AOT_OldPage_card_table_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 8;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12;
+static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16;
+static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20;
+static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
+    20;
+static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
+    28;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_object_store_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_shared_class_table_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 16;
+static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_ImmutableLinkedHashBase_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_deleted_keys_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_hash_mask_offset = 8;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_type_arguments_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_used_data_offset = 16;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
+    4;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_buckets_offset = 12;
+static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_argc_tag_offset = 4;
+static constexpr dart::compiler::target::word AOT_NativeArguments_argv_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_retval_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_double_type_offset = 160;
+static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
+    116;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_string_type_offset = 180;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    104;
+static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_Pointer_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_target_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::compiler::target::word
+    AOT_StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_String_hash_offset = 8;
+static constexpr dart::compiler::target::word AOT_String_length_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_cache_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_Thread_AllocateArray_entry_point_offset = 384;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_exception_offset = 800;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_stacktrace_offset = 804;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_code_offset = 128;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_entry_point_offset = 276;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 284;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 188;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 288;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 292;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 296;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 200;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 300;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 204;
+static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
+    840;
+static constexpr dart::compiler::target::word
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 348;
+static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
+    120;
+static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 116;
+static constexpr dart::compiler::target::word
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 340;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_entry_point_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_stub_offset = 144;
+static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
+    864;
+static constexpr dart::compiler::target::word
+    AOT_Thread_dispatch_table_array_offset = 44;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_truncate_round_supported_offset = 844;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
+    320;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
+    232;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_entry_offset = 324;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_stub_offset = 236;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_abs_address_offset = 364;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_negate_address_offset = 360;
+static constexpr dart::compiler::target::word AOT_Thread_end_offset = 52;
+static constexpr dart::compiler::target::word
+    AOT_Thread_enter_safepoint_stub_offset = 256;
+static constexpr dart::compiler::target::word
+    AOT_Thread_execution_state_offset = 820;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_stub_offset = 260;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 264;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_stub_offset = 268;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 328;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_allocation_stub_code_offset = 136;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_callers_target_code_offset = 132;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_absolute_address_offset = 376;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_negate_address_offset = 372;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_not_address_offset = 368;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_zerow_address_offset = 380;
+static constexpr dart::compiler::target::word
+    AOT_Thread_global_object_pool_offset = 808;
+static constexpr dart::compiler::target::word
+    AOT_Thread_invoke_dart_code_stub_offset = 140;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_through_ffi_offset = 836;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
+    868;
+static constexpr dart::compiler::target::word
+    AOT_Thread_field_table_values_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 240;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 244;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 252;
+static constexpr dart::compiler::target::word
+    AOT_Thread_marking_stack_block_offset = 80;
+static constexpr dart::compiler::target::word
+    AOT_Thread_megamorphic_call_checked_entry_offset = 312;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_entry_offset = 316;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_stub_offset = 216;
+static constexpr dart::compiler::target::word
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 152;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_without_fpu_regs_stub_offset =
+        148;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 156;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 168;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 164;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 176;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 172;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 180;
+static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
+    112;
+static constexpr dart::compiler::target::word
+    AOT_Thread_predefined_symbols_address_offset = 352;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 812;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_shadow_call_stack_offset = 816;
+static constexpr dart::compiler::target::word
+    AOT_Thread_safepoint_state_offset = 824;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_stub_offset = 248;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_entry_point_offset = 336;
+static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
+    28;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_stack_limit_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_flags_offset = 60;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 308;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 212;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 208;
+static constexpr dart::compiler::target::word
+    AOT_Thread_store_buffer_block_offset = 76;
+static constexpr dart::compiler::target::word
+    AOT_Thread_top_exit_frame_info_offset = 72;
+static constexpr dart::compiler::target::word AOT_Thread_top_offset = 48;
+static constexpr dart::compiler::target::word AOT_Thread_top_resource_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_double_runtime_arg_offset = 104;
+static constexpr dart::compiler::target::word AOT_Thread_vm_tag_offset = 88;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_code_offset = 124;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_entry_point_offset = 272;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_mask_offset = 32;
+static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 36;
+static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
+    828;
+static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 832;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 848;
+static constexpr dart::compiler::target::word
+    AOT_Thread_jump_to_frame_entry_point_offset = 332;
+static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
+    856;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_function_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_buffer_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_pc_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_sp_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_fp_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_TimelineStream_enabled_offset = 8;
+static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 12;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 16;
+static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
+    20;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_named_parameter_names_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_nullability_offset = 39;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_parameter_counts_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_type_parameter_counts_offset = 36;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
+    23;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_nullability_offset = 25;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
+    20;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_exception_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_stacktrace_offset = 8;
+static constexpr dart::compiler::target::word AOT_UserTag_tag_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_expected_cid_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_entrypoint_offset = 8;
+static constexpr dart::compiler::target::word AOT_WeakProperty_key_offset = 4;
+static constexpr dart::compiler::target::word AOT_WeakProperty_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
+    4, 12, 8, 16};
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,  -1,  -1, -1, -1, 728, 732, 736, -1,  -1,  740,
+        744, 748, -1, -1, -1, 752, 756, 760, 764, 768, 772,
+        776, 780, -1, -1, -1, -1,  784, 788, 792, 796};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
+static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_ObjectHeaderSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word AOT_Context_header_size = 12;
+static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTypedData_InstanceSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_FfiTrampolineData_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_UnalignedHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsTable_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_KernelProgramInfo_InstanceSize = 60;
+static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_MirrorReference_InstanceSize =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_Namespace_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_NativeArguments_StructSize =
+    16;
+static constexpr dart::compiler::target::word AOT_Number_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_Object_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 8;
+static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 4;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 20;
+static constexpr dart::compiler::target::word AOT_String_InstanceSize = 12;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize = 20;
+static constexpr dart::compiler::target::word
+    AOT_TransferableTypedData_InstanceSize = 4;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
+    28;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 12;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
+    12;
+static constexpr dart::compiler::target::word AOT_TypedDataView_InstanceSize =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_UnlinkedCall_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word AOT_UnwindError_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_WeakSerializationReference_InstanceSize = 12;
+#endif  // defined(TARGET_ARCH_RISCV32) && !defined(DART_COMPRESSED_POINTERS)
+
+#if defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+    56;
+static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
+    24;
+static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
+static constexpr dart::compiler::target::word AOT_Code_elements_start_offset =
+    120;
+static constexpr dart::compiler::target::word AOT_Code_element_size = 4;
+static constexpr dart::compiler::target::word
+    AOT_Context_elements_start_offset = 24;
+static constexpr dart::compiler::target::word AOT_Context_element_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_ContextScope_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_ContextScope_element_size =
+    64;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_elements_start_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_ExceptionHandlers_element_size = 12;
+static constexpr dart::compiler::target::word
+    AOT_ObjectPool_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
+static constexpr dart::compiler::target::word
+    AOT_OneByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_OneByteString_element_size =
+    1;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_elements_start_offset = 40;
+static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_TwoByteString_elements_start_offset = 16;
+static constexpr dart::compiler::target::word AOT_TwoByteString_element_size =
+    2;
+static constexpr dart::compiler::target::word AOT_Array_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word AOT_Array_kMaxNewSpaceElements =
+    32765;
+static constexpr dart::compiler::target::word AOT_Context_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetJIT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetJIT = 42;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kMonomorphicEntryOffsetAOT = 6;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kPolymorphicEntryOffsetAOT = 16;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
+static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
+    10;
+static constexpr dart::compiler::target::word
+    AOT_NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::compiler::target::word AOT_String_kMaxElements =
+    2305843009213693951;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kFunctionTypeArguments = 5;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceCidOrSignature = 1;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kDestinationType = 2;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 7;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceParentFunctionTypeArguments = 6;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstanceTypeArguments = 3;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kInstantiatorTypeArguments = 4;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_kTestEntryLength = 8;
+static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult =
+    0;
+static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements =
+    576460752303423487;
+static constexpr dart::compiler::target::word
+    AOT_AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_size_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_first_named_entry_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_positional_count_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::compiler::target::word AOT_Array_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_Array_length_offset = 16;
+static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0;
+static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_Class_declaration_type_offset = 96;
+static constexpr dart::compiler::target::word
+    AOT_Class_num_type_arguments_offset = 116;
+static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 80;
+static constexpr dart::compiler::target::word
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 128;
+static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Closure_function_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_Closure_function_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
+static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_Code_saved_instructions_offset = 48;
+static constexpr dart::compiler::target::word AOT_Code_owner_offset = 56;
+static constexpr dart::compiler::target::word AOT_Context_num_variables_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_Context_parent_offset = 16;
+static constexpr dart::compiler::target::word AOT_Double_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::compiler::target::word AOT_Float32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Float64x2_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Field_initializer_function_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_Field_host_offset_or_field_id_offset = 40;
+static constexpr dart::compiler::target::word AOT_Field_guarded_cid_offset = 72;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_in_object_offset_offset = 76;
+static constexpr dart::compiler::target::word
+    AOT_Field_guarded_list_length_offset = 48;
+static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
+static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 64;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_Function_entry_point_offset[] = {8, 16};
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word
+    AOT_Function_packed_fields_offset = 76;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FutureOr_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_length_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word AOT_OldPage_card_table_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_CallSiteData_arguments_descriptor_offset = 16;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedMask = 3;
+static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0;
+static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24;
+static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32;
+static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40;
+static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8;
+static constexpr dart::compiler::target::word AOT_Isolate_current_tag_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
+    48;
+static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
+    56;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_object_store_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_shared_class_table_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_IsolateGroup_cached_class_table_table_offset = 32;
+static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_ImmutableLinkedHashBase_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_hash_mask_offset = 16;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
+    48;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_type_arguments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_LinkedHashBase_used_data_offset = 32;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
+    8;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_buckets_offset = 24;
+static constexpr dart::compiler::target::word AOT_MegamorphicCache_mask_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_Mint_value_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_argc_tag_offset = 8;
+static constexpr dart::compiler::target::word AOT_NativeArguments_argv_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_retval_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_NativeArguments_thread_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_double_type_offset = 320;
+static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
+    232;
+static constexpr dart::compiler::target::word
+    AOT_ObjectStore_string_type_offset = 360;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    208;
+static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Pointer_type_arguments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_target_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::compiler::target::word
+    AOT_StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::compiler::target::word AOT_StoreBufferBlock_top_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_String_hash_offset = 4;
+static constexpr dart::compiler::target::word AOT_String_length_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_cache_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_Thread_AllocateArray_entry_point_offset = 744;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_exception_offset = 1576;
+static constexpr dart::compiler::target::word
+    AOT_Thread_active_stacktrace_offset = 1584;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_code_offset = 232;
+static constexpr dart::compiler::target::word
+    AOT_Thread_array_write_barrier_entry_point_offset = 528;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_entry_point_offset = 544;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_with_fpu_regs_stub_offset = 352;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_entry_point_offset = 552;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_mint_without_fpu_regs_stub_offset = 360;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_entry_point_offset = 560;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_entry_point_offset = 568;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_parameterized_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_entry_point_offset = 576;
+static constexpr dart::compiler::target::word
+    AOT_Thread_allocate_object_slow_stub_offset = 384;
+static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
+    1656;
+static constexpr dart::compiler::target::word
+    AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 672;
+static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
+    216;
+static constexpr dart::compiler::target::word AOT_Thread_bool_true_offset = 208;
+static constexpr dart::compiler::target::word
+    AOT_Thread_bootstrap_native_wrapper_entry_point_offset = 656;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_entry_point_offset = 536;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
+    1696;
+static constexpr dart::compiler::target::word
+    AOT_Thread_dispatch_table_array_offset = 88;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_truncate_round_supported_offset = 1664;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
+    616;
+static constexpr dart::compiler::target::word AOT_Thread_optimize_stub_offset =
+    440;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_entry_offset = 624;
+static constexpr dart::compiler::target::word
+    AOT_Thread_deoptimize_stub_offset = 448;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_abs_address_offset = 704;
+static constexpr dart::compiler::target::word
+    AOT_Thread_double_negate_address_offset = 696;
+static constexpr dart::compiler::target::word AOT_Thread_end_offset = 104;
+static constexpr dart::compiler::target::word
+    AOT_Thread_enter_safepoint_stub_offset = 488;
+static constexpr dart::compiler::target::word
+    AOT_Thread_execution_state_offset = 1616;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_stub_offset = 496;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_safepoint_ignore_unwind_in_progress_stub_offset = 504;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_stub_offset = 512;
+static constexpr dart::compiler::target::word
+    AOT_Thread_call_native_through_safepoint_entry_point_offset = 632;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_allocation_stub_code_offset = 248;
+static constexpr dart::compiler::target::word
+    AOT_Thread_fix_callers_target_code_offset = 240;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_absolute_address_offset = 728;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_negate_address_offset = 720;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_not_address_offset = 712;
+static constexpr dart::compiler::target::word
+    AOT_Thread_float_zerow_address_offset = 736;
+static constexpr dart::compiler::target::word
+    AOT_Thread_global_object_pool_offset = 1592;
+static constexpr dart::compiler::target::word
+    AOT_Thread_invoke_dart_code_stub_offset = 256;
+static constexpr dart::compiler::target::word
+    AOT_Thread_exit_through_ffi_offset = 1648;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
+static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
+    1704;
+static constexpr dart::compiler::target::word
+    AOT_Thread_field_table_values_offset = 128;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_return_stub_offset = 456;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_deopt_from_throw_stub_offset = 464;
+static constexpr dart::compiler::target::word
+    AOT_Thread_lazy_specialize_type_test_stub_offset = 480;
+static constexpr dart::compiler::target::word
+    AOT_Thread_marking_stack_block_offset = 160;
+static constexpr dart::compiler::target::word
+    AOT_Thread_megamorphic_call_checked_entry_offset = 600;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_entry_offset = 608;
+static constexpr dart::compiler::target::word
+    AOT_Thread_switchable_call_miss_stub_offset = 408;
+static constexpr dart::compiler::target::word
+    AOT_Thread_no_scope_native_wrapper_entry_point_offset = 664;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_with_fpu_regs_stub_offset = 280;
+static constexpr dart::compiler::target::word
+    AOT_Thread_late_initialization_error_shared_without_fpu_regs_stub_offset =
+        272;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_with_fpu_regs_stub_offset = 296;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_error_shared_without_fpu_regs_stub_offset = 288;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_with_fpu_regs_stub_offset = 312;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_arg_error_shared_without_fpu_regs_stub_offset = 304;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_with_fpu_regs_stub_offset = 328;
+static constexpr dart::compiler::target::word
+    AOT_Thread_null_cast_error_shared_without_fpu_regs_stub_offset = 320;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_with_fpu_regs_stub_offset = 344;
+static constexpr dart::compiler::target::word
+    AOT_Thread_range_error_shared_without_fpu_regs_stub_offset = 336;
+static constexpr dart::compiler::target::word AOT_Thread_object_null_offset =
+    200;
+static constexpr dart::compiler::target::word
+    AOT_Thread_predefined_symbols_address_offset = 680;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
+    1600;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_shadow_call_stack_offset = 1608;
+static constexpr dart::compiler::target::word
+    AOT_Thread_safepoint_state_offset = 1624;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_stub_offset = 472;
+static constexpr dart::compiler::target::word
+    AOT_Thread_slow_type_test_entry_point_offset = 648;
+static constexpr dart::compiler::target::word AOT_Thread_stack_limit_offset =
+    56;
+static constexpr dart::compiler::target::word
+    AOT_Thread_saved_stack_limit_offset = 112;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_flags_offset = 120;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 592;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 400;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 584;
+static constexpr dart::compiler::target::word
+    AOT_Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 392;
+static constexpr dart::compiler::target::word
+    AOT_Thread_store_buffer_block_offset = 152;
+static constexpr dart::compiler::target::word
+    AOT_Thread_top_exit_frame_info_offset = 144;
+static constexpr dart::compiler::target::word AOT_Thread_top_offset = 96;
+static constexpr dart::compiler::target::word AOT_Thread_top_resource_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word
+    AOT_Thread_unboxed_double_runtime_arg_offset = 192;
+static constexpr dart::compiler::target::word AOT_Thread_vm_tag_offset = 176;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_code_offset = 224;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_entry_point_offset = 520;
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_mask_offset = 64;
+static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 72;
+static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
+    1632;
+static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1640;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1672;
+static constexpr dart::compiler::target::word
+    AOT_Thread_jump_to_frame_entry_point_offset = 640;
+static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
+    1680;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_function_offset = 0;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_setjmp_buffer_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_pc_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_sp_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TsanUtils_exception_fp_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_TimelineStream_enabled_offset = 16;
+static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
+static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_named_parameter_names_offset = 48;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_nullability_offset = 71;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_parameter_counts_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_packed_type_parameter_counts_offset = 68;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
+    43;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_nullability_offset = 45;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
+    40;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_exception_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_stacktrace_offset = 16;
+static constexpr dart::compiler::target::word AOT_UserTag_tag_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_expected_cid_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_entrypoint_offset = 16;
+static constexpr dart::compiler::target::word AOT_WeakProperty_key_offset = 8;
+static constexpr dart::compiler::target::word AOT_WeakProperty_value_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
+    8, 24, 16, 32};
+static constexpr dart::compiler::target::word
+    AOT_Thread_write_barrier_wrappers_thread_offset[] = {
+        -1,   -1,   -1, -1, -1, 1432, 1440, 1448, -1,   -1,   1456,
+        1464, 1472, -1, -1, -1, 1480, 1488, 1496, 1504, 1512, 1520,
+        1528, 1536, -1, -1, -1, -1,   1544, 1552, 1560, 1568};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
+static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 136;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_ObjectHeaderSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_CompressedStackMaps_PayloadHeaderSize = 4;
+static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
+static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_ExternalOneByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTwoByteString_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_ExternalTypedData_InstanceSize = 24;
+static constexpr dart::compiler::target::word
+    AOT_FfiTrampolineData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
+static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_GrowableObjectArray_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
+static constexpr dart::compiler::target::word
+    AOT_InstructionsTable_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_KernelProgramInfo_InstanceSize = 120;
+static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_LinkedHashBase_InstanceSize =
+    56;
+static constexpr dart::compiler::target::word
+    AOT_MegamorphicCache_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Mint_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_MirrorReference_InstanceSize =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_MonomorphicSmiableCall_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Namespace_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_NativeArguments_StructSize =
+    32;
+static constexpr dart::compiler::target::word AOT_Number_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Object_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
+static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
+static constexpr dart::compiler::target::word
+    AOT_SingleTargetCache_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_String_InstanceSize = 16;
+static constexpr dart::compiler::target::word
+    AOT_SubtypeTestCache_InstanceSize = 16;
+static constexpr dart::compiler::target::word AOT_LoadingUnit_InstanceSize = 32;
+static constexpr dart::compiler::target::word
+    AOT_TransferableTypedData_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
+static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
+    24;
+static constexpr dart::compiler::target::word AOT_TypedDataView_InstanceSize =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_UnhandledException_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_UnlinkedCall_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word AOT_UnwindError_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_UserTag_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_WeakProperty_InstanceSize =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_WeakSerializationReference_InstanceSize = 24;
+#endif  // defined(TARGET_ARCH_RISCV64) && !defined(DART_COMPRESSED_POINTERS)
+
 #endif  // !defined(PRODUCT)
 
 #endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 1328b23..bff550b 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -223,6 +223,7 @@
   FIELD(Thread, enter_safepoint_stub_offset)                                   \
   FIELD(Thread, execution_state_offset)                                        \
   FIELD(Thread, exit_safepoint_stub_offset)                                    \
+  FIELD(Thread, exit_safepoint_ignore_unwind_in_progress_stub_offset)          \
   FIELD(Thread, call_native_through_safepoint_stub_offset)                     \
   FIELD(Thread, call_native_through_safepoint_entry_point_offset)              \
   FIELD(Thread, fix_allocation_stub_code_offset)                               \
@@ -334,10 +335,10 @@
   RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal,       \
         CodeEntryKind::kMonomorphicUnchecked,                                  \
         [](CodeEntryKind value) { return true; })                              \
-  ONLY_IN_ARM_ARM64_X64(RANGE(                                                 \
-      Thread, write_barrier_wrappers_thread_offset, Register, 0,               \
-      kNumberOfCpuRegisters - 1,                                               \
-      [](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
+  NOT_IN_IA32(RANGE(Thread, write_barrier_wrappers_thread_offset, Register, 0, \
+                    kNumberOfCpuRegisters - 1, [](Register reg) {              \
+                      return (kDartAvailableCpuRegs & (1 << reg)) != 0;        \
+                    }))                                                        \
                                                                                \
   SIZEOF(AbstractType, InstanceSize, UntaggedAbstractType)                     \
   SIZEOF(ApiError, InstanceSize, UntaggedApiError)                             \
@@ -350,7 +351,7 @@
   SIZEOF(CodeSourceMap, HeaderSize, UntaggedCodeSourceMap)                     \
   SIZEOF(CompressedStackMaps, ObjectHeaderSize, UntaggedCompressedStackMaps)   \
   SIZEOF(CompressedStackMaps, PayloadHeaderSize,                               \
-         UntaggedCompressedStackMaps::Payload)                                 \
+         UntaggedCompressedStackMaps::Payload::FlagsAndSizeHeader)             \
   SIZEOF(Context, header_size, UntaggedContext)                                \
   SIZEOF(Double, InstanceSize, UntaggedDouble)                                 \
   SIZEOF(DynamicLibrary, InstanceSize, UntaggedDynamicLibrary)                 \
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index c4d5c98..b70a40e 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -25,8 +25,7 @@
     Register cpu_register) {
   ASSERT(RegisterSet::Contains(kDartAvailableCpuRegs, cpu_register));
 
-  // Skip FP + saved PC.
-  intptr_t slots_from_fp = 2;
+  intptr_t slots_from_fp = target::frame_layout.param_end_from_fp + 1;
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
     Register reg = static_cast<Register>(i);
     if (reg == cpu_register) break;
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index fc28901..6c4b3ae 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -133,6 +133,16 @@
   static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
 #endif
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
+#elif defined(TARGET_ARCH_RISCV32)
+  static constexpr intptr_t kNativeCallbackTrampolineSize = 8;
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 192;
+  static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
+#elif defined(TARGET_ARCH_RISCV64)
+  static constexpr intptr_t kNativeCallbackTrampolineSize = 8;
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 196;
+  static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
+#else
+#error What architecture?
 #endif
 
   static void GenerateJITCallbackTrampolines(Assembler* assembler,
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index e31e943..602dfb2 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -318,7 +318,8 @@
   __ Ret();
 }
 
-void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+static void GenerateExitSafepointStubCommon(Assembler* assembler,
+                                            uword runtime_entry_offset) {
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
@@ -332,7 +333,7 @@
   __ LoadImmediate(R0, target::Thread::vm_execution_state());
   __ str(R0, Address(THR, target::Thread::execution_state_offset()));
 
-  __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
+  __ ldr(R0, Address(THR, runtime_entry_offset));
   __ blx(R0);
   RESTORES_LR_FROM_FRAME(__ LeaveFrame((1 << FP) | (1 << LR), 0));
 
@@ -340,6 +341,18 @@
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
+}
+
+void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
+    Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler,
+      kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
+}
+
 // Call a native function within a safepoint.
 //
 // On entry:
@@ -2896,14 +2909,20 @@
 #endif
   Label exit_through_non_ffi;
   Register tmp1 = R0, tmp2 = R1;
-  // Check if we exited generated from FFI. If so do transition.
+  // Check if we exited generated from FFI. If so do transition - this is needed
+  // because normally runtime calls transition back to generated via destructor
+  // of TransititionGeneratedToVM/Native that is part of runtime boilerplate
+  // code (see DEFINE_RUNTIME_ENTRY_IMPL in runtime_entry.h). Ffi calls don't
+  // have this boilerplate, don't have this stack resource, have to transition
+  // explicitly.
   __ LoadFromOffset(tmp1, THR,
                     compiler::target::Thread::exit_through_ffi_offset());
   __ LoadImmediate(tmp2, target::Thread::exit_through_ffi());
   __ cmp(tmp1, Operand(tmp2));
   __ b(&exit_through_non_ffi, NE);
   __ TransitionNativeToGenerated(tmp1, tmp2,
-                                 /*leave_safepoint=*/true);
+                                 /*leave_safepoint=*/true,
+                                 /*ignore_unwind_in_progress=*/true);
   __ Bind(&exit_through_non_ffi);
 
   // Set the tag.
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index af8d3c5..4d22204 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -250,7 +250,8 @@
   __ Ret();
 }
 
-void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+static void GenerateExitSafepointStubCommon(Assembler* assembler,
+                                            uword runtime_entry_offset) {
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
 
@@ -268,7 +269,7 @@
   __ LoadImmediate(R0, target::Thread::vm_execution_state());
   __ str(R0, Address(THR, target::Thread::execution_state_offset()));
 
-  __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
+  __ ldr(R0, Address(THR, runtime_entry_offset));
   __ blr(R0);
 
   __ mov(SP, CALLEE_SAVED_TEMP2);
@@ -280,6 +281,18 @@
   __ Ret();
 }
 
+void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
+}
+
+void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
+    Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler,
+      kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
+}
+
 // Calls native code within a safepoint.
 //
 // On entry:
@@ -1948,15 +1961,15 @@
       Label not_parameterized_case;
 
       const Register kClsIdReg = R4;
-      const Register kTypeOffestReg = R5;
+      const Register kTypeOffsetReg = R5;
 
       __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
 
       // Load class' type_arguments_field offset in words.
-      __ LoadClassById(kTypeOffestReg, kClsIdReg);
+      __ LoadClassById(kTypeOffsetReg, kClsIdReg);
       __ ldr(
-          kTypeOffestReg,
-          FieldAddress(kTypeOffestReg,
+          kTypeOffsetReg,
+          FieldAddress(kTypeOffsetReg,
                        target::Class::
                            host_type_arguments_field_offset_in_words_offset()),
           kFourBytes);
@@ -1964,7 +1977,7 @@
       // Set the type arguments in the new object.
       __ StoreCompressedIntoObjectNoBarrier(
           AllocateObjectABI::kResultReg,
-          Address(AllocateObjectABI::kResultReg, kTypeOffestReg, UXTX,
+          Address(AllocateObjectABI::kResultReg, kTypeOffsetReg, UXTX,
                   Address::Scaled),
           AllocateObjectABI::kTypeArgumentsReg);
 
@@ -3092,13 +3105,19 @@
 #endif
   Label exit_through_non_ffi;
   Register tmp1 = R0, tmp2 = R1;
-  // Check if we exited generated from FFI. If so do transition.
+  // Check if we exited generated from FFI. If so do transition - this is needed
+  // because normally runtime calls transition back to generated via destructor
+  // of TransititionGeneratedToVM/Native that is part of runtime boilerplate
+  // code (see DEFINE_RUNTIME_ENTRY_IMPL in runtime_entry.h). Ffi calls don't
+  // have this boilerplate, don't have this stack resource, have to transition
+  // explicitly.
   __ LoadFromOffset(tmp1, THR,
                     compiler::target::Thread::exit_through_ffi_offset());
   __ LoadImmediate(tmp2, target::Thread::exit_through_ffi());
   __ cmp(tmp1, Operand(tmp2));
   __ b(&exit_through_non_ffi, NE);
-  __ TransitionNativeToGenerated(tmp1, /*leave_safepoint=*/true);
+  __ TransitionNativeToGenerated(tmp1, /*leave_safepoint=*/true,
+                                 /*ignore_unwind_in_progress=*/true);
   __ Bind(&exit_through_non_ffi);
 
   // Refresh pinned registers values (inc. write barrier mask and null object).
@@ -3704,9 +3723,7 @@
     /* R0: new object start as a tagged pointer. */
     /* R1: new object end address. */
     /* R2: iterator which initially points to the start of the variable */
-    /* R3: scratch register. */
     /* data area to be initialized. */
-    __ mov(R3, ZR);
     __ AddImmediate(R2, R0, target::TypedData::HeaderSize() - 1);
     __ StoreInternalPointer(
         R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R2);
@@ -3714,7 +3731,7 @@
     __ Bind(&init_loop);
     __ cmp(R2, Operand(R1));
     __ b(&done, CS);
-    __ str(R3, Address(R2, 0));
+    __ str(ZR, Address(R2, 0));
     __ add(R2, R2, Operand(target::kWordSize));
     __ b(&init_loop);
     __ Bind(&done);
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 654e0ef..e75588c 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -157,7 +157,8 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+static void GenerateExitSafepointStubCommon(Assembler* assembler,
+                                            uword runtime_entry_offset) {
   __ pushal();
   __ subl(SPREG, Immediate(8));
   __ movsd(Address(SPREG, 0), XMM0);
@@ -171,7 +172,7 @@
   __ movl(Address(THR, target::Thread::execution_state_offset()),
           Immediate(target::Thread::vm_execution_state()));
 
-  __ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
+  __ movl(EAX, Address(THR, runtime_entry_offset));
   __ call(EAX);
   __ LeaveFrame();
 
@@ -181,6 +182,18 @@
   __ ret();
 }
 
+void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
+}
+
+void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
+    Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler,
+      kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
+}
+
 // Calls a native function inside a safepoint.
 //
 // On entry:
@@ -2527,12 +2540,18 @@
 #endif
 
   Label exit_through_non_ffi;
-  // Check if we exited generated from FFI. If so do transition.
+  // Check if we exited generated from FFI. If so do transition - this is needed
+  // because normally runtime calls transition back to generated via destructor
+  // of TransititionGeneratedToVM/Native that is part of runtime boilerplate
+  // code (see DEFINE_RUNTIME_ENTRY_IMPL in runtime_entry.h). Ffi calls don't
+  // have this boilerplate, don't have this stack resource, have to transition
+  // explicitly.
   __ cmpl(compiler::Address(
               THR, compiler::target::Thread::exit_through_ffi_offset()),
           compiler::Immediate(target::Thread::exit_through_ffi()));
   __ j(NOT_EQUAL, &exit_through_non_ffi, compiler::Assembler::kNearJump);
-  __ TransitionNativeToGenerated(ECX, /*leave_safepoint=*/true);
+  __ TransitionNativeToGenerated(ECX, /*leave_safepoint=*/true,
+                                 /*ignore_unwind_in_progress=*/true);
   __ Bind(&exit_through_non_ffi);
 
   // Set tag.
diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc
new file mode 100644
index 0000000..ec19d60
--- /dev/null
+++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc
@@ -0,0 +1,3651 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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"
+
+// For `AllocateObjectInstr::WillAllocateNewOrRemembered`
+// For `GenericCheckBoundInstr::UseUnboxedRepresentation`
+#include "vm/compiler/backend/il.h"
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/stub_code_compiler.h"
+
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/class_id.h"
+#include "vm/code_entry_kind.h"
+#include "vm/compiler/api/type_check_mode.h"
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/constants.h"
+#include "vm/instructions.h"
+#include "vm/static_type_exactness_state.h"
+#include "vm/tags.h"
+
+#define __ assembler->
+
+namespace dart {
+namespace compiler {
+
+// Ensures that [A0] is a new object, if not it will be added to the remembered
+// set via a leaf runtime call.
+//
+// WARNING: This might clobber all registers except for [A0], [THR] and [FP].
+// The caller should simply call LeaveStubFrame() and return.
+void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler,
+                                               bool preserve_registers) {
+  // If the object is not remembered we call a leaf-runtime to add it to the
+  // remembered set.
+  Label done;
+  __ andi(TMP2, A0, 1 << target::ObjectAlignment::kNewObjectBitPosition);
+  __ bnez(TMP2, &done);
+
+  {
+    Assembler::CallRuntimeScope scope(
+        assembler, kEnsureRememberedAndMarkingDeferredRuntimeEntry,
+        /*frame_size=*/0, /*preserve_registers=*/preserve_registers);
+    __ mv(A1, THR);
+    scope.Call(/*argument_count=*/2);
+  }
+
+  __ Bind(&done);
+}
+
+// Input parameters:
+//   RA : return address.
+//   SP : address of last argument in argument array.
+//   SP + 8*T4 - 8 : address of first argument in argument array.
+//   SP + 8*T4 : address of return value.
+//   T5 : address of the runtime function to call.
+//   T4 : number of arguments to the call.
+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");
+  __ lx(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, target::Thread::top_exit_frame_info_offset());
+
+  // Mark that the thread exited generated code through a runtime call.
+  __ LoadImmediate(TMP, target::Thread::exit_through_runtime_call());
+  __ StoreToOffset(TMP, THR, target::Thread::exit_through_ffi_offset());
+
+#if defined(DEBUG)
+  {
+    Label ok;
+    // Check that we are always entering from Dart code.
+    __ LoadFromOffset(TMP, THR, target::Thread::vm_tag_offset());
+    __ CompareImmediate(TMP, VMTag::kDartTagId);
+    __ BranchIf(EQ, &ok);
+    __ Stop("Not coming from Dart code.");
+    __ Bind(&ok);
+  }
+#endif
+
+  // Mark that the thread is executing VM code.
+  __ StoreToOffset(T5, THR, target::Thread::vm_tag_offset());
+
+  // Reserve space for arguments and align frame before entering C++ world.
+  // target::NativeArguments are passed in registers.
+  __ Comment("align stack");
+  // Reserve space for arguments.
+  ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
+
+  // Pass target::NativeArguments structure by value and call runtime.
+  // Registers R0, R1, R2, and R3 are used.
+
+  ASSERT(thread_offset == 0 * target::kWordSize);
+  // 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 * target::kWordSize);
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  __ slli(T2, T4, target::kWordSizeLog2);
+  __ add(T2, FP, T2);  // Compute argv.
+  // Set argv in target::NativeArguments.
+  __ AddImmediate(T2,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
+
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ AddImmediate(T3, T2, target::kWordSize);
+
+  __ StoreToOffset(THR, SP, thread_offset);
+  __ StoreToOffset(T4, SP, argc_tag_offset);
+  __ StoreToOffset(T2, SP, argv_offset);
+  __ StoreToOffset(T3, SP, retval_offset);
+  __ mv(A0, SP);  // Pass the pointer to the target::NativeArguments.
+
+  ASSERT(IsAbiPreservedRegister(THR));
+  __ jalr(T5);
+  __ Comment("CallToRuntimeStub return");
+
+  // Refresh pinned registers values (inc. write barrier mask and null object).
+  __ RestorePinnedRegisters();
+
+  // Retval is next to 1st argument.
+  // Mark that the thread is executing Dart code.
+  __ LoadImmediate(TMP, VMTag::kDartTagId);
+  __ StoreToOffset(TMP, THR, target::Thread::vm_tag_offset());
+
+  // Mark that the thread has not exited generated Dart code.
+  __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
+
+  // Reset exit frame information in Isolate's mutator thread structure.
+  __ 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) {
+    __ SetupGlobalPoolAndDispatchTable();
+  }
+
+  __ LeaveStubFrame();
+
+  // The following return can jump to a lazy-deopt stub, which assumes A0
+  // contains a return value and will save it in a GC-visible way.  We therefore
+  // have to ensure A0 does not contain any garbage value left from the C
+  // function we called (which has return type "void").
+  // (See GenerateDeoptimizationSequence::saved_result_slot_from_fp.)
+  __ LoadImmediate(A0, 0);
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateSharedStubGeneric(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return,
+    std::function<void()> perform_runtime_call) {
+  // We want the saved registers to appear like part of the caller's frame, so
+  // we push them before calling EnterStubFrame.
+  RegisterSet all_registers;
+  all_registers.AddAllNonReservedRegisters(save_fpu_registers);
+
+  // To make the stack map calculation architecture independent we do the same
+  // as on intel.
+  __ PushRegister(RA);
+  __ PushRegisters(all_registers);
+  __ lx(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
+  __ EnterStubFrame();
+  perform_runtime_call();
+  if (!allow_return) {
+    __ Breakpoint();
+    return;
+  }
+  __ LeaveStubFrame();
+  __ PopRegisters(all_registers);
+  __ Drop(1);  // We use the RA restored via LeaveStubFrame.
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return,
+    bool store_runtime_result_in_result_register) {
+  ASSERT(!store_runtime_result_in_result_register || allow_return);
+  auto perform_runtime_call = [&]() {
+    if (store_runtime_result_in_result_register) {
+      __ PushRegister(NULL_REG);
+    }
+    __ CallRuntime(*target, /*argument_count=*/0);
+    if (store_runtime_result_in_result_register) {
+      __ PopRegister(A0);
+      __ sx(A0, Address(FP, target::kWordSize *
+                                StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                    SharedSlowPathStubABI::kResultReg)));
+    }
+  };
+  GenerateSharedStubGeneric(assembler, save_fpu_registers,
+                            self_code_stub_offset_from_thread, allow_return,
+                            perform_runtime_call);
+}
+
+void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
+  RegisterSet all_registers;
+  all_registers.AddAllGeneralRegisters();
+
+  __ EnterFrame(0);
+  __ PushRegisters(all_registers);
+
+  __ ReserveAlignedFrameSpace(0);
+
+  __ lx(TMP, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
+  __ jalr(TMP);
+
+  __ PopRegisters(all_registers);
+  __ LeaveFrame();
+  __ ret();
+}
+
+static void GenerateExitSafepointStubCommon(Assembler* assembler,
+                                            uword runtime_entry_offset) {
+  RegisterSet all_registers;
+  all_registers.AddAllGeneralRegisters();
+
+  __ EnterFrame(0);
+  __ PushRegisters(all_registers);
+
+  __ ReserveAlignedFrameSpace(0);
+
+  // Set the execution state to VM while waiting for the safepoint to end.
+  // This isn't strictly necessary but enables tests to check that we're not
+  // in native code anymore. See tests/ffi/function_gc_test.dart for example.
+  __ LoadImmediate(TMP, target::Thread::vm_execution_state());
+  __ sx(TMP, Address(THR, target::Thread::execution_state_offset()));
+
+  __ lx(TMP, Address(THR, runtime_entry_offset));
+  __ jalr(TMP);
+
+  __ PopRegisters(all_registers);
+  __ LeaveFrame();
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
+}
+
+void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
+    Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler,
+      kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
+}
+
+// Calls native code within a safepoint.
+//
+// On entry:
+//   T0: target to call
+//   Stack: set up for native call (SP), aligned, CSP < SP
+//
+// On exit:
+//   S2: clobbered, although normally callee-saved
+//   Stack: preserved, CSP == SP
+void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
+    Assembler* assembler) {
+  COMPILE_ASSERT(IsAbiPreservedRegister(S2));
+  __ mv(S2, RA);
+  __ LoadImmediate(T1, target::Thread::exit_through_ffi());
+  __ TransitionGeneratedToNative(T0, FPREG, T1 /*volatile*/,
+                                 /*enter_safepoint=*/true);
+
+#if defined(DEBUG)
+  // Check SP alignment.
+  __ andi(T2 /*volatile*/, SP, ~(OS::ActivationFrameAlignment() - 1));
+  Label done;
+  __ beq(T2, SP, &done);
+  __ Breakpoint();
+  __ Bind(&done);
+#endif
+
+  __ jalr(T0);
+
+  __ TransitionNativeToGenerated(T1, /*leave_safepoint=*/true);
+  __ jr(S2);
+}
+
+#if !defined(DART_PRECOMPILER)
+void StubCodeCompiler::GenerateJITCallbackTrampolines(
+    Assembler* assembler,
+    intptr_t next_callback_id) {
+#if defined(USING_SIMULATOR)
+  // TODO(37299): FFI is not support in SIMRISCV32/64.
+  __ ebreak();
+#else
+  Label loaded_callback_id_hi;
+
+  // T1 is volatile and not used for passing any arguments.
+  COMPILE_ASSERT(!IsCalleeSavedRegister(T1) && !IsArgumentRegister(T1));
+  for (intptr_t i = 0;
+       i < NativeCallbackTrampolines::NumCallbackTrampolinesPerPage(); ++i) {
+    // We don't use LoadImmediate because we need the trampoline size to be
+    // fixed independently of the callback ID.
+    // lui has 20 bits of range.
+    __ lui_fixed(T1, (next_callback_id + i) << 12);
+    __ j(&loaded_callback_id_hi);
+  }
+
+  ASSERT(__ CodeSize() ==
+         kNativeCallbackTrampolineSize *
+             NativeCallbackTrampolines::NumCallbackTrampolinesPerPage());
+
+  __ Bind(&loaded_callback_id_hi);
+  __ srai(T1, T1, 12);
+
+  const intptr_t shared_stub_start = __ CodeSize();
+
+  // Save THR (callee-saved) and RA. Keeps stack aligned.
+  COMPILE_ASSERT(StubCodeCompiler::kNativeCallbackTrampolineStackDelta == 2);
+  __ PushRegisterPair(RA, THR);
+  COMPILE_ASSERT(!IsArgumentRegister(THR));
+
+  RegisterSet all_registers;
+  all_registers.AddAllArgumentRegisters();
+
+  // The call below might clobber T1 (volatile, holding callback_id).
+  all_registers.Add(Location::RegisterLocation(T1));
+
+  // Load the thread, verify the callback ID and exit the safepoint.
+  //
+  // We exit the safepoint inside DLRT_GetThreadForNativeCallbackTrampoline
+  // in order to safe code size on this shared stub.
+  {
+    __ PushRegisters(all_registers);
+    __ EnterFrame(0);
+    __ ReserveAlignedFrameSpace(0);
+
+    // Since DLRT_GetThreadForNativeCallbackTrampoline can theoretically be
+    // loaded anywhere, we use the same trick as before to ensure a predictable
+    // instruction sequence.
+    Label call;
+    __ mv(A0, T1);
+
+    const intptr_t kPCRelativeLoadOffset = 12;
+    intptr_t start = __ CodeSize();
+    __ auipc(T1, 0);
+    __ lx(T1, Address(T1, kPCRelativeLoadOffset));
+    __ j(&call);
+
+    ASSERT_EQUAL(__ CodeSize() - start, kPCRelativeLoadOffset);
+#if XLEN == 32
+    __ Emit32(
+        reinterpret_cast<int32_t>(&DLRT_GetThreadForNativeCallbackTrampoline));
+#else
+    __ Emit64(
+        reinterpret_cast<int64_t>(&DLRT_GetThreadForNativeCallbackTrampoline));
+#endif
+
+    __ Bind(&call);
+    __ jalr(T1);
+    __ mv(THR, A0);
+
+    __ LeaveFrame();
+
+    __ PopRegisters(all_registers);
+  }
+
+  COMPILE_ASSERT(!IsCalleeSavedRegister(T2) && !IsArgumentRegister(T2));
+  COMPILE_ASSERT(!IsCalleeSavedRegister(T3) && !IsArgumentRegister(T3));
+
+  // Load the code object.
+  __ LoadFromOffset(T2, THR, compiler::target::Thread::callback_code_offset());
+  __ LoadCompressedFieldFromOffset(
+      T2, T2, compiler::target::GrowableObjectArray::data_offset());
+  __ LoadCompressed(
+      T2,
+      __ ElementAddressForRegIndex(
+          /*external=*/false,
+          /*array_cid=*/kArrayCid,
+          /*index_scale, smi-tagged=*/compiler::target::kCompressedWordSize * 2,
+          /*index_unboxed=*/false,
+          /*array=*/T2,
+          /*index=*/T1,
+          /*temp=*/T3));
+  __ LoadFieldFromOffset(T2, T2, compiler::target::Code::entry_point_offset());
+
+  // Clobbers all volatile registers, including the callback ID in T1.
+  __ jalr(T2);
+
+  // Clobbers TMP, TMP2 and T1 -- all volatile and not holding return values.
+  __ EnterFullSafepoint(/*scratch=*/T1);
+
+  __ PopRegisterPair(RA, THR);
+  __ ret();
+
+  ASSERT_EQUAL((__ CodeSize() - shared_stub_start),
+               kNativeCallbackSharedStubSize);
+  ASSERT(__ CodeSize() <= VirtualMemory::PageSize());
+
+#if defined(DEBUG)
+  while (__ CodeSize() < VirtualMemory::PageSize()) {
+    __ ebreak();
+  }
+#endif
+#endif
+}
+#endif  // !defined(DART_PRECOMPILER)
+
+// T1: The extracted method.
+// T4: The type_arguments_field_offset (or 0)
+void StubCodeCompiler::GenerateBuildMethodExtractorStub(
+    Assembler* assembler,
+    const Code& closure_allocation_stub,
+    const Code& context_allocation_stub,
+    bool generic) {
+  const intptr_t kReceiverOffset = target::frame_layout.param_end_from_fp + 1;
+
+  __ EnterStubFrame();
+
+  // Build type_arguments vector (or null)
+  Label no_type_args;
+  __ lx(T3, Address(THR, target::Thread::object_null_offset()));
+  __ CompareImmediate(T4, 0);
+  __ BranchIf(EQ, &no_type_args);
+  __ lx(T0, Address(FP, kReceiverOffset * target::kWordSize));
+  __ add(TMP, T0, T4);
+  __ LoadCompressed(T3, Address(TMP, 0));
+  __ Bind(&no_type_args);
+
+  // Push type arguments & extracted method.
+  __ PushRegister(T3);
+  __ PushRegister(T1);
+
+  // Allocate context.
+  {
+    Label done, slow_path;
+    if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+      __ TryAllocateArray(kContextCid, target::Context::InstanceSize(1),
+                          &slow_path,
+                          A0,  // instance
+                          T1,  // end address
+                          T2, T3);
+      __ StoreCompressedIntoObjectNoBarrier(
+          A0, FieldAddress(A0, target::Context::parent_offset()), NULL_REG);
+      __ LoadImmediate(T1, 1);
+      __ sw(T1, FieldAddress(A0, target::Context::num_variables_offset()));
+      __ j(&done, compiler::Assembler::kNearJump);
+    }
+
+    __ Bind(&slow_path);
+
+    __ LoadImmediate(/*num_vars=*/T1, 1);
+    __ LoadObject(CODE_REG, context_allocation_stub);
+    __ lx(RA, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+    __ jalr(RA);
+
+    __ Bind(&done);
+  }
+
+  // Put context in right register for AllocateClosure call.
+  __ MoveRegister(AllocateClosureABI::kContextReg, A0);
+
+  // Store receiver in context
+  __ lx(AllocateClosureABI::kScratchReg,
+        Address(FP, target::kWordSize * kReceiverOffset));
+  __ StoreCompressedIntoObject(
+      AllocateClosureABI::kContextReg,
+      FieldAddress(AllocateClosureABI::kContextReg,
+                   target::Context::variable_offset(0)),
+      AllocateClosureABI::kScratchReg);
+
+  // Pop function before pushing context.
+  __ PopRegister(AllocateClosureABI::kFunctionReg);
+
+  // Allocate closure. After this point, we only use the registers in
+  // AllocateClosureABI.
+  __ LoadObject(CODE_REG, closure_allocation_stub);
+  __ lx(AllocateClosureABI::kScratchReg,
+        FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+  __ jalr(AllocateClosureABI::kScratchReg);
+
+  // Populate closure object.
+  __ PopRegister(AllocateClosureABI::kScratchReg);  // Pop type arguments.
+  __ StoreCompressedIntoObjectNoBarrier(
+      AllocateClosureABI::kResultReg,
+      FieldAddress(AllocateClosureABI::kResultReg,
+                   target::Closure::instantiator_type_arguments_offset()),
+      AllocateClosureABI::kScratchReg);
+  // Keep delayed_type_arguments as null if non-generic (see Closure::New).
+  if (generic) {
+    __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
+    __ StoreCompressedIntoObjectNoBarrier(
+        AllocateClosureABI::kResultReg,
+        FieldAddress(AllocateClosureABI::kResultReg,
+                     target::Closure::delayed_type_arguments_offset()),
+        AllocateClosureABI::kScratchReg);
+  }
+
+  __ LeaveStubFrame();
+  // No-op if the two are the same.
+  __ MoveRegister(A0, AllocateClosureABI::kResultReg);
+  __ Ret();
+}
+
+void StubCodeCompiler::GenerateDispatchTableNullErrorStub(
+    Assembler* assembler) {
+  __ EnterStubFrame();
+  __ SmiTag(DispatchTableNullErrorABI::kClassIdReg);
+  __ PushRegister(DispatchTableNullErrorABI::kClassIdReg);
+  __ CallRuntime(kDispatchTableNullErrorRuntimeEntry, /*argument_count=*/1);
+  // The NullError runtime entry does not return.
+  __ Breakpoint();
+}
+
+void StubCodeCompiler::GenerateRangeError(Assembler* assembler,
+                                          bool with_fpu_regs) {
+  auto perform_runtime_call = [&]() {
+  // If the generated code has unboxed index/length we need to box them before
+  // calling the runtime entry.
+#if XLEN == 32
+    ASSERT(!GenericCheckBoundInstr::UseUnboxedRepresentation());
+#else
+    if (GenericCheckBoundInstr::UseUnboxedRepresentation()) {
+      Label length, smi_case;
+
+      // The user-controlled index might not fit into a Smi.
+      __ mv(TMP, RangeErrorABI::kIndexReg);
+      __ SmiTag(RangeErrorABI::kIndexReg, RangeErrorABI::kIndexReg);
+      __ SmiUntag(TMP2, RangeErrorABI::kIndexReg);
+      __ beq(TMP, TMP2, &length);  // No overflow.
+      {
+        // Allocate a mint, reload the two registers and popualte the mint.
+        __ PushRegister(NULL_REG);
+        __ CallRuntime(kAllocateMintRuntimeEntry, /*argument_count=*/0);
+        __ PopRegister(RangeErrorABI::kIndexReg);
+        __ lx(TMP,
+              Address(FP, target::kWordSize *
+                              StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                  RangeErrorABI::kIndexReg)));
+        __ sx(TMP, FieldAddress(RangeErrorABI::kIndexReg,
+                                target::Mint::value_offset()));
+        __ lx(RangeErrorABI::kLengthReg,
+              Address(FP, target::kWordSize *
+                              StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                  RangeErrorABI::kLengthReg)));
+      }
+
+      // Length is guaranteed to be in positive Smi range (it comes from a load
+      // of a vm recognized array).
+      __ Bind(&length);
+      __ SmiTag(RangeErrorABI::kLengthReg);
+    }
+#endif  // XLEN != 32
+    __ PushRegister(RangeErrorABI::kLengthReg);
+    __ PushRegister(RangeErrorABI::kIndexReg);
+    __ CallRuntime(kRangeErrorRuntimeEntry, /*argument_count=*/2);
+    __ Breakpoint();
+  };
+
+  GenerateSharedStubGeneric(
+      assembler, /*save_fpu_registers=*/with_fpu_regs,
+      with_fpu_regs
+          ? target::Thread::range_error_shared_with_fpu_regs_stub_offset()
+          : target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false, perform_runtime_call);
+}
+
+// Input parameters:
+//   RA : return address.
+//   SP : address of return value.
+//   T5 : address of the native function to call.
+//   T2 : address of first argument in argument array.
+//   T1 : argc_tag including number of arguments and function kind.
+static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
+                                              Address wrapper) {
+  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, target::Thread::top_exit_frame_info_offset());
+
+  // Mark that the thread exited generated code through a runtime call.
+  __ LoadImmediate(TMP, target::Thread::exit_through_runtime_call());
+  __ StoreToOffset(TMP, THR, target::Thread::exit_through_ffi_offset());
+
+#if defined(DEBUG)
+  {
+    Label ok;
+    // Check that we are always entering from Dart code.
+    __ LoadFromOffset(TMP, THR, target::Thread::vm_tag_offset());
+    __ CompareImmediate(TMP, VMTag::kDartTagId);
+    __ BranchIf(EQ, &ok);
+    __ Stop("Not coming from Dart code.");
+    __ Bind(&ok);
+  }
+#endif
+
+  // Mark that the thread is executing native code.
+  __ StoreToOffset(T5, 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(target::NativeArguments::StructSize());
+
+  // Initialize target::NativeArguments structure and call native function.
+  ASSERT(thread_offset == 0 * target::kWordSize);
+  // 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 * target::kWordSize);
+  // Set argc in target::NativeArguments: R1 already contains argc.
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  // Set argv in target::NativeArguments: R2 already contains argv.
+  // Set retval in NativeArgs.
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ AddImmediate(T3, FP, 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.
+  __ StoreToOffset(THR, SP, thread_offset);
+  __ StoreToOffset(T1, SP, argc_tag_offset);
+  __ StoreToOffset(T2, SP, argv_offset);
+  __ StoreToOffset(T3, SP, retval_offset);
+  __ mv(A0, SP);  // Pass the pointer to the target::NativeArguments.
+  __ mv(A1, T5);  // Pass the function entrypoint to call.
+
+  // Call native function invocation wrapper or redirection via simulator.
+  ASSERT(IsAbiPreservedRegister(THR));
+  __ Call(wrapper);
+
+  // Refresh pinned registers values (inc. write barrier mask and null object).
+  __ RestorePinnedRegisters();
+
+  // Mark that the thread is executing Dart code.
+  __ LoadImmediate(TMP, VMTag::kDartTagId);
+  __ StoreToOffset(TMP, THR, target::Thread::vm_tag_offset());
+
+  // Mark that the thread has not exited generated Dart code.
+  __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
+
+  // Reset exit frame information in Isolate's mutator thread structure.
+  __ 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) {
+    __ SetupGlobalPoolAndDispatchTable();
+  }
+
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateCallNoScopeNativeStub(Assembler* assembler) {
+  GenerateCallNativeWithWrapperStub(
+      assembler,
+      Address(THR,
+              target::Thread::no_scope_native_wrapper_entry_point_offset()));
+}
+
+void StubCodeCompiler::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
+  GenerateCallNativeWithWrapperStub(
+      assembler,
+      Address(THR,
+              target::Thread::auto_scope_native_wrapper_entry_point_offset()));
+}
+
+// Input parameters:
+//   RA : return address.
+//   SP : address of return value.
+//   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 StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
+  GenerateCallNativeWithWrapperStub(
+      assembler,
+      Address(THR,
+              target::Thread::bootstrap_native_wrapper_entry_point_offset()));
+}
+
+// Input parameters:
+//   S4: arguments descriptor array.
+void StubCodeCompiler::GenerateCallStaticFunctionStub(Assembler* assembler) {
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+  __ subi(SP, SP, 2 * target::kWordSize);
+  __ sx(S4, Address(SP, 1 * target::kWordSize));  // Preserve args descriptor.
+  __ sx(ZR, Address(SP, 0 * target::kWordSize));  // Result slot.
+  __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
+  __ lx(CODE_REG, Address(SP, 0 * target::kWordSize));  // Result.
+  __ lx(S4, Address(SP, 1 * target::kWordSize));  // Restore args descriptor.
+  __ addi(SP, SP, 2 * target::kWordSize);
+  __ LeaveStubFrame();
+  // Jump to the dart function.
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+}
+
+// Called from a static call only when an invalid code has been entered
+// (invalid because its function was optimized or deoptimized).
+// S4: arguments descriptor array.
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
+  Label monomorphic;
+  __ BranchOnMonomorphicCheckedEntryJIT(&monomorphic);
+
+  // 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.
+  __ lx(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();
+  // Setup space on stack for return value and preserve arguments descriptor.
+  __ PushRegister(S4);
+  __ PushRegister(ZR);
+  __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
+  // Get Code object result and restore arguments descriptor array.
+  __ PopRegister(CODE_REG);
+  __ PopRegister(S4);
+  // Remove the stub frame.
+  __ LeaveStubFrame();
+  // Jump to the dart function.
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+
+  __ Bind(&monomorphic);
+  // 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.
+  __ lx(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();
+  __ PushRegister(ZR);  // Result slot.
+  __ PushRegister(A0);  // Preserve receiver.
+  __ PushRegister(S5);  // Old cache value (also 2nd return value).
+  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+  __ PopRegister(S5);        // Get target cache object.
+  __ PopRegister(A0);        // Restore receiver.
+  __ PopRegister(CODE_REG);  // Get target Code object.
+  // Remove the stub frame.
+  __ LeaveStubFrame();
+  // Jump to the dart function.
+  __ LoadFieldFromOffset(
+      TMP, CODE_REG,
+      target::Code::entry_point_offset(CodeEntryKind::kMonomorphic));
+  __ jr(TMP);
+}
+
+// Called from object allocate instruction when the allocation stub has been
+// disabled.
+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.
+  __ lx(CODE_REG,
+        Address(THR, target::Thread::fix_allocation_stub_code_offset()));
+  __ EnterStubFrame();
+  // Setup space on stack for return value.
+  __ PushRegister(ZR);
+  __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
+  // Get Code object result.
+  __ PopRegister(CODE_REG);
+  // Remove the stub frame.
+  __ LeaveStubFrame();
+  // Jump to the dart function.
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+}
+
+// Input parameters:
+//   T2: smi-tagged argument count, may be zero.
+//   FP[target::frame_layout.param_end_from_fp + 1]: last argument.
+static void PushArrayOfArguments(Assembler* assembler) {
+  COMPILE_ASSERT(AllocateArrayABI::kLengthReg == T2);
+  COMPILE_ASSERT(AllocateArrayABI::kTypeArgumentsReg == T1);
+
+  // Allocate array to store arguments of caller.
+  __ LoadObject(T1, NullObject());
+  // T1: null element type for raw Array.
+  // T2: smi-tagged argument count, may be zero.
+  __ JumpAndLink(StubCodeAllocateArray());
+  // A0: newly allocated array.
+  // T2: smi-tagged argument count, may be zero (was preserved by the stub).
+  __ PushRegister(A0);  // Array is in A0 and on top of stack.
+  __ SmiUntag(T2);
+  __ slli(T1, T2, target::kWordSizeLog2);
+  __ add(T1, T1, FP);
+  __ AddImmediate(T1,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
+  __ AddImmediate(T3, A0, target::Array::data_offset() - kHeapObjectTag);
+  // T1: address of first argument on stack.
+  // T3: address of first argument in array.
+
+  Label loop, loop_exit;
+  __ Bind(&loop);
+  __ beqz(T2, &loop_exit);
+  __ lx(T6, Address(T1, 0));
+  __ addi(T1, T1, -target::kWordSize);
+  __ StoreCompressedIntoObject(A0, Address(T3, 0), T6);
+  __ addi(T3, T3, target::kCompressedWordSize);
+  __ addi(T2, T2, -1);
+  __ j(&loop);
+  __ Bind(&loop_exit);
+}
+
+// Used by eager and lazy deoptimization. Preserve result in RAX if necessary.
+// This stub translates optimized frame into unoptimized frame. The optimized
+// frame can contain values in registers and on stack, the unoptimized
+// frame contains all values on stack.
+// Deoptimization occurs in following steps:
+// - Push all registers that can contain values.
+// - Call C routine to copy the stack and saved registers into temporary buffer.
+// - Adjust caller's frame to correct unoptimized frame size.
+// - Fill the unoptimized frame.
+// - Materialize objects that require allocation (e.g. Double instances).
+// GC can occur only after frame is fully rewritten.
+// Stack after TagAndPushPP() below:
+//   +------------------+
+//   | Saved PP         | <- PP
+//   +------------------+
+//   | PC marker        | <- TOS
+//   +------------------+
+//   | Saved FP         | <- FP of stub
+//   +------------------+
+//   | return-address   |  (deoptimization point)
+//   +------------------+
+//   | Saved CODE_REG   |
+//   +------------------+
+//   | ...              | <- SP of optimized frame
+//
+// Parts of the code cannot GC, part of the code can GC.
+static void GenerateDeoptimizationSequence(Assembler* assembler,
+                                           DeoptStubKind kind) {
+  // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
+  __ EnterStubFrame();
+
+  // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
+  // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
+  const intptr_t saved_result_slot_from_fp =
+      target::frame_layout.first_local_from_fp + 1 -
+      (kNumberOfCpuRegisters - A0);
+  const intptr_t saved_exception_slot_from_fp =
+      target::frame_layout.first_local_from_fp + 1 -
+      (kNumberOfCpuRegisters - A0);
+  const intptr_t saved_stacktrace_slot_from_fp =
+      target::frame_layout.first_local_from_fp + 1 -
+      (kNumberOfCpuRegisters - A1);
+  // Result in A0 is preserved as part of pushing all registers below.
+
+  // Push registers in their enumeration order: lowest register number at
+  // lowest address.
+  __ subi(SP, SP, kNumberOfCpuRegisters * target::kWordSize);
+  for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
+    const Register r = static_cast<Register>(i);
+    if (r == CODE_REG) {
+      // Save the original value of CODE_REG pushed before invoking this stub
+      // instead of the value used to call this stub.
+      COMPILE_ASSERT(TMP > CODE_REG);  // TMP saved first
+      __ lx(TMP, Address(FP, 2 * target::kWordSize));
+      __ sx(TMP, Address(SP, i * target::kWordSize));
+    } else {
+      __ sx(r, Address(SP, i * target::kWordSize));
+    }
+  }
+
+  __ subi(SP, SP, kNumberOfFpuRegisters * kFpuRegisterSize);
+  for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; i--) {
+    FRegister freg = static_cast<FRegister>(i);
+    __ fsd(freg, Address(SP, i * kFpuRegisterSize));
+  }
+
+  __ mv(A0, SP);  // Pass address of saved registers block.
+  bool is_lazy =
+      (kind == kLazyDeoptFromReturn) || (kind == kLazyDeoptFromThrow);
+  __ li(A1, is_lazy ? 1 : 0);
+  __ ReserveAlignedFrameSpace(0);
+  __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
+  // Result (A0) is stack-size (FP - SP) in bytes.
+
+  if (kind == kLazyDeoptFromReturn) {
+    // Restore result into T1 temporarily.
+    __ LoadFromOffset(T1, FP, saved_result_slot_from_fp * target::kWordSize);
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into T1 temporarily.
+    __ LoadFromOffset(T1, FP, saved_exception_slot_from_fp * target::kWordSize);
+    __ LoadFromOffset(T2, FP,
+                      saved_stacktrace_slot_from_fp * target::kWordSize);
+  }
+
+  // There is a Dart Frame on the stack. We must restore PP and leave frame.
+  __ RestoreCodePointer();
+  __ LeaveStubFrame();
+  __ sub(SP, FP, A0);
+
+  // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
+  // is no need to set the correct PC marker or load PP, since they get patched.
+  __ EnterStubFrame();
+
+  if (kind == kLazyDeoptFromReturn) {
+    __ PushRegister(T1);  // Preserve result as first local.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ PushRegister(T1);  // Preserve exception as first local.
+    __ PushRegister(T2);  // Preserve stacktrace as second local.
+  }
+  __ ReserveAlignedFrameSpace(0);
+  __ mv(A0, FP);  // Pass last FP as parameter in R0.
+  __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
+  if (kind == kLazyDeoptFromReturn) {
+    // Restore result into T1.
+    __ LoadFromOffset(
+        T1, FP, target::frame_layout.first_local_from_fp * target::kWordSize);
+  } else if (kind == kLazyDeoptFromThrow) {
+    // Restore result into T1.
+    __ LoadFromOffset(
+        T1, FP, target::frame_layout.first_local_from_fp * target::kWordSize);
+    __ LoadFromOffset(
+        T2, FP,
+        (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.
+  __ RestoreCodePointer();
+  __ LeaveStubFrame();
+
+  // Frame is fully rewritten at this point and it is safe to perform a GC.
+  // Materialize any objects that were deferred by FillFrame because they
+  // require allocation.
+  // Enter stub frame with loading PP. The caller's PP is not materialized yet.
+  __ EnterStubFrame();
+  if (kind == kLazyDeoptFromReturn) {
+    __ PushRegister(T1);  // Preserve result, it will be GC-d here.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ PushRegister(T1);  // Preserve exception, it will be GC-d here.
+    __ PushRegister(T2);  // Preserve stacktrace, it will be GC-d here.
+  }
+
+  __ PushRegister(ZR);  // 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.
+  __ PopRegister(T2);
+  __ SmiUntag(T2);
+  if (kind == kLazyDeoptFromReturn) {
+    __ PopRegister(A0);  // Restore result.
+  } else if (kind == kLazyDeoptFromThrow) {
+    __ PopRegister(A1);  // Restore stacktrace.
+    __ PopRegister(A0);  // Restore exception.
+  }
+  __ LeaveStubFrame();
+  // Remove materialization arguments.
+  __ add(SP, SP, T2);
+  // The caller is responsible for emitting the return instruction.
+}
+
+// A0: result, must be preserved
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ LoadImmediate(TMP, kZapCodeReg);
+  __ PushRegister(TMP);
+  // Return address for "call" to deopt stub.
+  __ LoadImmediate(RA, kZapReturnAddress);
+  __ lx(CODE_REG,
+        Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
+  __ ret();
+}
+
+// A0: exception, must be preserved
+// A1: stacktrace, must be preserved
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
+  // Push zap value instead of CODE_REG for lazy deopt.
+  __ LoadImmediate(TMP, kZapCodeReg);
+  __ PushRegister(TMP);
+  // Return address for "call" to deopt stub.
+  __ LoadImmediate(RA, kZapReturnAddress);
+  __ lx(CODE_REG,
+        Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
+  GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
+  __ PushRegister(CODE_REG);
+  __ lx(CODE_REG, Address(THR, target::Thread::deoptimize_stub_offset()));
+  GenerateDeoptimizationSequence(assembler, kEagerDeopt);
+  __ ret();
+}
+
+// S5: ICData/MegamorphicCache
+static void GenerateNoSuchMethodDispatcherBody(Assembler* assembler) {
+  __ EnterStubFrame();
+
+  __ lx(S4,
+        FieldAddress(S5, target::CallSiteData::arguments_descriptor_offset()));
+
+  // Load the receiver.
+  __ LoadCompressedSmiFieldFromOffset(
+      T2, S4, target::ArgumentsDescriptor::size_offset());
+  __ slli(TMP, T2, target::kWordSizeLog2 - 1);  // T2 is Smi.
+  __ add(TMP, TMP, FP);
+  __ LoadFromOffset(A0, TMP,
+                    target::frame_layout.param_end_from_fp * target::kWordSize);
+  __ PushRegister(ZR);  // Result slot.
+  __ PushRegister(A0);  // Receiver.
+  __ PushRegister(S5);  // ICData/MegamorphicCache.
+  __ PushRegister(S4);  // Arguments descriptor.
+
+  // Adjust arguments count.
+  __ LoadCompressedSmiFieldFromOffset(
+      T3, S4, target::ArgumentsDescriptor::type_args_len_offset());
+  Label args_count_ok;
+  __ beqz(T3, &args_count_ok, Assembler::kNearJump);
+  // Include the type arguments.
+  __ addi(T2, T2, target::ToRawSmi(1));
+  __ Bind(&args_count_ok);
+
+  // T2: Smi-tagged arguments array length.
+  PushArrayOfArguments(assembler);
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromCallStubRuntimeEntry, kNumArgs);
+  __ Drop(4);
+  __ PopRegister(A0);  // Return value.
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+static void GenerateDispatcherCode(Assembler* assembler,
+                                   Label* call_target_function) {
+  __ Comment("NoSuchMethodDispatch");
+  // When lazily generated invocation dispatchers are disabled, the
+  // miss-handler may return null.
+  __ bne(T0, NULL_REG, call_target_function);
+
+  GenerateNoSuchMethodDispatcherBody(assembler);
+}
+
+// Input:
+//   S4 - arguments descriptor
+//   S5 - icdata/megamorphic_cache
+void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
+    Assembler* assembler) {
+  GenerateNoSuchMethodDispatcherBody(assembler);
+}
+
+// Called for inline allocation of arrays.
+// Input registers (preserved):
+//   RA: return address.
+//   AllocateArrayABI::kLengthReg: array length as Smi.
+//   AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
+// Output registers:
+//   AllocateArrayABI::kResultReg: newly allocated array.
+// Clobbered:
+//   T3, T4, T5
+void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+    // Compute the size to be allocated, it is based on the array length
+    // and is computed as:
+    // RoundedAllocationSize(
+    //     (array_length * kCompressedWordSize) + target::Array::header_size()).
+    // Check that length is a Smi.
+    __ BranchIfNotSmi(AllocateArrayABI::kLengthReg, &slow_case);
+
+    // Check length >= 0 && length <= kMaxNewSpaceElements
+    const intptr_t max_len =
+        target::ToRawSmi(target::Array::kMaxNewSpaceElements);
+    __ CompareImmediate(AllocateArrayABI::kLengthReg, max_len, kObjectBytes);
+    __ BranchIf(HI, &slow_case);
+
+    const intptr_t cid = kArrayCid;
+    NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid, T4, &slow_case));
+
+    // Calculate and align allocation size.
+    // Load new object start and calculate next object start.
+    // AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
+    // AllocateArrayABI::kLengthReg: array length as Smi.
+    __ lx(AllocateArrayABI::kResultReg,
+          Address(THR, target::Thread::top_offset()));
+    intptr_t fixed_size_plus_alignment_padding =
+        target::Array::header_size() +
+        target::ObjectAlignment::kObjectAlignment - 1;
+    // AllocateArrayABI::kLengthReg is Smi.
+    __ slli(T3, AllocateArrayABI::kLengthReg,
+            target::kWordSizeLog2 - kSmiTagSize);
+    __ AddImmediate(T3, fixed_size_plus_alignment_padding);
+    __ andi(T3, T3, ~(target::ObjectAlignment::kObjectAlignment - 1));
+    // AllocateArrayABI::kResultReg: potential new object start.
+    // T3: object size in bytes.
+    __ add(T4, AllocateArrayABI::kResultReg, T3);
+    // Branch if unsigned overflow.
+    __ bltu(T4, AllocateArrayABI::kResultReg, &slow_case);
+
+    // Check if the allocation fits into the remaining space.
+    // AllocateArrayABI::kResultReg: potential new object start.
+    // AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
+    // AllocateArrayABI::kLengthReg: array length as Smi.
+    // T3: array size.
+    // T4: potential next object start.
+    __ LoadFromOffset(TMP, THR, target::Thread::end_offset());
+    __ bgeu(T4, TMP, &slow_case);  // Branch if unsigned higher or equal.
+
+    // Successfully allocated the object(s), now update top to point to
+    // next object start and initialize the object.
+    // AllocateArrayABI::kResultReg: potential new object start.
+    // T3: array size.
+    // T4: potential next object start.
+    __ sx(T4, Address(THR, target::Thread::top_offset()));
+    __ addi(AllocateArrayABI::kResultReg, AllocateArrayABI::kResultReg,
+            kHeapObjectTag);
+
+    // AllocateArrayABI::kResultReg: new object start as a tagged pointer.
+    // AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
+    // AllocateArrayABI::kLengthReg: array length as Smi.
+    // R3: array size.
+    // R7: new object end address.
+
+    // Store the type argument field.
+    __ StoreCompressedIntoObjectOffsetNoBarrier(
+        AllocateArrayABI::kResultReg, target::Array::type_arguments_offset(),
+        AllocateArrayABI::kTypeArgumentsReg);
+
+    // Set the length field.
+    __ StoreCompressedIntoObjectOffsetNoBarrier(AllocateArrayABI::kResultReg,
+                                                target::Array::length_offset(),
+                                                AllocateArrayABI::kLengthReg);
+
+    // Calculate the size tag.
+    // AllocateArrayABI::kResultReg: new object start as a tagged pointer.
+    // AllocateArrayABI::kLengthReg: array length as Smi.
+    // T3: array size.
+    // T4: new object end address.
+    const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
+    __ li(T5, 0);
+    __ CompareImmediate(T3, target::UntaggedObject::kSizeTagMaxSizeTag);
+    compiler::Label zero_tag;
+    __ BranchIf(UNSIGNED_GREATER, &zero_tag);
+    __ slli(T5, T3, shift);
+    __ Bind(&zero_tag);
+
+    // Get the class index and insert it into the tags.
+    const uword tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+
+    __ OrImmediate(T5, T5, tags);
+    __ StoreFieldToOffset(T5, AllocateArrayABI::kResultReg,
+                          target::Array::tags_offset());
+
+    // Initialize all array elements to raw_null.
+    // AllocateArrayABI::kResultReg: new object start as a tagged pointer.
+    // R7: new object end address.
+    // AllocateArrayABI::kLengthReg: array length as Smi.
+    __ AddImmediate(T3, AllocateArrayABI::kResultReg,
+                    target::Array::data_offset() - kHeapObjectTag);
+    // R3: iterator which initially points to the start of the variable
+    // data area to be initialized.
+    Label loop, done;
+    __ Bind(&loop);
+    // TODO(cshapiro): StoreIntoObjectNoBarrier
+    __ bgeu(T3, T4, &done);
+    __ sx(NULL_REG, Address(T3, 0));
+    __ sx(NULL_REG, Address(T3, target::kCompressedWordSize));
+    __ AddImmediate(T3, 2 * target::kCompressedWordSize);
+    __ j(&loop);  // Loop until T3 == T4.
+    __ Bind(&done);
+
+    // Done allocating and initializing the array.
+    // AllocateArrayABI::kResultReg: new object.
+    // AllocateArrayABI::kLengthReg: array length as Smi (preserved).
+    __ ret();
+
+    // Unable to allocate the array using the fast inline code, just call
+    // into the runtime.
+    __ Bind(&slow_case);
+  }
+
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(ZR, Address(SP, 2 * target::kWordSize));  // Result slot.
+  __ sx(AllocateArrayABI::kLengthReg, Address(SP, 1 * target::kWordSize));
+  __ sx(AllocateArrayABI::kTypeArgumentsReg,
+        Address(SP, 0 * target::kWordSize));
+  __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
+  __ lx(AllocateArrayABI::kTypeArgumentsReg,
+        Address(SP, 0 * target::kWordSize));
+  __ lx(AllocateArrayABI::kLengthReg, Address(SP, 1 * target::kWordSize));
+  __ lx(AllocateArrayABI::kResultReg, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  __ LeaveStubFrame();
+
+  // Write-barrier elimination might be enabled for this array (depending on the
+  // array length). To be sure we will check if the allocated object is in old
+  // space and if so call a leaf runtime to add it to the remembered set.
+  ASSERT(AllocateArrayABI::kResultReg == A0);
+  EnsureIsNewOrRemembered(assembler);
+
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateAllocateMintSharedWithFPURegsStub(
+    Assembler* assembler) {
+  // For test purpose call allocation stub without inline allocation attempt.
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+    __ TryAllocate(compiler::MintClass(), &slow_case, Assembler::kNearJump,
+                   AllocateMintABI::kResultReg, AllocateMintABI::kTempReg);
+    __ ret();
+
+    __ Bind(&slow_case);
+  }
+  COMPILE_ASSERT(AllocateMintABI::kResultReg ==
+                 SharedSlowPathStubABI::kResultReg);
+  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
+                     &kAllocateMintRuntimeEntry,
+                     target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
+                     /*allow_return=*/true,
+                     /*store_runtime_result_in_result_register=*/true);
+}
+
+void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  // For test purpose call allocation stub without inline allocation attempt.
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+    __ TryAllocate(compiler::MintClass(), &slow_case, Assembler::kNearJump,
+                   AllocateMintABI::kResultReg, AllocateMintABI::kTempReg);
+    __ ret();
+
+    __ Bind(&slow_case);
+  }
+  COMPILE_ASSERT(AllocateMintABI::kResultReg ==
+                 SharedSlowPathStubABI::kResultReg);
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kAllocateMintRuntimeEntry,
+      target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
+      /*allow_return=*/true,
+      /*store_runtime_result_in_result_register=*/true);
+}
+
+// Called when invoking Dart code from C++ (VM code).
+// Input parameters:
+//   RA : points to return address.
+//   A0 : target code or entry point (in bare instructions mode).
+//   A1 : arguments descriptor array.
+//   A2 : arguments array.
+//   A3 : current thread.
+// Beware!  TMP == A3
+void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
+  __ Comment("InvokeDartCodeStub");
+
+  __ PushRegister(RA);  // Marker for the profiler.
+  __ EnterFrame(0);
+
+  // Push code object to PC marker slot.
+  __ lx(TMP2, Address(A3, target::Thread::invoke_dart_code_stub_offset()));
+  __ PushRegister(TMP2);
+
+#if defined(USING_SHADOW_CALL_STACK)
+#error Unimplemented
+#endif
+
+  // TODO(riscv): Consider using only volatile FPU registers in Dart code so we
+  // don't need to save the preserved FPU registers here.
+  __ PushNativeCalleeSavedRegisters();
+
+  // Set up THR, which caches the current thread in Dart code.
+  if (THR != A3) {
+    __ mv(THR, A3);
+  }
+
+  // Refresh pinned registers values (inc. write barrier mask and null object).
+  __ RestorePinnedRegisters();
+
+  // Save the current VMTag on the stack.
+  __ LoadFromOffset(TMP, THR, target::Thread::vm_tag_offset());
+  __ PushRegister(TMP);
+
+  // 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(TMP, THR, target::Thread::top_resource_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_resource_offset());
+  __ PushRegister(TMP);
+
+  __ LoadFromOffset(TMP, THR, target::Thread::exit_through_ffi_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
+  __ PushRegister(TMP);
+
+  __ LoadFromOffset(TMP, THR, target::Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+  __ PushRegister(TMP);
+  // target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
+  // with the code below.
+#if XLEN == 32
+  ASSERT_EQUAL(target::frame_layout.exit_link_slot_from_entry_fp, -40);
+#elif XLEN == 64
+  ASSERT_EQUAL(target::frame_layout.exit_link_slot_from_entry_fp, -28);
+#endif
+
+  // Mark that the thread is executing Dart code. Do this after initializing the
+  // exit link for the profiler.
+  __ LoadImmediate(TMP, VMTag::kDartTagId);
+  __ StoreToOffset(TMP, THR, target::Thread::vm_tag_offset());
+
+  // Load arguments descriptor array, which is passed to Dart code.
+  __ LoadFromOffset(ARGS_DESC_REG, A1, VMHandles::kOffsetOfRawPtrInHandle);
+
+  // Load number of arguments into T5 and adjust count for type arguments.
+  __ LoadFieldFromOffset(T5, ARGS_DESC_REG,
+                         target::ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(T3, ARGS_DESC_REG,
+                         target::ArgumentsDescriptor::type_args_len_offset());
+  __ SmiUntag(T5);
+  // Include the type arguments.
+  __ snez(T3, T3);  // T3 <- T3 == 0 ? 0 : 1
+  __ add(T5, T5, T3);
+
+  // Compute address of 'arguments array' data area into A2.
+  __ LoadFromOffset(A2, A2, VMHandles::kOffsetOfRawPtrInHandle);
+  __ AddImmediate(A2, target::Array::data_offset() - kHeapObjectTag);
+
+  // Set up arguments for the Dart call.
+  Label push_arguments;
+  Label done_push_arguments;
+  __ beqz(T5, &done_push_arguments);  // check if there are arguments.
+  __ LoadImmediate(T2, 0);
+  __ Bind(&push_arguments);
+  __ lx(T3, Address(A2, 0));
+  __ PushRegister(T3);
+  __ addi(T2, T2, 1);
+  __ addi(A2, A2, target::kWordSize);
+  __ blt(T2, T5, &push_arguments, compiler::Assembler::kNearJump);
+  __ Bind(&done_push_arguments);
+
+  if (FLAG_precompiled_mode) {
+    __ SetupGlobalPoolAndDispatchTable();
+    __ mv(CODE_REG, ZR);  // GC-safe value into CODE_REG.
+  } 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.
+    __ li(PP, 1);  // PP is untagged, callee will tag and spill PP.
+    __ lx(CODE_REG, Address(A0, VMHandles::kOffsetOfRawPtrInHandle));
+    __ lx(A0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+  }
+
+  // Call the Dart code entrypoint.
+  __ jalr(A0);  // ARGS_DESC_REG is the arguments descriptor array.
+  __ Comment("InvokeDartCodeStub return");
+
+  // Get rid of arguments pushed on the stack.
+  __ addi(
+      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.
+  __ PopRegister(TMP);
+  __ StoreToOffset(TMP, THR, target::Thread::top_exit_frame_info_offset());
+  __ PopRegister(TMP);
+  __ StoreToOffset(TMP, THR, target::Thread::exit_through_ffi_offset());
+  __ PopRegister(TMP);
+  __ StoreToOffset(TMP, THR, target::Thread::top_resource_offset());
+
+  // Restore the current VMTag from the stack.
+  __ PopRegister(TMP);
+  __ StoreToOffset(TMP, THR, target::Thread::vm_tag_offset());
+
+  __ PopNativeCalleeSavedRegisters();
+
+  // Restore the frame pointer and C stack pointer and return.
+  __ LeaveFrame();
+  __ Drop(1);
+  __ ret();
+}
+
+// Helper to generate space allocation of context stub.
+// This does not initialise the fields of the context.
+// Input:
+//   T1: number of context variables.
+// Output:
+//   A0: new allocated Context object.
+// Clobbered:
+//   T2, T3, T4, TMP
+static void GenerateAllocateContextSpaceStub(Assembler* assembler,
+                                             Label* slow_case) {
+  // First compute the rounded instance size.
+  // R1: number of context variables.
+  intptr_t fixed_size_plus_alignment_padding =
+      target::Context::header_size() +
+      target::ObjectAlignment::kObjectAlignment - 1;
+  __ slli(T2, T1, kCompressedWordSizeLog2);
+  __ AddImmediate(T2, fixed_size_plus_alignment_padding);
+  __ andi(T2, T2, ~(target::ObjectAlignment::kObjectAlignment - 1));
+
+  NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, T4, slow_case));
+  // Now allocate the object.
+  // T1: number of context variables.
+  // T2: object size.
+  __ lx(A0, Address(THR, target::Thread::top_offset()));
+  __ add(T3, T2, A0);
+  // Check if the allocation fits into the remaining space.
+  // A0: potential new object.
+  // T1: number of context variables.
+  // T2: object size.
+  // T3: potential next object start.
+  __ lx(TMP, Address(THR, target::Thread::end_offset()));
+  __ CompareRegisters(T3, TMP);
+  __ BranchIf(CS, slow_case);  // Branch if unsigned higher or equal.
+
+  // Successfully allocated the object, now update top to point to
+  // next object start and initialize the object.
+  // A0: new object.
+  // T1: number of context variables.
+  // T2: object size.
+  // T3: next object start.
+  __ sx(T3, Address(THR, target::Thread::top_offset()));
+  __ addi(A0, A0, kHeapObjectTag);
+
+  // Calculate the size tag.
+  // A0: new object.
+  // T1: number of context variables.
+  // T2: object size.
+  const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
+                         target::ObjectAlignment::kObjectAlignmentLog2;
+  __ li(T3, 0);
+  __ CompareImmediate(T2, target::UntaggedObject::kSizeTagMaxSizeTag);
+  // If no size tag overflow, shift R2 left, else set R2 to zero.
+  compiler::Label zero_tag;
+  __ BranchIf(HI, &zero_tag);
+  __ slli(T3, T2, shift);
+  __ Bind(&zero_tag);
+
+  // Get the class index and insert it into the tags.
+  // T3: size and bit tags.
+  const uword tags =
+      target::MakeTagWordForNewSpaceObject(kContextCid, /*instance_size=*/0);
+
+  __ OrImmediate(T3, T3, tags);
+  __ StoreFieldToOffset(T3, A0, target::Object::tags_offset());
+
+  // Setup up number of context variables field.
+  // A0: new object.
+  // T1: number of context variables as integer value (not object).
+  __ StoreFieldToOffset(T1, A0, target::Context::num_variables_offset(),
+                        kFourBytes);
+}
+
+// Called for inline allocation of contexts.
+// Input:
+//   T1: number of context variables.
+// Output:
+//   A0: new allocated Context object.
+void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+
+    GenerateAllocateContextSpaceStub(assembler, &slow_case);
+
+    // Setup the parent field.
+    // A0: new object.
+    // T1: number of context variables.
+    __ StoreCompressedIntoObjectOffset(A0, target::Context::parent_offset(),
+                                       NULL_REG);
+
+    // Initialize the context variables.
+    // A0: new object.
+    // T1: number of context variables.
+    {
+      Label loop, done;
+      __ AddImmediate(T3, A0,
+                      target::Context::variable_offset(0) - kHeapObjectTag);
+      __ Bind(&loop);
+      __ subi(T1, T1, 1);
+      __ bltz(T1, &done);
+      __ sx(NULL_REG, Address(T3, 0));
+      __ addi(T3, T3, target::kCompressedWordSize);
+      __ j(&loop);
+      __ Bind(&done);
+    }
+
+    // Done allocating and initializing the context.
+    // A0: new object.
+    __ ret();
+
+    __ Bind(&slow_case);
+  }
+
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+  // Setup space on stack for return value.
+  __ SmiTag(T1);
+  __ PushObject(NullObject());
+  __ PushRegister(T1);
+  __ CallRuntime(kAllocateContextRuntimeEntry, 1);  // Allocate context.
+  __ Drop(1);          // Pop number of context variables argument.
+  __ PopRegister(A0);  // Pop the new context object.
+
+  // Write-barrier elimination might be enabled for this context (depending on
+  // the size). To be sure we will check if the allocated object is in old
+  // space and if so call a leaf runtime to add it to the remembered set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+
+  // A0: new object
+  // Restore the frame pointer.
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+// Called for clone of contexts.
+// Input:
+//   T5: context variable to clone.
+// Output:
+//   A0: new allocated Context object.
+void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label slow_case;
+
+    // Load num. variable (int32) in the existing context.
+    __ lw(T1, FieldAddress(T5, target::Context::num_variables_offset()));
+
+    GenerateAllocateContextSpaceStub(assembler, &slow_case);
+
+    // Load parent in the existing context.
+    __ LoadCompressed(T3, FieldAddress(T5, target::Context::parent_offset()));
+    // Setup the parent field.
+    // A0: new context.
+    __ StoreCompressedIntoObjectNoBarrier(
+        A0, FieldAddress(A0, target::Context::parent_offset()), T3);
+
+    // Clone the context variables.
+    // A0: new context.
+    // T1: number of context variables.
+    {
+      Label loop, done;
+      // T3: Variable array address, new context.
+      __ AddImmediate(T3, A0,
+                      target::Context::variable_offset(0) - kHeapObjectTag);
+      // T4: Variable array address, old context.
+      __ AddImmediate(T4, T5,
+                      target::Context::variable_offset(0) - kHeapObjectTag);
+
+      __ Bind(&loop);
+      __ subi(T1, T1, 1);
+      __ bltz(T1, &done);
+      __ lx(T5, Address(T4, 0));
+      __ addi(T4, T4, target::kCompressedWordSize);
+      __ sx(T5, Address(T3, 0));
+      __ addi(T3, T3, target::kCompressedWordSize);
+      __ j(&loop);
+
+      __ Bind(&done);
+    }
+
+    // Done allocating and initializing the context.
+    // A0: new object.
+    __ ret();
+
+    __ Bind(&slow_case);
+  }
+
+  __ EnterStubFrame();
+
+  __ subi(SP, SP, 2 * target::kWordSize);
+  __ sx(NULL_REG, Address(SP, 1 * target::kWordSize));  // Result slot.
+  __ sx(T5, Address(SP, 0 * target::kWordSize));        // Context argument.
+  __ CallRuntime(kCloneContextRuntimeEntry, 1);
+  __ lx(A0, Address(SP, 1 * target::kWordSize));  // Context result.
+  __ subi(SP, SP, 2 * target::kWordSize);
+
+  // Write-barrier elimination might be enabled for this context (depending on
+  // the size). To be sure we will check if the allocated object is in old
+  // space and if so call a leaf runtime to add it to the remembered set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+
+  // A0: new object
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
+
+    Register reg = static_cast<Register>(i);
+    intptr_t start = __ CodeSize();
+    __ addi(SP, SP, -3 * target::kWordSize);
+    __ sx(RA, Address(SP, 2 * target::kWordSize));
+    __ sx(TMP, Address(SP, 1 * target::kWordSize));
+    __ sx(kWriteBarrierObjectReg, Address(SP, 0 * target::kWordSize));
+    __ mv(kWriteBarrierObjectReg, reg);
+    __ Call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
+    __ lx(kWriteBarrierObjectReg, Address(SP, 0 * target::kWordSize));
+    __ lx(TMP, Address(SP, 1 * target::kWordSize));
+    __ lx(RA, Address(SP, 2 * target::kWordSize));
+    __ addi(SP, SP, 3 * target::kWordSize);
+    __ jr(TMP);  // Return.
+    intptr_t end = __ CodeSize();
+    ASSERT_EQUAL(end - start, kStoreBufferWrapperSize);
+  }
+}
+
+// Helper stub to implement Assembler::StoreIntoObject/Array.
+// Input parameters:
+//   A0: Object (old)
+//   A1: Value (old or new)
+//   A6: Slot
+// If A1 is new, add A0 to the store buffer. Otherwise A1 is old, mark A1
+// and add it to the mark list.
+COMPILE_ASSERT(kWriteBarrierObjectReg == A0);
+COMPILE_ASSERT(kWriteBarrierValueReg == A1);
+COMPILE_ASSERT(kWriteBarrierSlotReg == A6);
+static void GenerateWriteBarrierStubHelper(Assembler* assembler,
+                                           Address stub_code,
+                                           bool cards) {
+  Label add_to_mark_stack, remember_card, lost_race;
+  __ andi(TMP2, A1, 1 << target::ObjectAlignment::kNewObjectBitPosition);
+  __ beqz(TMP2, &add_to_mark_stack);
+
+  if (cards) {
+    __ lbu(TMP2, FieldAddress(A0, target::Object::tags_offset()));
+    __ andi(TMP2, TMP2, 1 << target::UntaggedObject::kCardRememberedBit);
+    __ bnez(TMP2, &remember_card);
+  } else {
+#if defined(DEBUG)
+    Label ok;
+    __ lbu(TMP2, FieldAddress(A0, target::Object::tags_offset()));
+    __ andi(TMP2, TMP2, 1 << target::UntaggedObject::kCardRememberedBit);
+    __ beqz(TMP2, &ok, Assembler::kNearJump);
+    __ Stop("Wrong barrier!");
+    __ Bind(&ok);
+#endif
+  }
+
+  // Spill T2, T3, T4.
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(T2, Address(SP, 2 * target::kWordSize));
+  __ sx(T3, Address(SP, 1 * target::kWordSize));
+  __ sx(T4, Address(SP, 0 * target::kWordSize));
+
+  // Atomically clear kOldAndNotRememberedBit.
+  // TODO(riscv): Use amoand instead of lr/sc.
+  ASSERT(target::Object::tags_offset() == 0);
+  __ subi(T3, A0, kHeapObjectTag);
+  // T3: Untagged address of header word (lr/sc do not support offsets).
+  Label retry;
+  __ Bind(&retry);
+  __ lr(T2, Address(T3, 0));
+  __ andi(TMP2, T2, 1 << target::UntaggedObject::kOldAndNotRememberedBit);
+  __ beqz(TMP2, &lost_race);
+  __ andi(T2, T2, ~(1 << target::UntaggedObject::kOldAndNotRememberedBit));
+  __ sc(T4, T2, Address(T3, 0));
+  __ bnez(T4, &retry);
+
+  // Load the StoreBuffer block out of the thread. Then load top_ out of the
+  // StoreBufferBlock and add the address to the pointers_.
+  __ LoadFromOffset(T4, THR, target::Thread::store_buffer_block_offset());
+  __ LoadFromOffset(T2, T4, target::StoreBufferBlock::top_offset(),
+                    kUnsignedFourBytes);
+  __ slli(T3, T2, target::kWordSizeLog2);
+  __ add(T3, T4, T3);
+  __ StoreToOffset(A0, T3, target::StoreBufferBlock::pointers_offset());
+
+  // Increment top_ and check for overflow.
+  // T2: top_.
+  // T4: StoreBufferBlock.
+  Label overflow;
+  __ addi(T2, T2, 1);
+  __ StoreToOffset(T2, T4, target::StoreBufferBlock::top_offset(),
+                   kUnsignedFourBytes);
+  __ CompareImmediate(T2, target::StoreBufferBlock::kSize);
+  // Restore values.
+  __ BranchIf(EQ, &overflow);
+
+  // Restore T2, T3, T4.
+  __ lx(T4, Address(SP, 0 * target::kWordSize));
+  __ lx(T3, Address(SP, 1 * target::kWordSize));
+  __ lx(T2, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  __ ret();
+
+  // Handle overflow: Call the runtime leaf function.
+  __ Bind(&overflow);
+  // Restore T2, T3, T4.
+  __ lx(T4, Address(SP, 0 * target::kWordSize));
+  __ lx(T3, Address(SP, 1 * target::kWordSize));
+  __ lx(T2, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  {
+    Assembler::CallRuntimeScope scope(assembler,
+                                      kStoreBufferBlockProcessRuntimeEntry,
+                                      /*frame_size=*/0, stub_code);
+    __ mv(A0, THR);
+    scope.Call(/*argument_count=*/1);
+  }
+  __ ret();
+
+  __ Bind(&add_to_mark_stack);
+  // Spill T2, T3, T4.
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(T2, Address(SP, 2 * target::kWordSize));
+  __ sx(T3, Address(SP, 1 * target::kWordSize));
+  __ sx(T4, Address(SP, 0 * target::kWordSize));
+
+  // Atomically clear kOldAndNotMarkedBit.
+  // TODO(riscv): Use amoand instead of lr/sc.
+  Label marking_retry, marking_overflow;
+  ASSERT(target::Object::tags_offset() == 0);
+  __ subi(T3, A1, kHeapObjectTag);
+  // T3: Untagged address of header word (lr/sc do not support offsets).
+  __ Bind(&marking_retry);
+  __ lr(T2, Address(T3, 0));
+  __ andi(TMP2, T2, 1 << target::UntaggedObject::kOldAndNotMarkedBit);
+  __ beqz(TMP2, &lost_race);
+  __ andi(T2, T2, ~(1 << target::UntaggedObject::kOldAndNotMarkedBit));
+  __ sc(T4, T2, Address(T3, 0));
+  __ bnez(T4, &marking_retry);
+
+  __ LoadFromOffset(T4, THR, target::Thread::marking_stack_block_offset());
+  __ LoadFromOffset(T2, T4, target::MarkingStackBlock::top_offset(),
+                    kUnsignedFourBytes);
+  __ slli(T3, T2, target::kWordSizeLog2);
+  __ add(T3, T4, T3);
+  __ StoreToOffset(A1, T3, target::MarkingStackBlock::pointers_offset());
+  __ addi(T2, T2, 1);
+  __ StoreToOffset(T2, T4, target::MarkingStackBlock::top_offset(),
+                   kUnsignedFourBytes);
+  __ CompareImmediate(T2, target::MarkingStackBlock::kSize);
+  __ BranchIf(EQ, &marking_overflow);
+  // Restore T2, T3, T4.
+  __ lx(T4, Address(SP, 0 * target::kWordSize));
+  __ lx(T3, Address(SP, 1 * target::kWordSize));
+  __ lx(T2, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  __ ret();
+
+  __ Bind(&marking_overflow);
+  // Restore T2, T3, T4.
+  __ lx(T4, Address(SP, 0 * target::kWordSize));
+  __ lx(T3, Address(SP, 1 * target::kWordSize));
+  __ lx(T2, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  {
+    Assembler::CallRuntimeScope scope(assembler,
+                                      kMarkingStackBlockProcessRuntimeEntry,
+                                      /*frame_size=*/0, stub_code);
+    __ mv(A0, THR);
+    scope.Call(/*argument_count=*/1);
+  }
+  __ ret();
+
+  __ Bind(&lost_race);
+  // Restore T2, T3, T4.
+  __ lx(T4, Address(SP, 0 * target::kWordSize));
+  __ lx(T3, Address(SP, 1 * target::kWordSize));
+  __ lx(T2, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+  __ ret();
+
+  if (cards) {
+    Label remember_card_slow;
+
+    // Get card table.
+    __ Bind(&remember_card);
+    __ AndImmediate(TMP, A0, target::kOldPageMask);  // OldPage.
+    __ lx(TMP,
+          Address(TMP, target::OldPage::card_table_offset()));  // Card table.
+    __ beqz(TMP, &remember_card_slow);
+
+    // Dirty the card.
+    __ AndImmediate(TMP, A0, target::kOldPageMask);  // OldPage.
+    __ sub(A6, A6, TMP);                             // Offset in page.
+    __ lx(TMP,
+          Address(TMP, target::OldPage::card_table_offset()));  // Card table.
+    __ srli(A6, A6, target::OldPage::kBytesPerCardLog2);
+    __ add(TMP, TMP, A6);        // Card address.
+    __ sb(A0, Address(TMP, 0));  // Low byte of A0 is non-zero from object tag.
+    __ ret();
+
+    // Card table not yet allocated.
+    __ Bind(&remember_card_slow);
+    {
+      Assembler::CallRuntimeScope scope(assembler, kRememberCardRuntimeEntry,
+                                        /*frame_size=*/0, stub_code);
+      __ mv(A0, A0);  // Arg0 = Object
+      __ mv(A1, A6);  // Arg1 = Slot
+      scope.Call(/*argument_count=*/2);
+    }
+    __ ret();
+  }
+}
+
+void StubCodeCompiler::GenerateWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler, Address(THR, target::Thread::write_barrier_code_offset()),
+      false);
+}
+
+void StubCodeCompiler::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+  GenerateWriteBarrierStubHelper(
+      assembler,
+      Address(THR, target::Thread::array_write_barrier_code_offset()), true);
+}
+
+static void GenerateAllocateObjectHelper(Assembler* assembler,
+                                         bool is_cls_parameterized) {
+  const Register kTagsReg = T2;
+
+  {
+    Label slow_case;
+
+    const Register kNewTopReg = T3;
+
+    // Bump allocation.
+    {
+      const Register kInstanceSizeReg = T4;
+      const Register kEndReg = T5;
+
+      __ ExtractInstanceSizeFromTags(kInstanceSizeReg, kTagsReg);
+
+      // Load two words from Thread::top: top and end.
+      // AllocateObjectABI::kResultReg: potential next object start.
+      __ lx(AllocateObjectABI::kResultReg,
+            Address(THR, target::Thread::top_offset()));
+      __ lx(kEndReg, Address(THR, target::Thread::end_offset()));
+
+      __ add(kNewTopReg, AllocateObjectABI::kResultReg, kInstanceSizeReg);
+
+      __ CompareRegisters(kEndReg, kNewTopReg);
+      __ BranchIf(UNSIGNED_LESS_EQUAL, &slow_case);
+
+      // Successfully allocated the object, now update top to point to
+      // next object start and store the class in the class field of object.
+      __ sx(kNewTopReg, Address(THR, target::Thread::top_offset()));
+    }  // kInstanceSizeReg = R4, kEndReg = R5
+
+    // Tags.
+    __ sx(kTagsReg, Address(AllocateObjectABI::kResultReg,
+                            target::Object::tags_offset()));
+
+    // Initialize the remaining words of the object.
+    {
+      const Register kFieldReg = T4;
+
+      __ AddImmediate(kFieldReg, AllocateObjectABI::kResultReg,
+                      target::Instance::first_field_offset());
+      Label done, init_loop;
+      __ Bind(&init_loop);
+      __ CompareRegisters(kFieldReg, kNewTopReg);
+      __ BranchIf(UNSIGNED_GREATER_EQUAL, &done);
+      __ sx(NULL_REG, Address(kFieldReg, 0));
+      __ addi(kFieldReg, kFieldReg, target::kCompressedWordSize);
+      __ j(&init_loop);
+
+      __ Bind(&done);
+    }  // kFieldReg = T4
+
+    if (is_cls_parameterized) {
+      Label not_parameterized_case;
+
+      const Register kClsIdReg = T4;
+      const Register kTypeOffsetReg = T5;
+
+      __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
+
+      // Load class' type_arguments_field offset in words.
+      __ LoadClassById(kTypeOffsetReg, kClsIdReg);
+      __ lw(
+          kTypeOffsetReg,
+          FieldAddress(kTypeOffsetReg,
+                       target::Class::
+                           host_type_arguments_field_offset_in_words_offset()));
+
+      // Set the type arguments in the new object.
+      __ slli(kTypeOffsetReg, kTypeOffsetReg, target::kWordSizeLog2);
+      __ add(kTypeOffsetReg, kTypeOffsetReg, AllocateObjectABI::kResultReg);
+      __ sx(AllocateObjectABI::kTypeArgumentsReg, Address(kTypeOffsetReg, 0));
+
+      __ Bind(&not_parameterized_case);
+    }  // kClsIdReg = R4, kTypeOffestReg = R5
+
+    __ AddImmediate(AllocateObjectABI::kResultReg,
+                    AllocateObjectABI::kResultReg, kHeapObjectTag);
+
+    __ ret();
+
+    __ Bind(&slow_case);
+  }  // kNewTopReg = R3
+
+  // Fall back on slow case:
+  if (!is_cls_parameterized) {
+    __ mv(AllocateObjectABI::kTypeArgumentsReg, NULL_REG);
+  }
+  // Tail call to generic allocation stub.
+  __ lx(
+      TMP,
+      Address(THR, target::Thread::allocate_object_slow_entry_point_offset()));
+  __ jr(TMP);
+}
+
+// Called for inline allocation of objects (any class).
+void StubCodeCompiler::GenerateAllocateObjectStub(Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/false);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectParameterizedStub(
+    Assembler* assembler) {
+  GenerateAllocateObjectHelper(assembler, /*is_cls_parameterized=*/true);
+}
+
+void StubCodeCompiler::GenerateAllocateObjectSlowStub(Assembler* assembler) {
+  const Register kTagsToClsIdReg = T2;
+
+  if (!FLAG_precompiled_mode) {
+    __ lx(CODE_REG,
+          Address(THR, target::Thread::call_to_runtime_stub_offset()));
+  }
+
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+
+  __ ExtractClassIdFromTags(kTagsToClsIdReg, kTagsToClsIdReg);
+  __ LoadClassById(A0, kTagsToClsIdReg);
+
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(ZR, Address(SP, 2 * target::kWordSize));  // Result slot.
+  __ sx(A0, Address(SP, 1 * target::kWordSize));  // Arg0: Class object.
+  __ sx(AllocateObjectABI::kTypeArgumentsReg,
+        Address(SP, 0 * target::kWordSize));  // Arg1: Type args or null.
+  __ CallRuntime(kAllocateObjectRuntimeEntry, 2);
+  __ lx(AllocateObjectABI::kResultReg, Address(SP, 2 * target::kWordSize));
+  __ addi(SP, SP, 3 * target::kWordSize);
+
+  // Write-barrier elimination is enabled for [cls] and we therefore need to
+  // ensure that the object is in new-space or has remembered bit set.
+  EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
+
+  __ LeaveStubFrame();
+
+  __ ret();
+}
+
+// Called for inline allocation of objects.
+void StubCodeCompiler::GenerateAllocationStubForClass(
+    Assembler* assembler,
+    UnresolvedPcRelativeCalls* unresolved_calls,
+    const Class& cls,
+    const Code& allocate_object,
+    const Code& allocat_object_parametrized) {
+  classid_t cls_id = target::Class::GetId(cls);
+  ASSERT(cls_id != kIllegalCid);
+
+  RELEASE_ASSERT(AllocateObjectInstr::WillAllocateNewOrRemembered(cls));
+
+  // The generated code is different if the class is parameterized.
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
+                                      cls) != target::Class::kNoTypeArguments);
+
+  const intptr_t instance_size = target::Class::GetInstanceSize(cls);
+  ASSERT(instance_size > 0);
+  RELEASE_ASSERT(target::Heap::IsAllocatableInNewSpace(instance_size));
+
+  const uword tags =
+      target::MakeTagWordForNewSpaceObject(cls_id, instance_size);
+
+  // Note: Keep in sync with helper function.
+  const Register kTagsReg = T2;
+  ASSERT(kTagsReg != AllocateObjectABI::kTypeArgumentsReg);
+
+  __ LoadImmediate(kTagsReg, tags);
+
+  if (!FLAG_use_slow_path && FLAG_inline_alloc &&
+      !target::Class::TraceAllocation(cls) &&
+      target::SizeFitsInSizeTag(instance_size)) {
+    if (is_cls_parameterized) {
+      // TODO(41974): Assign all allocation stubs to the root loading unit?
+      if (false &&
+          !IsSameObject(NullObject(),
+                        CastHandle<Object>(allocat_object_parametrized))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocat_object_parametrized, /*is_tail_call=*/true));
+      } else {
+        __ lx(TMP,
+              Address(THR,
+                      target::Thread::
+                          allocate_object_parameterized_entry_point_offset()));
+        __ jr(TMP);
+      }
+    } else {
+      // TODO(41974): Assign all allocation stubs to the root loading unit?
+      if (false &&
+          !IsSameObject(NullObject(), CastHandle<Object>(allocate_object))) {
+        __ GenerateUnRelocatedPcRelativeTailCall();
+        unresolved_calls->Add(new UnresolvedPcRelativeCall(
+            __ CodeSize(), allocate_object, /*is_tail_call=*/true));
+      } else {
+        __ lx(
+            TMP,
+            Address(THR, target::Thread::allocate_object_entry_point_offset()));
+        __ jr(TMP);
+      }
+    }
+  } else {
+    if (!is_cls_parameterized) {
+      __ LoadObject(AllocateObjectABI::kTypeArgumentsReg, NullObject());
+    }
+    __ lx(TMP,
+          Address(THR,
+                  target::Thread::allocate_object_slow_entry_point_offset()));
+    __ jr(TMP);
+  }
+}
+
+// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
+// from the entry code of a dart function after an error in passed argument
+// name or number is detected.
+// Input parameters:
+//  RA : return address.
+//  SP : address of last argument.
+//  S4: arguments descriptor array.
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
+  __ EnterStubFrame();
+
+  // Load the receiver.
+  __ LoadCompressedSmiFieldFromOffset(
+      T2, S4, target::ArgumentsDescriptor::size_offset());
+  __ slli(TMP, T2, target::kWordSizeLog2 - 1);  // T2 is Smi
+  __ add(TMP, TMP, FP);
+  __ LoadFromOffset(A0, TMP,
+                    target::frame_layout.param_end_from_fp * target::kWordSize);
+
+  // Load the function.
+  __ LoadCompressedFieldFromOffset(TMP, A0, target::Closure::function_offset());
+
+  __ PushRegister(ZR);   // Result slot.
+  __ PushRegister(A0);   // Receiver.
+  __ PushRegister(TMP);  // Function
+  __ PushRegister(S4);   // Arguments descriptor.
+
+  // Adjust arguments count.
+  __ LoadCompressedSmiFieldFromOffset(
+      T3, S4, target::ArgumentsDescriptor::type_args_len_offset());
+  Label args_count_ok;
+  __ beqz(T3, &args_count_ok, Assembler::kNearJump);
+  // Include the type arguments.
+  __ addi(T2, T2, target::ToRawSmi(1));
+  __ Bind(&args_count_ok);
+
+  // T2: Smi-tagged arguments array length.
+  PushArrayOfArguments(assembler);
+
+  const intptr_t kNumArgs = 4;
+  __ CallRuntime(kNoSuchMethodFromPrologueRuntimeEntry, kNumArgs);
+  // noSuchMethod on closures always throws an error, so it will never return.
+  __ ebreak();
+}
+
+//  A6: function object.
+//  S5: inline cache data object.
+// Cannot use function object from ICData as it may be the inlined
+// function and not the top-scope function.
+void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
+    Assembler* assembler) {
+  if (FLAG_precompiled_mode) {
+    __ Breakpoint();
+    return;
+  }
+  if (FLAG_trace_optimized_ic_calls) {
+    __ Stop("Unimplemented");
+  }
+  __ LoadFieldFromOffset(TMP, A6, target::Function::usage_counter_offset(),
+                         kFourBytes);
+  __ addi(TMP, TMP, 1);
+  __ StoreFieldToOffset(TMP, A6, target::Function::usage_counter_offset(),
+                        kFourBytes);
+}
+
+// Loads function into 'func_reg'.
+void StubCodeCompiler::GenerateUsageCounterIncrement(Assembler* assembler,
+                                                     Register func_reg) {
+  if (FLAG_precompiled_mode) {
+    __ trap();
+    return;
+  }
+  if (FLAG_optimization_counter_threshold >= 0) {
+    __ Comment("Increment function counter");
+    __ LoadFieldFromOffset(func_reg, IC_DATA_REG,
+                           target::ICData::owner_offset());
+    __ LoadFieldFromOffset(
+        A1, func_reg, target::Function::usage_counter_offset(), kFourBytes);
+    __ AddImmediate(A1, 1);
+    __ StoreFieldToOffset(A1, func_reg,
+                          target::Function::usage_counter_offset(), kFourBytes);
+  }
+}
+
+// Note: S5 must be preserved.
+// Attempt a quick Smi operation for known operations ('kind'). The ICData
+// must have been primed with a Smi/Smi check that will be used for counting
+// the invocations.
+static void EmitFastSmiOp(Assembler* assembler,
+                          Token::Kind kind,
+                          intptr_t num_args,
+                          Label* not_smi_or_overflow) {
+  __ Comment("Fast Smi op");
+  __ lx(A0, Address(SP, +1 * target::kWordSize));  // Left.
+  __ lx(A1, Address(SP, +0 * target::kWordSize));  // Right.
+  __ or_(TMP2, A0, A1);
+  __ andi(TMP2, TMP2, kSmiTagMask);
+  __ bnez(TMP2, not_smi_or_overflow);
+  switch (kind) {
+    case Token::kADD: {
+      __ AddBranchOverflow(A0, A0, A1, not_smi_or_overflow);
+      break;
+    }
+    case Token::kLT: {
+      // TODO(riscv): Bit tricks with stl and NULL_REG.
+      Label load_true, done;
+      __ blt(A0, A1, &load_true, compiler::Assembler::kNearJump);
+      __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+      __ j(&done, Assembler::kNearJump);
+      __ Bind(&load_true);
+      __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+      __ Bind(&done);
+      break;
+    }
+    case Token::kEQ: {
+      // TODO(riscv): Bit tricks with stl and NULL_REG.
+      Label load_true, done;
+      __ beq(A0, A1, &load_true, Assembler::kNearJump);
+      __ LoadObject(A0, CastHandle<Object>(FalseObject()));
+      __ j(&done, Assembler::kNearJump);
+      __ Bind(&load_true);
+      __ LoadObject(A0, CastHandle<Object>(TrueObject()));
+      __ Bind(&done);
+      break;
+    }
+    default:
+      UNIMPLEMENTED();
+  }
+
+  // S5: IC data object (preserved).
+  __ LoadFieldFromOffset(A6, IC_DATA_REG, target::ICData::entries_offset());
+  // R6: ic_data_array with check entries: classes and target functions.
+  __ AddImmediate(A6, 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 = target::ToRawSmi(kSmiCid);
+  __ LoadCompressedSmiFromOffset(TMP, A6, 0);
+  __ CompareImmediate(TMP, imm_smi_cid);
+  __ BranchIf(NE, &error);
+  __ LoadCompressedSmiFromOffset(TMP, A6, target::kCompressedWordSize);
+  __ CompareImmediate(TMP, imm_smi_cid);
+  __ BranchIf(EQ, &ok);
+  __ Bind(&error);
+  __ Stop("Incorrect IC data");
+  __ Bind(&ok);
+#endif
+  if (FLAG_optimization_counter_threshold >= 0) {
+    const intptr_t count_offset =
+        target::ICData::CountIndexFor(num_args) * target::kCompressedWordSize;
+    // Update counter, ignore overflow.
+    __ LoadCompressedSmiFromOffset(A1, A6, count_offset);
+    __ addi(A1, A1, target::ToRawSmi(1));
+    __ StoreToOffset(A1, A6, count_offset);
+  }
+
+  __ ret();
+}
+
+// Saves the offset of the target entry-point (from the Function) into T6.
+//
+// Must be the first code generated, since any code before will be skipped in
+// the unchecked entry-point.
+static void GenerateRecordEntryPoint(Assembler* assembler) {
+  Label done;
+  __ LoadImmediate(T6, target::Function::entry_point_offset() - kHeapObjectTag);
+  __ j(&done, Assembler::kNearJump);
+  __ BindUncheckedEntryPoint();
+  __ LoadImmediate(
+      T6, target::Function::entry_point_offset(CodeEntryKind::kUnchecked) -
+              kHeapObjectTag);
+  __ Bind(&done);
+}
+
+// Generate inline cache check for 'num_args'.
+//  A0: receiver (if instance call)
+//  S5: ICData
+//  RA: return address
+// Control flow:
+// - If receiver is null -> jump to IC miss.
+// - If receiver is Smi -> load Smi class.
+// - If receiver is not-Smi -> load receiver's class.
+// - Check if 'num_args' (including receiver) match any IC data group.
+// - Match found -> jump to target.
+// - Match not found -> jump to IC miss.
+void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
+    Assembler* assembler,
+    intptr_t num_args,
+    const RuntimeEntry& handle_ic_miss,
+    Token::Kind kind,
+    Optimized optimized,
+    CallType type,
+    Exactness exactness) {
+  const bool save_entry_point = kind == Token::kILLEGAL;
+  if (FLAG_precompiled_mode) {
+    __ Breakpoint();
+    return;
+  }
+
+  if (save_entry_point) {
+    GenerateRecordEntryPoint(assembler);
+    // T6: untagged entry point offset
+  }
+
+  if (optimized == kOptimized) {
+    GenerateOptimizedUsageCounterIncrement(assembler);
+  } else {
+    GenerateUsageCounterIncrement(assembler, /*scratch=*/T0);
+  }
+
+  ASSERT(exactness == kIgnoreExactness);  // Unimplemented.
+  ASSERT(num_args == 1 || num_args == 2);
+#if defined(DEBUG)
+  {
+    Label ok;
+    // Check that the IC data array has NumArgsTested() == num_args.
+    // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
+    __ LoadFromOffset(TMP, IC_DATA_REG,
+                      target::ICData::state_bits_offset() - kHeapObjectTag,
+                      kUnsignedFourBytes);
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andi(TMP, TMP, target::ICData::NumArgsTestedMask());
+    __ CompareImmediate(TMP2, num_args);
+    __ BranchIf(EQ, &ok, Assembler::kNearJump);
+    __ Stop("Incorrect stub for IC data");
+    __ Bind(&ok);
+  }
+#endif  // DEBUG
+
+#if !defined(PRODUCT)
+  Label stepping, done_stepping;
+  if (optimized == kUnoptimized) {
+    __ Comment("Check single stepping");
+    __ LoadIsolate(TMP);
+    __ LoadFromOffset(TMP, TMP, target::Isolate::single_step_offset(),
+                      kUnsignedByte);
+    __ bnez(TMP, &stepping);
+    __ Bind(&done_stepping);
+  }
+#endif
+
+  Label not_smi_or_overflow;
+  if (kind != Token::kILLEGAL) {
+    EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
+  }
+  __ Bind(&not_smi_or_overflow);
+
+  __ Comment("Extract ICData initial values and receiver cid");
+  // S5: IC data object (preserved).
+  __ LoadFieldFromOffset(A1, IC_DATA_REG, target::ICData::entries_offset());
+  // A1: ic_data_array with check entries: classes and target functions.
+  __ AddImmediate(A1, target::Array::data_offset() - kHeapObjectTag);
+  // A1: points directly to the first ic data array element.
+
+  if (type == kInstanceCall) {
+    __ LoadTaggedClassIdMayBeSmi(T1, A0);
+    __ LoadFieldFromOffset(ARGS_DESC_REG, IC_DATA_REG,
+                           target::CallSiteData::arguments_descriptor_offset());
+    if (num_args == 2) {
+      __ LoadCompressedSmiFieldFromOffset(
+          A7, ARGS_DESC_REG, target::ArgumentsDescriptor::count_offset());
+      __ slli(A7, A7, target::kWordSizeLog2 - kSmiTagSize);
+      __ add(A7, SP, A7);
+      __ lx(A6, Address(A7, -2 * target::kWordSize));
+      __ LoadTaggedClassIdMayBeSmi(T2, A6);
+    }
+  } else {
+    __ LoadFieldFromOffset(ARGS_DESC_REG, IC_DATA_REG,
+                           target::CallSiteData::arguments_descriptor_offset());
+    __ LoadCompressedSmiFieldFromOffset(
+        A7, ARGS_DESC_REG, target::ArgumentsDescriptor::count_offset());
+    __ slli(A7, A7, target::kWordSizeLog2 - kSmiTagSize);
+    __ add(A7, A7, SP);
+    __ lx(A6, Address(A7, -1 * target::kWordSize));
+    __ LoadTaggedClassIdMayBeSmi(T1, A6);
+    if (num_args == 2) {
+      __ lx(A6, Address(A7, -2 * target::kWordSize));
+      __ LoadTaggedClassIdMayBeSmi(T2, A6);
+    }
+  }
+  // T1: first argument class ID as Smi.
+  // T2: second argument class ID as Smi.
+  // S4: args descriptor
+
+  // We unroll the generic one that is generated once more than the others.
+  const bool optimize = kind == Token::kILLEGAL;
+
+  // Loop that checks if there is an IC data match.
+  Label loop, found, miss;
+  __ Comment("ICData loop");
+
+  __ Bind(&loop);
+  for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
+    Label update;
+
+    __ LoadCompressedSmiFromOffset(A7, A1, 0);
+    if (num_args == 1) {
+      __ beq(A7, T1, &found);  // Class id match?
+    } else {
+      __ bne(A7, T1, &update);  // Continue.
+      __ LoadCompressedSmiFromOffset(A7, A1, target::kCompressedWordSize);
+      __ beq(A7, T2, &found);  // Class id match?
+    }
+    __ Bind(&update);
+
+    const intptr_t entry_size = target::ICData::TestEntryLengthFor(
+                                    num_args, exactness == kCheckExactness) *
+                                target::kCompressedWordSize;
+    __ AddImmediate(A1, entry_size);  // Next entry.
+
+    __ CompareImmediate(A7, target::ToRawSmi(kIllegalCid));  // Done?
+    if (unroll == 0) {
+      __ BranchIf(NE, &loop);
+    } else {
+      __ BranchIf(EQ, &miss);
+    }
+  }
+
+  __ Bind(&miss);
+  __ Comment("IC miss");
+
+  // Compute address of arguments.
+  __ LoadCompressedSmiFieldFromOffset(
+      A7, ARGS_DESC_REG, target::ArgumentsDescriptor::count_offset());
+  __ slli(A7, A7, target::kWordSizeLog2 - kSmiTagSize);
+  __ add(A7, A7, SP);
+  __ subi(A7, A7, 1 * target::kWordSize);
+
+  // A7: address of receiver
+  // Create a stub frame as we are pushing some objects on the stack before
+  // calling into the runtime.
+  __ EnterStubFrame();
+  // Preserve IC data object and arguments descriptor array and
+  // setup space on stack for result (target code object).
+  __ PushRegister(ARGS_DESC_REG);  // Preserve arguments descriptor array.
+  __ PushRegister(IC_DATA_REG);    // Preserve IC Data.
+  if (save_entry_point) {
+    __ SmiTag(T6);
+    __ PushRegister(T6);
+  }
+  // Setup space on stack for the result (target code object).
+  __ PushRegister(ZR);
+  // Push call arguments.
+  for (intptr_t i = 0; i < num_args; i++) {
+    __ LoadFromOffset(TMP, A7, -target::kWordSize * i);
+    __ PushRegister(TMP);
+  }
+  // Pass IC data object.
+  __ PushRegister(IC_DATA_REG);
+  __ CallRuntime(handle_ic_miss, num_args + 1);
+  // Remove the call arguments pushed earlier, including the IC data object.
+  __ Drop(num_args + 1);
+  // Pop returned function object into R0.
+  // Restore arguments descriptor array and IC data array.
+  __ PopRegister(T0);  // Pop returned function object into T0.
+  if (save_entry_point) {
+    __ PopRegister(T6);
+    __ SmiUntag(T6);
+  }
+  __ PopRegister(IC_DATA_REG);    // Restore IC Data.
+  __ PopRegister(ARGS_DESC_REG);  // Restore arguments descriptor array.
+  __ RestoreCodePointer();
+  __ LeaveStubFrame();
+  Label call_target_function;
+  if (!FLAG_lazy_dispatchers) {
+    GenerateDispatcherCode(assembler, &call_target_function);
+  } else {
+    __ j(&call_target_function);
+  }
+
+  __ Bind(&found);
+  __ Comment("Update caller's counter");
+  // A1: pointer to an IC data check group.
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(num_args) * target::kCompressedWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(num_args) * target::kCompressedWordSize;
+  __ LoadCompressedFromOffset(T0, A1, target_offset);
+
+  if (FLAG_optimization_counter_threshold >= 0) {
+    // Update counter, ignore overflow.
+    __ LoadCompressedSmiFromOffset(TMP, A1, count_offset);
+    __ addi(TMP, TMP, target::ToRawSmi(1));
+    __ StoreToOffset(TMP, A1, count_offset);
+  }
+
+  __ Comment("Call target");
+  __ Bind(&call_target_function);
+  // T0: target function.
+  __ LoadCompressedFieldFromOffset(CODE_REG, T0,
+                                   target::Function::code_offset());
+  if (save_entry_point) {
+    __ add(A7, T0, T6);
+    __ lx(A7, Address(A7, 0));
+  } else {
+    __ LoadFieldFromOffset(A7, T0, target::Function::entry_point_offset());
+  }
+  __ jr(A7);  // T0: Function, argument to lazy compile stub.
+
+#if !defined(PRODUCT)
+  if (optimized == kUnoptimized) {
+    __ Bind(&stepping);
+    __ EnterStubFrame();
+    if (type == kInstanceCall) {
+      __ PushRegister(A0);  // Preserve receiver.
+    }
+    if (save_entry_point) {
+      __ SmiTag(T6);
+      __ PushRegister(T6);
+    }
+    __ PushRegister(IC_DATA_REG);  // Preserve IC data.
+    __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
+    __ PopRegister(IC_DATA_REG);
+    if (save_entry_point) {
+      __ PopRegister(T6);
+      __ SmiUntag(T6);
+    }
+    if (type == kInstanceCall) {
+      __ PopRegister(A0);
+    }
+    __ RestoreCodePointer();
+    __ LeaveStubFrame();
+    __ j(&done_stepping);
+  }
+#endif
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
+    Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+    Assembler* assembler) {
+  __ Stop("Unimplemented");
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
+    Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateSmiLessInlineCacheStub(Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kLT,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
+      kUnoptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// A6: Function
+// RA: return address
+void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
+    Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// A0: receiver
+// S5: ICData
+// A6: Function
+// RA: return address
+void StubCodeCompiler::
+    GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
+        Assembler* assembler) {
+  __ Stop("Unimplemented");
+}
+
+// A0: receiver
+// S5: ICData
+// A6: Function
+// RA: return address
+void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
+    Assembler* assembler) {
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kOptimized, kInstanceCall, kIgnoreExactness);
+}
+
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
+  GenerateRecordEntryPoint(assembler);
+  GenerateUsageCounterIncrement(assembler, /* scratch */ T0);
+
+#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(TMP, IC_DATA_REG,
+                      target::ICData::state_bits_offset() - kHeapObjectTag,
+                      kUnsignedFourBytes);
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andi(TMP, TMP, target::ICData::NumArgsTestedMask());
+    __ CompareImmediate(TMP, 0);
+    __ BranchIf(EQ, &ok);
+    __ Stop("Incorrect IC data for unoptimized static call");
+    __ Bind(&ok);
+  }
+#endif  // DEBUG
+
+  // Check single stepping.
+#if !defined(PRODUCT)
+  Label stepping, done_stepping;
+  __ LoadIsolate(TMP);
+  __ LoadFromOffset(TMP, TMP, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
+  __ bnez(TMP, &stepping, Assembler::kNearJump);
+  __ Bind(&done_stepping);
+#endif
+
+  // T5: IC data object (preserved).
+  __ LoadFieldFromOffset(A0, IC_DATA_REG, target::ICData::entries_offset());
+  // A0: ic_data_array with entries: target functions and count.
+  __ AddImmediate(A0, target::Array::data_offset() - kHeapObjectTag);
+  // A0: points directly to the first ic data array element.
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(0) * target::kCompressedWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(0) * target::kCompressedWordSize;
+
+  if (FLAG_optimization_counter_threshold >= 0) {
+    // Increment count for this call, ignore overflow.
+    __ LoadCompressedSmiFromOffset(TMP, A0, count_offset);
+    __ addi(TMP, TMP, target::ToRawSmi(1));
+    __ StoreToOffset(TMP, A0, count_offset);
+  }
+
+  // Load arguments descriptor into T4.
+  __ LoadFieldFromOffset(ARGS_DESC_REG, IC_DATA_REG,
+                         target::CallSiteData::arguments_descriptor_offset());
+
+  // Get function and call it, if possible.
+  __ LoadCompressedFromOffset(T0, A0, target_offset);
+  __ LoadCompressedFieldFromOffset(CODE_REG, T0,
+                                   target::Function::code_offset());
+  __ add(A0, T0, T6);
+  __ lx(TMP, Address(A0, 0));
+  __ jr(TMP);  // T0: Function, argument to lazy compile stub.
+
+#if !defined(PRODUCT)
+  __ Bind(&stepping);
+  __ EnterStubFrame();
+  __ PushRegister(IC_DATA_REG);  // Preserve IC data.
+  __ SmiTag(T6);
+  __ PushRegister(T6);
+  __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
+  __ PopRegister(T6);
+  __ SmiUntag(T6);
+  __ PopRegister(IC_DATA_REG);
+  __ RestoreCodePointer();
+  __ LeaveStubFrame();
+  __ j(&done_stepping);
+#endif
+}
+
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
+    Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ T0);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
+}
+
+// S5: ICData
+// RA: return address
+void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
+  GenerateUsageCounterIncrement(assembler, /* scratch */ T0);
+  GenerateNArgsCheckInlineCacheStub(
+      assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
+      kUnoptimized, kStaticCall, kIgnoreExactness);
+}
+
+// Stub for compiling a function and jumping to the compiled code.
+// S4: Arguments descriptor.
+// T0: Function.
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
+  // Preserve arg desc.
+  __ EnterStubFrame();
+  __ PushRegister(ARGS_DESC_REG);  // Save arg. desc.
+  __ PushRegister(T0);             // Pass function.
+  __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
+  __ PopRegister(T0);             // Restore argument.
+  __ PopRegister(ARGS_DESC_REG);  // Restore arg desc.
+  __ LeaveStubFrame();
+
+  __ LoadCompressedFieldFromOffset(CODE_REG, T0,
+                                   target::Function::code_offset());
+  __ LoadFieldFromOffset(TMP, T0, target::Function::entry_point_offset());
+  __ jr(TMP);
+}
+
+// A0: Receiver
+// S5: ICData
+void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Stop("No debugging in PRODUCT mode");
+#else
+  __ EnterStubFrame();
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(A0, Address(SP, 2 * target::kWordSize));  // Preserve receiver.
+  __ sx(S5, Address(SP, 1 * target::kWordSize));  // Preserve IC data.
+  __ sx(ZR, Address(SP, 0 * target::kWordSize));  // Space for result.
+  __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
+  __ lx(CODE_REG, Address(SP, 0 * target::kWordSize));  // Original stub.
+  __ lx(S5, Address(SP, 1 * target::kWordSize));        // Restore IC data.
+  __ lx(A0, Address(SP, 2 * target::kWordSize));        // Restore receiver.
+  __ LeaveStubFrame();
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+#endif
+}
+
+// S5: ICData
+void StubCodeCompiler::GenerateUnoptStaticCallBreakpointStub(
+    Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Stop("No debugging in PRODUCT mode");
+#else
+  __ EnterStubFrame();
+  __ subi(SP, SP, 2 * target::kWordSize);
+  __ sx(S5, Address(SP, 1 * target::kWordSize));  // Preserve IC data.
+  __ sx(ZR, Address(SP, 0 * target::kWordSize));  // Space for result.
+  __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
+  __ lx(CODE_REG, Address(SP, 0 * target::kWordSize));  // Original stub.
+  __ lx(S5, Address(SP, 1 * target::kWordSize));        // Restore IC data.
+  __ LeaveStubFrame();
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+#endif  // defined(PRODUCT)
+}
+
+void StubCodeCompiler::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Stop("No debugging in PRODUCT mode");
+#else
+  __ EnterStubFrame();
+  __ subi(SP, SP, 1 * target::kWordSize);
+  __ sx(ZR, Address(SP, 0 * target::kWordSize));  // Space for result.
+  __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
+  __ lx(CODE_REG, Address(SP, 0 * target::kWordSize));
+  __ LeaveStubFrame();
+  __ LoadFieldFromOffset(TMP, CODE_REG, target::Code::entry_point_offset());
+  __ jr(TMP);
+#endif  // defined(PRODUCT)
+}
+
+// Called only from unoptimized code. All relevant registers have been saved.
+void StubCodeCompiler::GenerateDebugStepCheckStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Stop("No debugging in PRODUCT mode");
+#else
+  // Check single stepping.
+  Label stepping, done_stepping;
+  __ LoadIsolate(A1);
+  __ LoadFromOffset(A1, A1, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
+  __ bnez(A1, &stepping, compiler::Assembler::kNearJump);
+  __ Bind(&done_stepping);
+  __ ret();
+
+  __ Bind(&stepping);
+  __ EnterStubFrame();
+  __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
+  __ LeaveStubFrame();
+  __ j(&done_stepping);
+#endif  // defined(PRODUCT)
+}
+
+// Used to check class and type arguments. Arguments passed in registers:
+//
+// Inputs (mostly from TypeTestABI struct):
+//   - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
+//   - kInstanceReg: instance to test against.
+//   - kDstTypeReg: destination type (for n>=3).
+//   - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n=5).
+//   - kFunctionTypeArgumentsReg: function type arguments (for n=5).
+//   - RA: return address.
+//
+// All input registers are preserved except for kSubtypeTestCacheReg, which
+// should be saved by the caller if needed.
+//
+// Result in SubtypeTestCacheABI::kResultReg: null -> not found, otherwise
+// result (true or false).
+static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
+  ASSERT(n == 1 || n == 3 || n == 5 || n == 7);
+
+  // Until we have the result, we use the result register to store the null
+  // value for quick access. This has the side benefit of initializing the
+  // result to null, so it only needs to be changed if found.
+  const Register kNullReg = TypeTestABI::kSubtypeTestCacheResultReg;
+  __ LoadObject(kNullReg, NullObject());
+
+  const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheReg;
+  const Register kScratchReg = TypeTestABI::kScratchReg;
+
+  // All of these must be distinct from TypeTestABI::kSubtypeTestCacheResultReg
+  // since it is used for kNullReg as well.
+
+  // Loop initialization (moved up here to avoid having all dependent loads
+  // after each other).
+
+  // We avoid a load-acquire barrier here by relying on the fact that all other
+  // loads from the array are data-dependent loads.
+  __ lx(kCacheArrayReg, FieldAddress(TypeTestABI::kSubtypeTestCacheReg,
+                                     target::SubtypeTestCache::cache_offset()));
+  __ AddImmediate(kCacheArrayReg,
+                  target::Array::data_offset() - kHeapObjectTag);
+
+  Label loop, not_closure;
+  if (n >= 5) {
+    __ LoadClassIdMayBeSmi(STCInternalRegs::kInstanceCidOrSignatureReg,
+                           TypeTestABI::TypeTestABI::kInstanceReg);
+  } else {
+    __ LoadClassId(STCInternalRegs::kInstanceCidOrSignatureReg,
+                   TypeTestABI::kInstanceReg);
+  }
+  __ CompareImmediate(STCInternalRegs::kInstanceCidOrSignatureReg, kClosureCid);
+  __ BranchIf(NE, &not_closure);
+
+  // Closure handling.
+  {
+    __ Comment("Closure");
+    __ LoadCompressed(STCInternalRegs::kInstanceCidOrSignatureReg,
+                      FieldAddress(TypeTestABI::kInstanceReg,
+                                   target::Closure::function_offset()));
+    __ LoadCompressed(STCInternalRegs::kInstanceCidOrSignatureReg,
+                      FieldAddress(STCInternalRegs::kInstanceCidOrSignatureReg,
+                                   target::Function::signature_offset()));
+    if (n >= 3) {
+      __ LoadCompressed(
+          STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
+          FieldAddress(TypeTestABI::kInstanceReg,
+                       target::Closure::instantiator_type_arguments_offset()));
+      if (n >= 7) {
+        __ LoadCompressed(
+            STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg,
+            FieldAddress(TypeTestABI::kInstanceReg,
+                         target::Closure::function_type_arguments_offset()));
+        __ LoadCompressed(
+            STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg,
+            FieldAddress(TypeTestABI::kInstanceReg,
+                         target::Closure::delayed_type_arguments_offset()));
+      }
+    }
+    __ j(&loop);
+  }
+
+  // Non-Closure handling.
+  {
+    __ Comment("Non-Closure");
+    __ Bind(&not_closure);
+    if (n >= 3) {
+      Label has_no_type_arguments;
+      __ LoadClassById(kScratchReg,
+                       STCInternalRegs::kInstanceCidOrSignatureReg);
+      __ mv(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg, kNullReg);
+      __ LoadFieldFromOffset(
+          kScratchReg, kScratchReg,
+          target::Class::host_type_arguments_field_offset_in_words_offset(),
+          kFourBytes);
+      __ CompareImmediate(kScratchReg, target::Class::kNoTypeArguments);
+      __ BranchIf(EQ, &has_no_type_arguments);
+      __ slli(kScratchReg, kScratchReg, kCompressedWordSizeLog2);
+      __ add(kScratchReg, kScratchReg, TypeTestABI::kInstanceReg);
+      __ LoadCompressed(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
+                        FieldAddress(kScratchReg, 0));
+      __ Bind(&has_no_type_arguments);
+      __ Comment("No type arguments");
+
+      if (n >= 7) {
+        __ mv(STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg,
+              kNullReg);
+        __ mv(STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg,
+              kNullReg);
+      }
+    }
+    __ SmiTag(STCInternalRegs::kInstanceCidOrSignatureReg);
+  }
+
+  Label found, done, next_iteration;
+
+  // Loop header
+  __ Bind(&loop);
+  __ Comment("Loop");
+  __ LoadCompressed(
+      kScratchReg,
+      Address(kCacheArrayReg,
+              target::kCompressedWordSize *
+                  target::SubtypeTestCache::kInstanceCidOrSignature));
+  __ CompareObjectRegisters(kScratchReg, kNullReg);
+  __ BranchIf(EQ, &done);
+  __ CompareObjectRegisters(kScratchReg,
+                            STCInternalRegs::kInstanceCidOrSignatureReg);
+  if (n == 1) {
+    __ BranchIf(EQ, &found);
+  } else {
+    __ BranchIf(NE, &next_iteration);
+    __ LoadCompressed(kScratchReg,
+                      Address(kCacheArrayReg,
+                              target::kCompressedWordSize *
+                                  target::SubtypeTestCache::kDestinationType));
+    __ CompareRegisters(kScratchReg, TypeTestABI::kDstTypeReg);
+    __ BranchIf(NE, &next_iteration);
+    __ LoadCompressed(
+        kScratchReg,
+        Address(kCacheArrayReg,
+                target::kCompressedWordSize *
+                    target::SubtypeTestCache::kInstanceTypeArguments));
+    __ CompareRegisters(kScratchReg,
+                        STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg);
+    if (n == 3) {
+      __ BranchIf(EQ, &found);
+    } else {
+      __ BranchIf(NE, &next_iteration);
+      __ LoadCompressed(
+          kScratchReg,
+          Address(kCacheArrayReg,
+                  target::kCompressedWordSize *
+                      target::SubtypeTestCache::kInstantiatorTypeArguments));
+      __ CompareRegisters(kScratchReg,
+                          TypeTestABI::kInstantiatorTypeArgumentsReg);
+      __ BranchIf(NE, &next_iteration);
+      __ LoadCompressed(
+          kScratchReg,
+          Address(kCacheArrayReg,
+                  target::kCompressedWordSize *
+                      target::SubtypeTestCache::kFunctionTypeArguments));
+      __ CompareRegisters(kScratchReg, TypeTestABI::kFunctionTypeArgumentsReg);
+      if (n == 5) {
+        __ BranchIf(EQ, &found);
+      } else {
+        ASSERT(n == 7);
+        __ BranchIf(NE, &next_iteration);
+
+        __ LoadCompressed(
+            kScratchReg, Address(kCacheArrayReg,
+                                 target::kCompressedWordSize *
+                                     target::SubtypeTestCache::
+                                         kInstanceParentFunctionTypeArguments));
+        __ CompareRegisters(
+            kScratchReg,
+            STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg);
+        __ BranchIf(NE, &next_iteration);
+
+        __ LoadCompressed(
+            kScratchReg,
+            Address(kCacheArrayReg,
+                    target::kCompressedWordSize *
+                        target::SubtypeTestCache::
+                            kInstanceDelayedFunctionTypeArguments));
+        __ CompareRegisters(
+            kScratchReg,
+            STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg);
+        __ BranchIf(EQ, &found);
+      }
+    }
+  }
+  __ Bind(&next_iteration);
+  __ Comment("Next iteration");
+  __ AddImmediate(
+      kCacheArrayReg,
+      target::kCompressedWordSize * target::SubtypeTestCache::kTestEntryLength);
+  __ j(&loop);
+
+  __ Bind(&found);
+  __ Comment("Found");
+  __ LoadCompressed(
+      TypeTestABI::kSubtypeTestCacheResultReg,
+      Address(kCacheArrayReg, target::kCompressedWordSize *
+                                  target::SubtypeTestCache::kTestResult));
+  __ Bind(&done);
+  __ Comment("Done");
+  __ ret();
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype1TestCacheStub(Assembler* assembler) {
+  GenerateSubtypeNTestCacheStub(assembler, 1);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype3TestCacheStub(Assembler* assembler) {
+  GenerateSubtypeNTestCacheStub(assembler, 3);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype5TestCacheStub(Assembler* assembler) {
+  GenerateSubtypeNTestCacheStub(assembler, 5);
+}
+
+// See comment on [GenerateSubtypeNTestCacheStub].
+void StubCodeCompiler::GenerateSubtype7TestCacheStub(Assembler* assembler) {
+  GenerateSubtypeNTestCacheStub(assembler, 7);
+}
+
+void StubCodeCompiler::GenerateGetCStackPointerStub(Assembler* assembler) {
+  __ mv(A0, SP);
+  __ ret();
+}
+
+// Jump to a frame on the call stack.
+// RA: return address.
+// A0: program_counter.
+// A1: stack_pointer.
+// A2: frame_pointer.
+// A3: thread.
+// Does not return.
+//
+// Notice: We need to keep this in sync with `Simulator::JumpToFrame()`.
+void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
+  ASSERT(kExceptionObjectReg == A0);
+  ASSERT(kStackTraceObjectReg == A1);
+  __ mv(CALLEE_SAVED_TEMP, A0);  // Program counter.
+  __ mv(SP, A1);                 // Stack pointer.
+  __ mv(FP, A2);                 // Frame_pointer.
+  __ mv(THR, A3);
+#if defined(USING_SHADOW_CALL_STACK)
+#error Unimplemented
+#endif
+  Label exit_through_non_ffi;
+  // Check if we exited generated from FFI. If so do transition.
+  __ LoadFromOffset(TMP, THR,
+                    compiler::target::Thread::exit_through_ffi_offset());
+  __ LoadImmediate(TMP2, target::Thread::exit_through_ffi());
+  __ bne(TMP, TMP2, &exit_through_non_ffi);
+  __ Stop("Unimplemented");
+  __ Bind(&exit_through_non_ffi);
+
+  // Refresh pinned registers values (inc. write barrier mask and null object).
+  __ RestorePinnedRegisters();
+  // Set the tag.
+  __ LoadImmediate(TMP, VMTag::kDartTagId);
+  __ StoreToOffset(TMP, THR, target::Thread::vm_tag_offset());
+  // Clear top exit frame.
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+  // Restore the pool pointer.
+  __ RestoreCodePointer();
+  if (FLAG_precompiled_mode) {
+    __ SetupGlobalPoolAndDispatchTable();
+  } else {
+    __ LoadPoolPointer();
+  }
+  __ jr(CALLEE_SAVED_TEMP);  // Jump to continuation point.
+}
+
+// Run an exception handler.  Execution comes from JumpToFrame
+// stub or from the simulator.
+//
+// The arguments are stored in the Thread object.
+// Does not return.
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+  // Exception object.
+  ASSERT(kExceptionObjectReg == A0);
+  __ LoadFromOffset(A0, THR, target::Thread::active_exception_offset());
+  __ StoreToOffset(NULL_REG, THR, target::Thread::active_exception_offset());
+
+  // StackTrace object.
+  ASSERT(kStackTraceObjectReg == A1);
+  __ LoadFromOffset(A1, THR, target::Thread::active_stacktrace_offset());
+  __ StoreToOffset(NULL_REG, THR, target::Thread::active_stacktrace_offset());
+
+  __ LoadFromOffset(RA, THR, target::Thread::resume_pc_offset());
+  __ ret();  // Jump to the exception handler code.
+}
+
+// Deoptimize a frame on the call stack before rewinding.
+// The arguments are stored in the Thread object.
+// No result.
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
+  // Push zap value instead of CODE_REG.
+  __ LoadImmediate(TMP, kZapCodeReg);
+  __ PushRegister(TMP);
+
+  // Load the deopt pc into RA.
+  __ LoadFromOffset(RA, THR, target::Thread::resume_pc_offset());
+  GenerateDeoptimizationSequence(assembler, kEagerDeopt);
+
+  // After we have deoptimized, jump to the correct frame.
+  __ EnterStubFrame();
+  __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0);
+  __ LeaveStubFrame();
+  __ ebreak();
+}
+
+// Calls to the runtime to optimize the given function.
+// A0: function to be re-optimized.
+// S4: argument descriptor (preserved).
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ LoadFromOffset(CODE_REG, THR, target::Thread::optimize_stub_offset());
+  __ EnterStubFrame();
+
+  __ subi(SP, SP, 3 * target::kWordSize);
+  __ sx(S4, Address(SP, 2 * target::kWordSize));  // Preserves args descriptor.
+  __ sx(ZR, Address(SP, 1 * target::kWordSize));  // Result slot.
+  __ sx(A0, Address(SP, 0 * target::kWordSize));  // Function argument.
+  __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
+  __ lx(T0, Address(SP, 1 * target::kWordSize));  // Function result.
+  __ lx(S4, Address(SP, 2 * target::kWordSize));  // Restore args descriptor.
+  __ addi(SP, SP, 3 * target::kWordSize);
+
+  __ LoadCompressedFieldFromOffset(CODE_REG, T0,
+                                   target::Function::code_offset());
+  __ LoadFieldFromOffset(A1, T0, target::Function::entry_point_offset());
+  __ LeaveStubFrame();
+  __ jr(A1);
+  __ ebreak();
+}
+
+// Does identical check (object references are equal or not equal) with special
+// checks for boxed numbers and returns with TMP = 0 iff left and right are
+// identical.
+static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                 const Register left,
+                                                 const Register right) {
+  Label reference_compare, check_mint, done;
+  // If any of the arguments is Smi do reference compare.
+  // Note: A Mint cannot contain a value that would fit in Smi.
+  __ BranchIfSmi(left, &reference_compare, Assembler::kNearJump);
+  __ BranchIfSmi(right, &reference_compare, Assembler::kNearJump);
+
+  // Value compare for two doubles.
+  __ CompareClassId(left, kDoubleCid, /*scratch*/ TMP);
+  __ BranchIf(NOT_EQUAL, &check_mint, Assembler::kNearJump);
+  __ CompareClassId(right, kDoubleCid, /*scratch*/ TMP);
+  __ BranchIf(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
+
+  // Double values bitwise compare.
+#if XLEN == 32
+  __ lw(T0, FieldAddress(left, target::Double::value_offset()));
+  __ lw(T1, FieldAddress(right, target::Double::value_offset()));
+  __ xor_(TMP, T0, T1);
+  __ lw(T0, FieldAddress(left, target::Double::value_offset() + 4));
+  __ lw(T1, FieldAddress(right, target::Double::value_offset() + 4));
+  __ xor_(TMP2, T0, T1);
+  __ or_(TMP, TMP, TMP2);
+#else
+  __ ld(T0, FieldAddress(left, target::Double::value_offset()));
+  __ ld(T1, FieldAddress(right, target::Double::value_offset()));
+  __ xor_(TMP, T0, T1);
+#endif
+  __ j(&done, Assembler::kNearJump);
+
+  __ Bind(&check_mint);
+  __ CompareClassId(left, kMintCid, /*scratch*/ TMP);
+  __ BranchIf(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
+  __ CompareClassId(right, kMintCid, /*scratch*/ TMP);
+  __ BranchIf(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
+#if XLEN == 32
+  __ lw(T0, FieldAddress(left, target::Mint::value_offset()));
+  __ lw(T1, FieldAddress(right, target::Mint::value_offset()));
+  __ xor_(TMP, T0, T1);
+  __ lw(T0, FieldAddress(left, target::Mint::value_offset() + 4));
+  __ lw(T1, FieldAddress(right, target::Mint::value_offset() + 4));
+  __ xor_(TMP2, T0, T1);
+  __ or_(TMP, TMP, TMP2);
+#else
+  __ ld(T0, FieldAddress(left, target::Mint::value_offset()));
+  __ ld(T1, FieldAddress(right, target::Mint::value_offset()));
+  __ xor_(TMP, T0, T1);
+#endif
+  __ j(&done, Assembler::kNearJump);
+
+  __ Bind(&reference_compare);
+  __ xor_(TMP, left, right);
+  __ Bind(&done);
+}
+
+// Called only from unoptimized code. All relevant registers have been saved.
+// RA: return address.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Return TMP set to 0 if equal.
+void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+#if !defined(PRODUCT)
+  // Check single stepping.
+  Label stepping, done_stepping;
+  __ LoadIsolate(TMP);
+  __ LoadFromOffset(TMP, TMP, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
+  __ bnez(TMP, &stepping);
+  __ Bind(&done_stepping);
+#endif
+
+  const Register left = A0;
+  const Register right = A1;
+  __ LoadFromOffset(left, SP, 1 * target::kWordSize);
+  __ LoadFromOffset(right, SP, 0 * target::kWordSize);
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right);
+  __ ret();
+
+#if !defined(PRODUCT)
+  __ Bind(&stepping);
+  __ EnterStubFrame();
+  __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
+  __ RestoreCodePointer();
+  __ LeaveStubFrame();
+  __ j(&done_stepping);
+#endif
+}
+
+// Called from optimized code only.
+// RA: return address.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Return TMP set to 0 if equal.
+void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register left = A0;
+  const Register right = A1;
+  __ LoadFromOffset(left, SP, 1 * target::kWordSize);
+  __ LoadFromOffset(right, SP, 0 * target::kWordSize);
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right);
+  __ ret();
+}
+
+// Called from megamorphic call sites.
+//  A0: receiver (passed to target)
+//  S5: MegamorphicCache (preserved)
+// Passed to target:
+//  A0: receiver
+//  CODE_REG: target Code
+//  S4: arguments descriptor
+//  S5: MegamorphicCache
+void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
+  // Jump if receiver is a smi.
+  Label smi_case;
+  __ BranchIfSmi(A0, &smi_case);
+
+  // Loads the cid of the object.
+  __ LoadClassId(T5, A0);
+
+  Label cid_loaded;
+  __ Bind(&cid_loaded);
+  __ lx(T2, FieldAddress(S5, target::MegamorphicCache::buckets_offset()));
+  __ lx(T1, FieldAddress(S5, target::MegamorphicCache::mask_offset()));
+  // T2: cache buckets array.
+  // T1: mask as a smi.
+
+  // Make the cid into a smi.
+  __ SmiTag(T5);
+  // T5: class ID of the receiver (smi).
+
+  // Compute the table index.
+  ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
+  // Use lsl and sub to multiply with 7 == 8 - 1.
+  __ slli(T3, T5, 3);
+  __ sub(T3, T3, T5);
+  // T3: probe.
+  Label loop;
+  __ Bind(&loop);
+  __ and_(T3, T3, T1);
+
+  const intptr_t base = target::Array::data_offset();
+  // T3 is smi tagged, but table entries are 16 bytes, so LSL 3.
+  __ slli(TMP, T3, kCompressedWordSizeLog2);
+  __ add(TMP, TMP, T2);
+  __ LoadCompressedSmiFieldFromOffset(T4, TMP, base);
+  Label probe_failed;
+  __ CompareObjectRegisters(T4, T5);
+  __ BranchIf(NE, &probe_failed);
+
+  Label load_target;
+  __ Bind(&load_target);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ LoadCompressed(T0, FieldAddress(TMP, base + target::kCompressedWordSize));
+  __ lx(A1, FieldAddress(T0, target::Function::entry_point_offset()));
+  __ lx(ARGS_DESC_REG,
+        FieldAddress(S5, target::CallSiteData::arguments_descriptor_offset()));
+  if (!FLAG_precompiled_mode) {
+    __ LoadCompressed(CODE_REG,
+                      FieldAddress(T0, target::Function::code_offset()));
+  }
+  __ jr(A1);  // T0: Function, argument to lazy compile stub.
+
+  // Probe failed, check if it is a miss.
+  __ Bind(&probe_failed);
+  ASSERT(kIllegalCid == 0);
+  Label miss;
+  __ beqz(T4, &miss);  // branch if miss.
+
+  // Try next extry in the table.
+  __ AddImmediate(T3, target::ToRawSmi(1));
+  __ j(&loop);
+
+  // Load cid for the Smi case.
+  __ Bind(&smi_case);
+  __ LoadImmediate(T5, kSmiCid);
+  __ j(&cid_loaded);
+
+  __ Bind(&miss);
+  GenerateSwitchableCallMissStub(assembler);
+}
+
+// Input:
+//   A0 - receiver
+//   S5 - icdata
+void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
+  Label loop, found, miss;
+  __ lx(T1, FieldAddress(S5, target::ICData::entries_offset()));
+  __ lx(S4,
+        FieldAddress(S5, target::CallSiteData::arguments_descriptor_offset()));
+  __ AddImmediate(T1, target::Array::data_offset() - kHeapObjectTag);
+  // T1: first IC entry
+  __ LoadTaggedClassIdMayBeSmi(A1, A0);
+  // A1: receiver cid as Smi
+
+  __ Bind(&loop);
+  __ LoadCompressedSmi(T2, Address(T1, 0));
+  __ beq(A1, T2, &found);
+  __ CompareImmediate(T2, target::ToRawSmi(kIllegalCid));
+  __ BranchIf(EQ, &miss);
+
+  const intptr_t entry_length =
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kCompressedWordSize;
+  __ AddImmediate(T1, entry_length);  // Next entry.
+  __ j(&loop);
+
+  __ Bind(&found);
+  if (FLAG_precompiled_mode) {
+    const intptr_t entry_offset =
+        target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(A1, Address(T1, entry_offset));
+    __ lx(A1, FieldAddress(A1, target::Function::entry_point_offset()));
+  } else {
+    const intptr_t code_offset =
+        target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(CODE_REG, Address(T1, code_offset));
+    __ lx(A1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+  }
+  __ jr(A1);
+
+  __ Bind(&miss);
+  __ LoadIsolate(A1);
+  __ lx(CODE_REG, Address(A1, target::Isolate::ic_miss_code_offset()));
+  __ lx(A1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
+  __ jr(A1);
+}
+
+// Implement the monomorphic entry check for call-sites where the receiver
+// might be a Smi.
+//
+//   A0: receiver
+//   S5: MonomorphicSmiableCall object
+//
+//   T1,T2: clobbered
+void StubCodeCompiler::GenerateMonomorphicSmiableCheckStub(
+    Assembler* assembler) {
+  Label miss;
+  __ LoadClassIdMayBeSmi(T1, A0);
+
+  // Note: this stub is only used in AOT mode, hence the direct (bare) call.
+  __ LoadField(
+      T2,
+      FieldAddress(S5, target::MonomorphicSmiableCall::expected_cid_offset()));
+  __ LoadField(
+      TMP,
+      FieldAddress(S5, target::MonomorphicSmiableCall::entrypoint_offset()));
+  __ bne(T1, T2, &miss);
+  __ jr(TMP);
+
+  __ Bind(&miss);
+  __ lx(TMP, Address(THR, target::Thread::switchable_call_miss_entry_offset()));
+  __ jr(TMP);
+}
+
+// Called from switchable IC calls.
+//  A0: receiver
+void StubCodeCompiler::GenerateSwitchableCallMissStub(Assembler* assembler) {
+  __ lx(CODE_REG,
+        Address(THR, target::Thread::switchable_call_miss_stub_offset()));
+  __ EnterStubFrame();
+  __ PushRegister(A0);  // Preserve receiver.
+
+  __ PushRegister(ZR);  // Result slot.
+  __ PushRegister(ZR);  // Arg0: stub out.
+  __ PushRegister(A0);  // Arg1: Receiver
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
+  __ Drop(1);
+  __ PopRegister(CODE_REG);     // result = stub
+  __ PopRegister(IC_DATA_REG);  // result = IC
+
+  __ PopRegister(A0);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ lx(TMP, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kNormal)));
+  __ jr(TMP);
+}
+
+// Called from switchable IC calls.
+//  A0: receiver
+//  S5: SingleTargetCache
+// Passed to target:
+//  CODE_REG: target Code object
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
+  Label miss;
+  __ LoadClassIdMayBeSmi(A1, A0);
+  __ lhu(T2, FieldAddress(S5, target::SingleTargetCache::lower_limit_offset()));
+  __ lhu(T3, FieldAddress(S5, target::SingleTargetCache::upper_limit_offset()));
+
+  __ blt(A1, T2, &miss);
+  __ bgt(A1, T3, &miss);
+
+  __ lx(TMP, FieldAddress(S5, target::SingleTargetCache::entry_point_offset()));
+  __ lx(CODE_REG, FieldAddress(S5, target::SingleTargetCache::target_offset()));
+  __ jr(TMP);
+
+  __ Bind(&miss);
+  __ EnterStubFrame();
+  __ PushRegister(A0);  // Preserve receiver.
+
+  __ PushRegister(ZR);  // Result slot.
+  __ PushRegister(ZR);  // Arg0: Stub out.
+  __ PushRegister(A0);  // Arg1: Receiver
+  __ CallRuntime(kSwitchableCallMissRuntimeEntry, 2);
+  __ Drop(1);
+  __ PopRegister(CODE_REG);  // result = stub
+  __ PopRegister(S5);        // result = IC
+
+  __ PopRegister(A0);  // Restore receiver.
+  __ LeaveStubFrame();
+
+  __ lx(TMP, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kMonomorphic)));
+  __ jr(TMP);
+}
+
+// Instantiate type arguments from instantiator and function type args.
+// T1 uninstantiated type arguments.
+// T2 instantiator type arguments.
+// T3: function type arguments.
+// Returns instantiated type arguments in T5.
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
+    Assembler* assembler) {
+  // Lookup cache before calling runtime.
+  __ LoadCompressedFieldFromOffset(
+      A1, InstantiationABI::kUninstantiatedTypeArgumentsReg,
+      target::TypeArguments::instantiations_offset());
+  __ AddImmediate(A1, Array::data_offset() - kHeapObjectTag);
+  // The instantiations cache is initialized with Object::zero_array() and is
+  // therefore guaranteed to contain kNoInstantiator. No length check needed.
+  compiler::Label loop, next, found, call_runtime;
+  __ Bind(&loop);
+
+  // Use load-acquire to test for sentinel, if we found non-sentinel it is safe
+  // to access the other entries. If we found a sentinel we go to runtime.
+  __ LoadAcquireCompressed(
+      A6, A1,
+      TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
+          target::kCompressedWordSize);
+  __ CompareImmediate(A6, Smi::RawValue(TypeArguments::kNoInstantiator),
+                      kObjectBytes);
+  __ BranchIf(EQ, &call_runtime);
+
+  __ CompareRegisters(A6, InstantiationABI::kInstantiatorTypeArgumentsReg);
+  __ BranchIf(NE, &next);
+  __ LoadCompressedFromOffset(
+      A7, A1,
+      TypeArguments::Instantiation::kFunctionTypeArgsIndex *
+          target::kCompressedWordSize);
+  __ CompareRegisters(A7, InstantiationABI::kFunctionTypeArgumentsReg);
+  __ BranchIf(EQ, &found);
+  __ Bind(&next);
+  __ AddImmediate(A1, TypeArguments::Instantiation::kSizeInWords *
+                          target::kCompressedWordSize);
+  __ j(&loop);
+
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ Bind(&call_runtime);
+  __ EnterStubFrame();
+  __ PushRegisterPair(InstantiationABI::kUninstantiatedTypeArgumentsReg,
+                      NULL_REG);
+  __ PushRegisterPair(InstantiationABI::kFunctionTypeArgumentsReg,
+                      InstantiationABI::kInstantiatorTypeArgumentsReg);
+  __ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
+  __ Drop(3);  // Drop 2 type vectors, and uninstantiated type.
+  __ PopRegister(InstantiationABI::kResultTypeArgumentsReg);
+  __ LeaveStubFrame();
+  __ Ret();
+
+  __ Bind(&found);
+  __ LoadCompressedFromOffset(
+      InstantiationABI::kResultTypeArgumentsReg, A1,
+      TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
+          target::kCompressedWordSize);
+  __ Ret();
+}
+
+void StubCodeCompiler::
+    GenerateInstantiateTypeArgumentsMayShareInstantiatorTAStub(
+        Assembler* assembler) {
+  // Return the instantiator type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ LoadCompressedSmi(
+      A6, FieldAddress(InstantiationABI::kUninstantiatedTypeArgumentsReg,
+                       target::TypeArguments::nullability_offset()));
+  __ LoadCompressedSmi(
+      A7, FieldAddress(InstantiationABI::kInstantiatorTypeArgumentsReg,
+                       target::TypeArguments::nullability_offset()));
+  __ and_(A7, A7, A6);
+  __ CompareRegisters(A7, A6);
+  __ BranchIf(NE, &cache_lookup);
+  __ mv(InstantiationABI::kResultTypeArgumentsReg,
+        InstantiationABI::kInstantiatorTypeArgumentsReg);
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
+    Assembler* assembler) {
+  // Return the function type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ LoadCompressedSmi(
+      A6, FieldAddress(InstantiationABI::kUninstantiatedTypeArgumentsReg,
+                       target::TypeArguments::nullability_offset()));
+  __ LoadCompressedSmi(
+      A7, FieldAddress(InstantiationABI::kFunctionTypeArgumentsReg,
+                       target::TypeArguments::nullability_offset()));
+  __ and_(A7, A7, A6);
+  __ CompareRegisters(A7, A6);
+  __ BranchIf(NE, &cache_lookup);
+  __ mv(InstantiationABI::kResultTypeArgumentsReg,
+        InstantiationABI::kFunctionTypeArgumentsReg);
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+static int GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1:
+      return 0;
+    case 2:
+      return 1;
+    case 4:
+      return 2;
+    case 8:
+      return 3;
+    case 16:
+      return 4;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                          intptr_t cid) {
+  const intptr_t element_size = TypedDataElementSizeInBytes(cid);
+  const intptr_t max_len = TypedDataMaxNewSpaceElements(cid);
+  const intptr_t scale_shift = GetScaleFactor(element_size);
+
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kLengthReg == T2);
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kResultReg == A0);
+
+  if (!FLAG_use_slow_path && FLAG_inline_alloc) {
+    Label call_runtime;
+    NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, T3, &call_runtime));
+    __ mv(T3, AllocateTypedDataArrayABI::kLengthReg);
+    /* Check that length is a positive Smi. */
+    /* T3: requested array length argument. */
+    __ BranchIfNotSmi(T3, &call_runtime);
+    __ SmiUntag(T3);
+    /* Check for length >= 0 && length <= max_len. */
+    /* T3: untagged array length. */
+    __ CompareImmediate(T3, max_len, kObjectBytes);
+    __ BranchIf(UNSIGNED_GREATER, &call_runtime);
+    if (scale_shift != 0) {
+      __ slli(T3, T3, scale_shift);
+    }
+    const intptr_t fixed_size_plus_alignment_padding =
+        target::TypedData::HeaderSize() +
+        target::ObjectAlignment::kObjectAlignment - 1;
+    __ AddImmediate(T3, fixed_size_plus_alignment_padding);
+    __ andi(T3, T3, ~(target::ObjectAlignment::kObjectAlignment - 1));
+    __ lx(A0, Address(THR, target::Thread::top_offset()));
+
+    /* T3: allocation size. */
+    __ add(T4, A0, T3);
+    __ bltu(T4, A0, &call_runtime); /* Fail on unsigned overflow. */
+
+    /* Check if the allocation fits into the remaining space. */
+    /* A0: potential new object start. */
+    /* T4: potential next object start. */
+    /* T3: allocation size. */
+    __ lx(TMP, Address(THR, target::Thread::end_offset()));
+    __ bgeu(T4, TMP, &call_runtime);
+
+    /* Successfully allocated the object(s), now update top to point to */
+    /* next object start and initialize the object. */
+    __ sx(T4, Address(THR, target::Thread::top_offset()));
+    __ AddImmediate(A0, kHeapObjectTag);
+    /* Initialize the tags. */
+    /* A0: new object start as a tagged pointer. */
+    /* T4: new object end address. */
+    /* T3: allocation size. */
+    {
+      __ li(T5, 0);
+      __ CompareImmediate(T3, target::UntaggedObject::kSizeTagMaxSizeTag);
+      compiler::Label zero_tags;
+      __ BranchIf(HI, &zero_tags);
+      __ slli(T5, T3,
+              target::UntaggedObject::kTagBitsSizeTagPos -
+                  target::ObjectAlignment::kObjectAlignmentLog2);
+      __ Bind(&zero_tags);
+
+      /* Get the class index and insert it into the tags. */
+      uword tags =
+          target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+      __ OrImmediate(T5, T5, tags);
+      __ sx(T5, FieldAddress(A0, target::Object::tags_offset())); /* Tags. */
+    }
+    /* Set the length field. */
+    /* A0: new object start as a tagged pointer. */
+    /* T4: new object end address. */
+    __ mv(T3, AllocateTypedDataArrayABI::kLengthReg); /* Array length. */
+    __ StoreCompressedIntoObjectNoBarrier(
+        A0, FieldAddress(A0, target::TypedDataBase::length_offset()), T3);
+    /* Initialize all array elements to 0. */
+    /* A0: new object start as a tagged pointer. */
+    /* T4: new object end address. */
+    /* T3: iterator which initially points to the start of the variable */
+    /* R3: scratch register. */
+    /* data area to be initialized. */
+    __ AddImmediate(T3, A0, target::TypedData::HeaderSize() - 1);
+    __ StoreInternalPointer(
+        A0, FieldAddress(A0, target::TypedDataBase::data_field_offset()), T3);
+    Label init_loop, done;
+    __ Bind(&init_loop);
+    __ bgeu(T3, T4, &done);
+    __ sx(ZR, Address(T3, 0));
+    __ addi(T3, T3, target::kWordSize);
+    __ j(&init_loop);
+    __ Bind(&done);
+
+    __ Ret();
+
+    __ Bind(&call_runtime);
+  }
+
+  __ EnterStubFrame();
+  __ PushRegister(ZR);                                     // Result slot.
+  __ PushImmediate(target::ToRawSmi(cid));                 // Cid
+  __ PushRegister(AllocateTypedDataArrayABI::kLengthReg);  // Array length
+  __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
+  __ Drop(2);  // Drop arguments.
+  __ PopRegister(AllocateTypedDataArrayABI::kResultReg);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
+}  // namespace compiler
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV)
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index ae87dca..fb870b5 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -335,7 +335,8 @@
   __ ret();
 }
 
-void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+static void GenerateExitSafepointStubCommon(Assembler* assembler,
+                                            uword runtime_entry_offset) {
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
@@ -349,7 +350,7 @@
   __ movq(Address(THR, target::Thread::execution_state_offset()),
           Immediate(target::Thread::vm_execution_state()));
 
-  __ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
+  __ movq(RAX, Address(THR, runtime_entry_offset));
   __ CallCFunction(RAX);
   __ LeaveFrame();
 
@@ -357,6 +358,18 @@
   __ ret();
 }
 
+void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler, kExitSafepointRuntimeEntry.OffsetFromThread());
+}
+
+void StubCodeCompiler::GenerateExitSafepointIgnoreUnwindInProgressStub(
+    Assembler* assembler) {
+  GenerateExitSafepointStubCommon(
+      assembler,
+      kExitSafepointIgnoreUnwindInProgressRuntimeEntry.OffsetFromThread());
+}
+
 // Calls native code within a safepoint.
 //
 // On entry:
@@ -3140,12 +3153,18 @@
 #error Unimplemented
 #endif
   Label exit_through_non_ffi;
-  // Check if we exited generated from FFI. If so do transition.
+  // Check if we exited generated from FFI. If so do transition - this is needed
+  // because normally runtime calls transition back to generated via destructor
+  // of TransititionGeneratedToVM/Native that is part of runtime boilerplate
+  // code (see DEFINE_RUNTIME_ENTRY_IMPL in runtime_entry.h). Ffi calls don't
+  // have this boilerplate, don't have this stack resource, have to transition
+  // explicitly.
   __ cmpq(compiler::Address(
               THR, compiler::target::Thread::exit_through_ffi_offset()),
           compiler::Immediate(target::Thread::exit_through_ffi()));
   __ j(NOT_EQUAL, &exit_through_non_ffi, compiler::Assembler::kNearJump);
-  __ TransitionNativeToGenerated(/*leave_safepoint=*/true);
+  __ TransitionNativeToGenerated(/*leave_safepoint=*/true,
+                                 /*ignore_unwind_in_progress=*/true);
   __ Bind(&exit_through_non_ffi);
 
   // Set the tag.
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 00e3f9b..26514bf 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -13,6 +13,8 @@
 #include "vm/constants_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/constants_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/constants_riscv.h"
 #else
 #error Unknown architecture.
 #endif
@@ -24,13 +26,13 @@
 // We re-use registers from another ABI to avoid duplicating this ABI across 4
 // architectures.
 struct InstantiateTypeABI {
-  static const Register kTypeReg =
+  static constexpr Register kTypeReg =
       InstantiationABI::kUninstantiatedTypeArgumentsReg;
-  static const Register kInstantiatorTypeArgumentsReg =
+  static constexpr Register kInstantiatorTypeArgumentsReg =
       InstantiationABI::kInstantiatorTypeArgumentsReg;
-  static const Register kFunctionTypeArgumentsReg =
+  static constexpr Register kFunctionTypeArgumentsReg =
       InstantiationABI::kFunctionTypeArgumentsReg;
-  static const Register kResultTypeReg = InstantiationABI::kResultTypeReg;
+  static constexpr Register kResultTypeReg = InstantiationABI::kResultTypeReg;
 };
 
 class RegisterNames {
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index c774203..94b214a 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -288,6 +288,8 @@
 typedef QRegister FpuRegister;
 
 const FpuRegister FpuTMP = QTMP;
+const int kFpuRegisterSize = 16;
+typedef simd128_value_t fpu_register_t;
 const int kNumberOfFpuRegisters = kNumberOfQRegisters;
 const FpuRegister kNoFpuRegister = kNoQRegister;
 
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 7947a60..9e4213d 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -123,6 +123,8 @@
 // Architecture independent aliases.
 typedef VRegister FpuRegister;
 const FpuRegister FpuTMP = VTMP;
+const int kFpuRegisterSize = 16;
+typedef simd128_value_t fpu_register_t;
 const int kNumberOfFpuRegisters = kNumberOfVRegisters;
 const FpuRegister kNoFpuRegister = kNoVRegister;
 
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 4a497730..bac9dd5 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -61,6 +61,8 @@
 // Architecture independent aliases.
 typedef XmmRegister FpuRegister;
 const FpuRegister FpuTMP = XMM7;
+const int kFpuRegisterSize = 16;
+typedef simd128_value_t fpu_register_t;
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
diff --git a/runtime/vm/constants_riscv.cc b/runtime/vm/constants_riscv.cc
new file mode 100644
index 0000000..6f694e9
--- /dev/null
+++ b/runtime/vm/constants_riscv.cc
@@ -0,0 +1,43 @@
+// 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.
+
+#include "platform/globals.h"  // NOLINT
+
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/constants.h"  // NOLINT
+
+namespace dart {
+
+#if !defined(FFI_UNIT_TESTS)
+DEFINE_FLAG(bool,
+            use_compressed_instructions,
+            true,
+            "Use instructions from the C extension");
+#endif
+
+const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
+    "zero", "ra", "sp",  "gp",   "tp",   "t0",   "t1", "t2", "fp", "thr", "a0",
+    "a1",   "a2", "tmp", "tmp2", "pp",   "a6",   "a7", "s2", "s3", "s4",  "s5",
+    "s6",   "s7", "s8",  "s9",   "null", "mask", "t3", "t4", "t5", "t6",
+};
+
+const char* const fpu_reg_names[kNumberOfFpuRegisters] = {
+    "ft0", "ft1", "ft2",  "ft3",  "ft4", "ft5", "ft6",  "ft7",
+    "fs0", "fs1", "fa0",  "fa1",  "fa2", "fa3", "fa4",  "fa5",
+    "fa6", "fa7", "fs2",  "fs3",  "fs4", "fs5", "fs6",  "fs7",
+    "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
+};
+
+const Register CallingConventions::ArgumentRegisters[] = {
+    A0, A1, A2, A3, A4, A5, A6, A7,
+};
+
+const FpuRegister CallingConventions::FpuArgumentRegisters[] = {
+    FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7,
+};
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
new file mode 100644
index 0000000..d04317b
--- /dev/null
+++ b/runtime/vm/constants_riscv.h
@@ -0,0 +1,1422 @@
+// 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.
+
+#ifndef RUNTIME_VM_CONSTANTS_RISCV_H_
+#define RUNTIME_VM_CONSTANTS_RISCV_H_
+
+#ifndef RUNTIME_VM_CONSTANTS_H_
+#error Do not include constants_riscv.h directly; use constants.h instead.
+#endif
+
+#include <sstream>
+
+#include "platform/assert.h"
+#include "platform/globals.h"
+#include "platform/utils.h"
+
+#include "vm/constants_base.h"
+#include "vm/flags.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, use_compressed_instructions);
+
+#if defined(TARGET_ARCH_RISCV32)
+typedef uint32_t uintx_t;
+typedef int32_t intx_t;
+constexpr intx_t kMaxIntX = kMaxInt32;
+constexpr uintx_t kMaxUIntX = kMaxUint32;
+constexpr intx_t kMinIntX = kMinInt32;
+#define XLEN 32
+#elif defined(TARGET_ARCH_RISCV64)
+typedef uint64_t uintx_t;
+typedef int64_t intx_t;
+constexpr intx_t kMaxIntX = kMaxInt64;
+constexpr uintx_t kMaxUIntX = kMaxUint64;
+constexpr intx_t kMinIntX = kMinInt64;
+#define XLEN 64
+#else
+#error What XLEN?
+#endif
+
+enum Register {
+  // The correct name for this register is ZERO, but this conflicts with other
+  // globals.
+  ZR = 0,
+  RA = 1,
+  SP = 2,
+  GP = 3,
+  TP = 4,
+  T0 = 5,
+  T1 = 6,
+  T2 = 7,
+  FP = 8,
+  S1 = 9,  // THR
+  A0 = 10,
+  A1 = 11,
+  A2 = 12,  // CODE_REG
+  A3 = 13,  // TMP
+  A4 = 14,  // TMP2
+  A5 = 15,  // PP, untagged
+  A6 = 16,
+  A7 = 17,
+  S2 = 18,
+  S3 = 19,
+  S4 = 20,  // ARGS_DESC_REG
+  S5 = 21,  // IC_DATA_REG
+  S6 = 22,
+  S7 = 23,   // CALLEE_SAVED_TEMP2
+  S8 = 24,   // CALLEE_SAVED_TEMP / FAR_TMP
+  S9 = 25,   // DISPATCH_TABLE_REG
+  S10 = 26,  // NULL
+  S11 = 27,  // WRITE_BARRIER_MASK
+  T3 = 28,
+  T4 = 29,
+  T5 = 30,
+  T6 = 31,
+  kNumberOfCpuRegisters = 32,
+  kNoRegister = -1,
+
+  RA2 = T0,
+  S0 = FP,
+
+  // Note that some compressed instructions can only take registers x8-x15 for
+  // some of their operands, so to reduce code size we assign the most popular
+  // uses to these registers.
+
+  // If the base register of a load/store is not SP, both the base register and
+  // source/destination register must be in x8-x15 and the offset must be
+  // aligned to make use a compressed instruction. So either,
+  //   - PP, CODE_REG and IC_DATA_REG should all be assigned to x8-x15 and we
+  //     should hold PP untagged like on ARM64. This makes the loads in the call
+  //     sequence shorter, but adds extra PP tagging/untagging on entry and
+  //     return.
+  //   - PP should be assigned to a C-preserved register to avoid spilling it on
+  //     leaf runtime calls.
+};
+
+enum FRegister {
+  FT0 = 0,
+  FT1 = 1,
+  FT2 = 2,
+  FT3 = 3,
+  FT4 = 4,
+  FT5 = 5,
+  FT6 = 6,
+  FT7 = 7,
+  FS0 = 8,
+  FS1 = 9,
+  FA0 = 10,
+  FA1 = 11,
+  FA2 = 12,
+  FA3 = 13,
+  FA4 = 14,
+  FA5 = 15,
+  FA6 = 16,
+  FA7 = 17,
+  FS2 = 18,
+  FS3 = 19,
+  FS4 = 20,
+  FS5 = 21,
+  FS6 = 22,
+  FS7 = 23,
+  FS8 = 24,
+  FS9 = 25,
+  FS10 = 26,
+  FS11 = 27,
+  FT8 = 28,
+  FT9 = 29,
+  FT10 = 30,
+  FT11 = 31,
+  kNumberOfFpuRegisters = 32,
+  kNoFpuRegister = -1,
+};
+
+// Register alias for floating point scratch register.
+const FRegister FTMP = FT11;
+
+// Architecture independent aliases.
+typedef FRegister FpuRegister;
+const FpuRegister FpuTMP = FTMP;
+const int kFpuRegisterSize = 8;
+typedef double fpu_register_t;
+
+extern const char* const cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* const fpu_reg_names[kNumberOfFpuRegisters];
+
+// Register aliases.
+constexpr Register TMP = A3;  // Used as scratch register by assembler.
+constexpr Register TMP2 = A4;
+constexpr Register FAR_TMP = S8;
+constexpr Register PP = A5;  // Caches object pool pointer in generated code.
+constexpr Register DISPATCH_TABLE_REG = S9;  // Dispatch table register.
+constexpr Register CODE_REG = A2;
+constexpr Register FPREG = FP;          // Frame pointer register.
+constexpr Register SPREG = SP;          // Stack pointer register.
+constexpr Register IC_DATA_REG = S5;    // ICData/MegamorphicCache register.
+constexpr Register ARGS_DESC_REG = S4;  // Arguments descriptor register.
+constexpr Register THR = S1;  // Caches current thread in generated code.
+constexpr Register CALLEE_SAVED_TEMP = S8;
+constexpr Register CALLEE_SAVED_TEMP2 = S7;
+constexpr Register WRITE_BARRIER_MASK = S11;
+constexpr Register NULL_REG = S10;  // Caches NullObject() value.
+
+// ABI for catch-clause entry point.
+constexpr Register kExceptionObjectReg = A0;
+constexpr Register kStackTraceObjectReg = A1;
+
+// ABI for write barrier stub.
+constexpr Register kWriteBarrierObjectReg = A0;
+constexpr Register kWriteBarrierValueReg = A1;
+constexpr Register kWriteBarrierSlotReg = A6;
+
+// Common ABI for shared slow path stubs.
+struct SharedSlowPathStubABI {
+  static constexpr Register kResultReg = A0;
+};
+
+// ABI for instantiation stubs.
+struct InstantiationABI {
+  static constexpr Register kUninstantiatedTypeArgumentsReg = T1;
+  static constexpr Register kInstantiatorTypeArgumentsReg = T2;
+  static constexpr Register kFunctionTypeArgumentsReg = T3;
+  static constexpr Register kResultTypeArgumentsReg = A0;
+  static constexpr Register kResultTypeReg = A0;
+};
+
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of type testing stubs that are _not_ preserved.
+struct TTSInternalRegs {
+  static constexpr Register kInstanceTypeArgumentsReg = S2;
+  static constexpr Register kScratchReg = S3;
+  static constexpr Register kSubTypeArgumentReg = S4;
+  static constexpr Register kSuperTypeArgumentReg = S5;
+
+  // Must be pushed/popped whenever generic type arguments are being checked as
+  // they overlap with registers in TypeTestABI.
+  static constexpr intptr_t kSavedTypeArgumentRegisters = 0;
+
+  static const intptr_t kInternalRegisters =
+      ((1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg) |
+       (1 << kSubTypeArgumentReg) | (1 << kSuperTypeArgumentReg)) &
+      ~kSavedTypeArgumentRegisters;
+};
+
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of subtype test cache stubs that are _not_ preserved.
+struct STCInternalRegs {
+  static constexpr Register kInstanceCidOrSignatureReg = S2;
+  static constexpr Register kInstanceInstantiatorTypeArgumentsReg = S3;
+  static constexpr Register kInstanceParentFunctionTypeArgumentsReg = S4;
+  static constexpr Register kInstanceDelayedFunctionTypeArgumentsReg = S5;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceCidOrSignatureReg) |
+      (1 << kInstanceInstantiatorTypeArgumentsReg) |
+      (1 << kInstanceParentFunctionTypeArgumentsReg) |
+      (1 << kInstanceDelayedFunctionTypeArgumentsReg);
+};
+
+// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
+struct TypeTestABI {
+  static constexpr Register kInstanceReg = A0;
+  static constexpr Register kDstTypeReg = T1;
+  static constexpr Register kInstantiatorTypeArgumentsReg = T2;
+  static constexpr Register kFunctionTypeArgumentsReg = T3;
+  static constexpr Register kSubtypeTestCacheReg = T4;
+  static constexpr Register kScratchReg = T5;
+
+  // For calls to InstanceOfStub.
+  static constexpr Register kInstanceOfResultReg = kInstanceReg;
+  // For calls to SubtypeNTestCacheStub. Must not overlap with any other
+  // registers above, for it is also used internally as kNullReg in those stubs.
+  static constexpr Register kSubtypeTestCacheResultReg = T0;
+
+  // Registers that need saving across SubtypeTestCacheStub calls.
+  static const intptr_t kSubtypeTestCacheStubCallerSavedRegisters =
+      1 << kSubtypeTestCacheReg;
+
+  static const intptr_t kPreservedAbiRegisters =
+      (1 << kInstanceReg) | (1 << kDstTypeReg) |
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg);
+
+  static const intptr_t kNonPreservedAbiRegisters =
+      TTSInternalRegs::kInternalRegisters |
+      STCInternalRegs::kInternalRegisters | (1 << kSubtypeTestCacheReg) |
+      (1 << kScratchReg) | (1 << kSubtypeTestCacheResultReg) | (1 << CODE_REG);
+
+  static const intptr_t kAbiRegisters =
+      kPreservedAbiRegisters | kNonPreservedAbiRegisters;
+};
+
+// Calling convention when calling AssertSubtypeStub.
+struct AssertSubtypeABI {
+  static constexpr Register kSubTypeReg = T1;
+  static constexpr Register kSuperTypeReg = T2;
+  static constexpr Register kInstantiatorTypeArgumentsReg = T3;
+  static constexpr Register kFunctionTypeArgumentsReg = T4;
+  static constexpr Register kDstNameReg = T5;
+
+  static const intptr_t kAbiRegisters =
+      (1 << kSubTypeReg) | (1 << kSuperTypeReg) |
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
+      (1 << kDstNameReg);
+
+  // No result register, as AssertSubtype is only run for side effect
+  // (throws if the subtype check fails).
+};
+
+// ABI for InitStaticFieldStub.
+struct InitStaticFieldABI {
+  static constexpr Register kFieldReg = T2;
+  static constexpr Register kResultReg = A0;
+};
+
+// Registers used inside the implementation of InitLateStaticFieldStub.
+struct InitLateStaticFieldInternalRegs {
+  static const Register kFunctionReg = T0;
+  static const Register kAddressReg = T3;
+  static const Register kScratchReg = T4;
+};
+
+// ABI for InitInstanceFieldStub.
+struct InitInstanceFieldABI {
+  static constexpr Register kInstanceReg = T1;
+  static constexpr Register kFieldReg = T2;
+  static constexpr Register kResultReg = A0;
+};
+
+// Registers used inside the implementation of InitLateInstanceFieldStub.
+struct InitLateInstanceFieldInternalRegs {
+  static constexpr Register kFunctionReg =
+      T0;  // Must agreee with lazy compile stub.
+  static constexpr Register kAddressReg = T3;
+  static constexpr Register kScratchReg = T4;
+};
+
+// ABI for LateInitializationError stubs.
+struct LateInitializationErrorABI {
+  static constexpr Register kFieldReg = T2;
+};
+
+// ABI for ThrowStub.
+struct ThrowABI {
+  static constexpr Register kExceptionReg = A0;
+};
+
+// ABI for ReThrowStub.
+struct ReThrowABI {
+  static constexpr Register kExceptionReg = A0;
+  static constexpr Register kStackTraceReg = A1;
+};
+
+// ABI for AssertBooleanStub.
+struct AssertBooleanABI {
+  static constexpr Register kObjectReg = A0;
+};
+
+// ABI for RangeErrorStub.
+struct RangeErrorABI {
+  static constexpr Register kLengthReg = T1;
+  static constexpr Register kIndexReg = T2;
+};
+
+// ABI for AllocateObjectStub.
+struct AllocateObjectABI {
+  static constexpr Register kResultReg = A0;
+  static constexpr Register kTypeArgumentsReg = T1;
+};
+
+// ABI for AllocateClosureStub.
+struct AllocateClosureABI {
+  static constexpr Register kResultReg = AllocateObjectABI::kResultReg;
+  static constexpr Register kFunctionReg = T2;
+  static constexpr Register kContextReg = T3;
+  static constexpr Register kScratchReg = T4;
+};
+
+// ABI for AllocateMintShared*Stub.
+struct AllocateMintABI {
+  static constexpr Register kResultReg = AllocateObjectABI::kResultReg;
+  static constexpr Register kTempReg = T2;
+};
+
+// ABI for Allocate{Mint,Double,Float32x4,Float64x2}Stub.
+struct AllocateBoxABI {
+  static constexpr Register kResultReg = AllocateObjectABI::kResultReg;
+  static constexpr Register kTempReg = T2;
+};
+
+// ABI for AllocateArrayStub.
+struct AllocateArrayABI {
+  static constexpr Register kResultReg = AllocateObjectABI::kResultReg;
+  static constexpr Register kLengthReg = T2;
+  static constexpr Register kTypeArgumentsReg = T1;
+};
+
+// ABI for AllocateTypedDataArrayStub.
+struct AllocateTypedDataArrayABI {
+  static constexpr Register kResultReg = AllocateObjectABI::kResultReg;
+  static constexpr Register kLengthReg = T2;
+};
+
+// ABI for BoxDoubleStub.
+struct BoxDoubleStubABI {
+  static constexpr FpuRegister kValueReg = FA0;
+  static constexpr Register kTempReg = T1;
+  static constexpr Register kResultReg = A0;
+};
+
+// ABI for DoubleToIntegerStub.
+struct DoubleToIntegerStubABI {
+  static constexpr FpuRegister kInputReg = FA0;
+  static constexpr Register kRecognizedKindReg = T1;
+  static constexpr Register kResultReg = A0;
+};
+
+// ABI for DispatchTableNullErrorStub and consequently for all dispatch
+// table calls (though normal functions will not expect or use this
+// register). This ABI is added to distinguish memory corruption errors from
+// null errors.
+struct DispatchTableNullErrorABI {
+  static constexpr Register kClassIdReg = T1;
+};
+
+typedef uint32_t RegList;
+const RegList kAllCpuRegistersList = 0xFFFFFFFF;
+
+#define R(REG) (1 << REG)
+
+// C++ ABI call registers.
+
+constexpr RegList kAbiArgumentCpuRegs =
+    R(A0) | R(A1) | R(A2) | R(A3) | R(A4) | R(A5) | R(A6) | R(A7);
+constexpr RegList kAbiVolatileCpuRegs =
+    kAbiArgumentCpuRegs | R(T0) | R(T1) | R(T2) | R(T3) | R(T4) | R(T5) | R(T6);
+constexpr RegList kAbiPreservedCpuRegs = R(S1) | R(S2) | R(S3) | R(S4) | R(S5) |
+                                         R(S6) | R(S7) | R(S8) | R(S9) |
+                                         R(S10) | R(S11);
+constexpr int kAbiPreservedCpuRegCount = 11;
+constexpr intptr_t kReservedCpuRegisters =
+    R(ZR) | R(TP) | R(GP) | R(SP) | R(FP) | R(TMP) | R(TMP2) | R(PP) | R(THR) |
+    R(RA) | R(WRITE_BARRIER_MASK) | R(NULL_REG) | R(DISPATCH_TABLE_REG) |
+    R(FAR_TMP);
+constexpr intptr_t kNumberOfReservedCpuRegisters = 14;
+// CPU registers available to Dart allocator.
+constexpr RegList kDartAvailableCpuRegs =
+    kAllCpuRegistersList & ~kReservedCpuRegisters;
+constexpr int kNumberOfDartAvailableCpuRegs = 18;
+// Registers available to Dart that are not preserved by runtime calls.
+constexpr RegList kDartVolatileCpuRegs =
+    kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
+
+constexpr RegList kAbiArgumentFpuRegs =
+    R(FA0) | R(FA1) | R(FA2) | R(FA3) | R(FA4) | R(FA5) | R(FA6) | R(FA7);
+constexpr RegList kAbiVolatileFpuRegs =
+    kAbiArgumentFpuRegs | R(FT0) | R(FT1) | R(FT2) | R(FT3) | R(FT4) | R(FT5) |
+    R(FT6) | R(FT7) | R(FT8) | R(FT9) | R(FT10) | R(FT11);
+constexpr RegList kAbiPreservedFpuRegs = R(FS0) | R(FS1) | R(FS2) | R(FS3) |
+                                         R(FS4) | R(FS5) | R(FS6) | R(FS7) |
+                                         R(FS8) | R(FS9) | R(FS10) | R(FS11);
+constexpr int kAbiPreservedFpuRegCount = 12;
+constexpr intptr_t kReservedFpuRegisters = 0;
+constexpr intptr_t kNumberOfReservedFpuRegisters = 0;
+
+// Two callee save scratch registers used by leaf runtime call sequence.
+constexpr Register kCallLeafRuntimeCalleeSaveScratch1 = CALLEE_SAVED_TEMP;
+constexpr Register kCallLeafRuntimeCalleeSaveScratch2 = CALLEE_SAVED_TEMP2;
+static_assert((R(kCallLeafRuntimeCalleeSaveScratch1) & kAbiPreservedCpuRegs) !=
+                  0,
+              "Need callee save scratch register for leaf runtime calls.");
+static_assert((R(kCallLeafRuntimeCalleeSaveScratch2) & kAbiPreservedCpuRegs) !=
+                  0,
+              "Need callee save scratch register for leaf runtime calls.");
+
+constexpr int kStoreBufferWrapperSize = 26;
+
+class CallingConventions {
+ public:
+  static const intptr_t kArgumentRegisters = kAbiArgumentCpuRegs;
+  static const Register ArgumentRegisters[];
+  static const intptr_t kNumArgRegs = 8;
+  static const Register kPointerToReturnStructRegisterCall = A0;
+  static const Register kPointerToReturnStructRegisterReturn = A0;
+
+  static const FpuRegister FpuArgumentRegisters[];
+  static const intptr_t kFpuArgumentRegisters =
+      R(FA0) | R(FA1) | R(FA2) | R(FA3) | R(FA4) | R(FA5) | R(FA6) | R(FA7);
+  static const intptr_t kNumFpuArgRegs = 8;
+
+  static const bool kArgumentIntRegXorFpuReg = false;
+
+  static constexpr intptr_t kCalleeSaveCpuRegisters = kAbiPreservedCpuRegs;
+
+  // Whether larger than wordsize arguments are aligned to even registers.
+  static constexpr AlignmentStrategy kArgumentRegisterAlignment =
+      kAlignedToWordSize;
+
+  // How stack arguments are aligned.
+  static constexpr AlignmentStrategy kArgumentStackAlignment =
+      kAlignedToValueSize;
+
+  // How fields in compounds are aligned.
+  static constexpr AlignmentStrategy kFieldAlignment = kAlignedToValueSize;
+
+  // Whether 1 or 2 byte-sized arguments or return values are passed extended
+  // to 4 bytes.
+  // TODO(ffi): Need to add kExtendedToWord.
+  static constexpr ExtensionStrategy kReturnRegisterExtension = kExtendedTo4;
+  static constexpr ExtensionStrategy kArgumentRegisterExtension = kExtendedTo4;
+  static constexpr ExtensionStrategy kArgumentStackExtension = kNotExtended;
+
+  static constexpr Register kReturnReg = A0;
+  static constexpr Register kSecondReturnReg = A1;
+  static constexpr FpuRegister kReturnFpuReg = FA0;
+
+  static constexpr Register kFfiAnyNonAbiRegister = S2;  // S0=FP, S1=THR
+  static constexpr Register kFirstNonArgumentRegister = T0;
+  static constexpr Register kSecondNonArgumentRegister = T1;
+  static constexpr Register kStackPointerRegister = SPREG;
+
+  COMPILE_ASSERT(
+      ((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
+       (kArgumentRegisters | R(kPointerToReturnStructRegisterCall))) == 0);
+};
+
+// TODO(riscv): Architecture-independent parts of the compiler should use
+// compare-and-branch instead of condition codes.
+enum Condition {
+  kNoCondition = -1,
+  EQ = 0,   // equal
+  NE = 1,   // not equal
+  CS = 2,   // carry set/unsigned higher or same
+  CC = 3,   // carry clear/unsigned lower
+  MI = 4,   // minus/negative
+  PL = 5,   // plus/positive or zero
+  VS = 6,   // overflow
+  VC = 7,   // no overflow
+  HI = 8,   // unsigned higher
+  LS = 9,   // unsigned lower or same
+  GE = 10,  // signed greater than or equal
+  LT = 11,  // signed less than
+  GT = 12,  // signed greater than
+  LE = 13,  // signed less than or equal
+  AL = 14,  // always (unconditional)
+  NV = 15,  // special condition (refer to section C1.2.3)
+  kNumberOfConditions = 16,
+
+  // Platform-independent variants declared for all platforms
+  EQUAL = EQ,
+  ZERO = EQUAL,
+  NOT_EQUAL = NE,
+  NOT_ZERO = NOT_EQUAL,
+  LESS = LT,
+  LESS_EQUAL = LE,
+  GREATER_EQUAL = GE,
+  GREATER = GT,
+  UNSIGNED_LESS = CC,
+  UNSIGNED_LESS_EQUAL = LS,
+  UNSIGNED_GREATER = HI,
+  UNSIGNED_GREATER_EQUAL = CS,
+  OVERFLOW = VS,
+  NO_OVERFLOW = VC,
+
+  kInvalidCondition = 16
+};
+
+static inline Condition InvertCondition(Condition c) {
+  COMPILE_ASSERT((EQ ^ NE) == 1);
+  COMPILE_ASSERT((CS ^ CC) == 1);
+  COMPILE_ASSERT((MI ^ PL) == 1);
+  COMPILE_ASSERT((VS ^ VC) == 1);
+  COMPILE_ASSERT((HI ^ LS) == 1);
+  COMPILE_ASSERT((GE ^ LT) == 1);
+  COMPILE_ASSERT((GT ^ LE) == 1);
+  COMPILE_ASSERT((AL ^ NV) == 1);
+  ASSERT(c != AL);
+  ASSERT(c != kInvalidCondition);
+  return static_cast<Condition>(c ^ 1);
+}
+
+enum ScaleFactor {
+  TIMES_1 = 0,
+  TIMES_2 = 1,
+  TIMES_4 = 2,
+  TIMES_8 = 3,
+  TIMES_16 = 4,
+// We can't include vm/compiler/runtime_api.h, so just be explicit instead
+// of using (dart::)kWordSizeLog2.
+#if defined(TARGET_ARCH_IS_64_BIT)
+  // Used for Smi-boxed indices.
+  TIMES_HALF_WORD_SIZE = kInt64SizeLog2 - 1,
+  // Used for unboxed indices.
+  TIMES_WORD_SIZE = kInt64SizeLog2,
+#elif defined(TARGET_ARCH_IS_32_BIT)
+  // Used for Smi-boxed indices.
+  TIMES_HALF_WORD_SIZE = kInt32SizeLog2 - 1,
+  // Used for unboxed indices.
+  TIMES_WORD_SIZE = kInt32SizeLog2,
+#else
+#error "Unexpected word size"
+#endif
+#if !defined(DART_COMPRESSED_POINTERS)
+  TIMES_COMPRESSED_WORD_SIZE = TIMES_WORD_SIZE,
+#else
+  TIMES_COMPRESSED_WORD_SIZE = TIMES_HALF_WORD_SIZE,
+#endif
+};
+
+const uword kBreakInstructionFiller = 0;  // trap or c.trap
+
+inline int32_t SignExtend(int N, int32_t value) {
+  return (value << (32 - N)) >> (32 - N);
+}
+
+inline intx_t sign_extend(int32_t x) {
+  return static_cast<intx_t>(x);
+}
+inline intx_t sign_extend(int64_t x) {
+  return static_cast<intx_t>(x);
+}
+inline intx_t sign_extend(uint32_t x) {
+  return static_cast<intx_t>(static_cast<int32_t>(x));
+}
+inline intx_t sign_extend(uint64_t x) {
+  return static_cast<intx_t>(static_cast<int64_t>(x));
+}
+
+enum Opcode {
+  LUI = 0b0110111,
+  AUIPC = 0b0010111,
+  JAL = 0b1101111,
+  JALR = 0b1100111,
+  BRANCH = 0b1100011,
+  LOAD = 0b0000011,
+  STORE = 0b0100011,
+  OPIMM = 0b0010011,
+  OP = 0b0110011,
+  MISCMEM = 0b0001111,
+  SYSTEM = 0b1110011,
+  OP32 = 0b0111011,
+  OPIMM32 = 0b0011011,
+  AMO = 0b0101111,
+  LOADFP = 0b0000111,
+  STOREFP = 0b0100111,
+  FMADD = 0b1000011,
+  FMSUB = 0b1000111,
+  FNMSUB = 0b1001011,
+  FNMADD = 0b1001111,
+  OPFP = 0b1010011,
+};
+
+enum Funct12 {
+  ECALL = 0,
+  EBREAK = 1,
+};
+
+enum Funct3 {
+  F3_0 = 0,
+  F3_1 = 1,
+
+  BEQ = 0b000,
+  BNE = 0b001,
+  BLT = 0b100,
+  BGE = 0b101,
+  BLTU = 0b110,
+  BGEU = 0b111,
+
+  LB = 0b000,
+  LH = 0b001,
+  LW = 0b010,
+  LBU = 0b100,
+  LHU = 0b101,
+  LWU = 0b110,
+  LD = 0b011,
+
+  SB = 0b000,
+  SH = 0b001,
+  SW = 0b010,
+  SD = 0b011,
+
+  ADDI = 0b000,
+  SLLI = 0b001,
+  SLTI = 0b010,
+  SLTIU = 0b011,
+  XORI = 0b100,
+  SRI = 0b101,
+  ORI = 0b110,
+  ANDI = 0b111,
+
+  ADD = 0b000,
+  SLL = 0b001,
+  SLT = 0b010,
+  SLTU = 0b011,
+  XOR = 0b100,
+  SR = 0b101,
+  OR = 0b110,
+  AND = 0b111,
+
+  FENCE = 0b000,
+  FENCEI = 0b001,
+
+  CSRRW = 0b001,
+  CSRRS = 0b010,
+  CSRRC = 0b011,
+  CSRRWI = 0b101,
+  CSRRSI = 0b110,
+  CSRRCI = 0b111,
+
+  MUL = 0b000,
+  MULH = 0b001,
+  MULHSU = 0b010,
+  MULHU = 0b011,
+  DIV = 0b100,
+  DIVU = 0b101,
+  REM = 0b110,
+  REMU = 0b111,
+
+  MULW = 0b000,
+  DIVW = 0b100,
+  DIVUW = 0b101,
+  REMW = 0b110,
+  REMUW = 0b111,
+
+  WIDTH32 = 0b010,
+  WIDTH64 = 0b011,
+
+  S = 0b010,
+  D = 0b011,
+  J = 0b000,
+  JN = 0b001,
+  JX = 0b010,
+  MIN = 0b000,
+  MAX = 0b001,
+  FEQ = 0b010,
+  FLT = 0b001,
+  FLE = 0b000,
+};
+
+enum Funct7 {
+  F7_0 = 0,
+  SRA = 0b0100000,
+  SUB = 0b0100000,
+  MULDIV = 0b0000001,
+
+  FADDS = 0b0000000,
+  FSUBS = 0b0000100,
+  FMULS = 0b0001000,
+  FDIVS = 0b0001100,
+  FSQRTS = 0b0101100,
+  FSGNJS = 0b0010000,
+  FMINMAXS = 0b0010100,
+  FCMPS = 0b1010000,
+  FCLASSS = 0b1110000,
+  FCVTintS = 0b1100000,
+  FCVTSint = 0b1101000,
+  FMVXW = 0b1110000,
+  FMVWX = 0b1111000,
+
+  FADDD = 0b0000001,
+  FSUBD = 0b0000101,
+  FMULD = 0b0001001,
+  FDIVD = 0b0001101,
+  FSQRTD = 0b0101101,
+  FSGNJD = 0b0010001,
+  FMINMAXD = 0b0010101,
+  FCVTS = 0b0100000,
+  FCVTD = 0b0100001,
+  FCMPD = 0b1010001,
+  FCLASSD = 0b1110001,
+  FCVTintD = 0b1100001,
+  FCVTDint = 0b1101001,
+  FMVXD = 0b1110001,
+  FMVDX = 0b1111001,
+};
+
+enum Funct5 {
+  LR = 0b00010,
+  SC = 0b00011,
+  AMOSWAP = 0b00001,
+  AMOADD = 0b00000,
+  AMOXOR = 0b00100,
+  AMOAND = 0b01100,
+  AMOOR = 0b01000,
+  AMOMIN = 0b10000,
+  AMOMAX = 0b10100,
+  AMOMINU = 0b11000,
+  AMOMAXU = 0b11100,
+};
+
+enum Funct2 {
+  F2_S = 0b00,
+  F2_D = 0b01,
+};
+
+enum RoundingMode {
+  RNE = 0b000,  // Round to Nearest, ties to Even
+  RTZ = 0b001,  // Round toward Zero
+  RDN = 0b010,  // Round Down (toward negative infinity)
+  RUP = 0b011,  // Round Up (toward positive infinity)
+  RMM = 0b100,  // Round to nearest, ties to Max Magnitude
+  DYN = 0b111,  // Dynamic rounding mode
+};
+
+enum FcvtRs2 {
+  W = 0b00000,
+  WU = 0b00001,
+  L = 0b00010,
+  LU = 0b00011,
+};
+
+enum FClass {
+  kFClassNegInfinity = 1 << 0,
+  kFClassNegNormal = 1 << 1,
+  kFClassNegSubnormal = 1 << 2,
+  kFClassNegZero = 1 << 3,
+  kFClassPosZero = 1 << 4,
+  kFClassPosSubnormal = 1 << 5,
+  kFClassPosNormal = 1 << 6,
+  kFClassPosInfinity = 1 << 7,
+  kFClassSignallingNan = 1 << 8,
+  kFClassQuietNan = 1 << 9,
+};
+
+enum HartEffects {
+  kWrite = 1 << 0,
+  kRead = 1 << 1,
+  kOutput = 1 << 2,
+  kInput = 1 << 3,
+  kMemory = kWrite | kRead,
+  kIO = kOutput | kInput,
+  kAll = kMemory | kIO,
+};
+
+const intptr_t kReleaseShift = 25;
+const intptr_t kAcquireShift = 26;
+
+#define DEFINE_REG_ENCODING(type, name, shift)                                 \
+  inline uint32_t Is##name(type r) { return static_cast<uint32_t>(r) < 32; }   \
+  inline uint32_t Encode##name(type r) {                                       \
+    ASSERT(Is##name(r));                                                       \
+    return static_cast<uint32_t>(r) << shift;                                  \
+  }                                                                            \
+  inline type Decode##name(uint32_t encoding) {                                \
+    return type((encoding >> shift) & 31);                                     \
+  }
+
+DEFINE_REG_ENCODING(Register, Rd, 7)
+DEFINE_REG_ENCODING(Register, Rs1, 15)
+DEFINE_REG_ENCODING(Register, Rs2, 20)
+DEFINE_REG_ENCODING(FRegister, FRd, 7)
+DEFINE_REG_ENCODING(FRegister, FRs1, 15)
+DEFINE_REG_ENCODING(FRegister, FRs2, 20)
+DEFINE_REG_ENCODING(FRegister, FRs3, 27)
+#undef DEFINE_REG_ENCODING
+
+#define DEFINE_FUNCT_ENCODING(type, name, shift, mask)                         \
+  inline uint32_t Is##name(type f) { return (f & mask) == f; }                 \
+  inline uint32_t Encode##name(type f) {                                       \
+    ASSERT(Is##name(f));                                                       \
+    return f << shift;                                                         \
+  }                                                                            \
+  inline type Decode##name(uint32_t encoding) {                                \
+    return static_cast<type>((encoding >> shift) & mask);                      \
+  }
+
+DEFINE_FUNCT_ENCODING(Opcode, Opcode, 0, 0x7F)
+DEFINE_FUNCT_ENCODING(Funct2, Funct2, 25, 0x3)
+DEFINE_FUNCT_ENCODING(Funct3, Funct3, 12, 0x7)
+DEFINE_FUNCT_ENCODING(Funct5, Funct5, 27, 0x1F)
+DEFINE_FUNCT_ENCODING(Funct7, Funct7, 25, 0x7F)
+DEFINE_FUNCT_ENCODING(Funct12, Funct12, 20, 0xFFF)
+#if XLEN == 32
+DEFINE_FUNCT_ENCODING(uint32_t, Shamt, 20, 0x1F)
+#elif XLEN == 64
+DEFINE_FUNCT_ENCODING(uint32_t, Shamt, 20, 0x3F)
+#endif
+DEFINE_FUNCT_ENCODING(RoundingMode, RoundingMode, 12, 0x7)
+#undef DEFINE_FUNCT_ENCODING
+
+inline bool IsBTypeImm(intptr_t imm) {
+  return Utils::IsInt(12, imm) && Utils::IsAligned(imm, 2);
+}
+inline uint32_t EncodeBTypeImm(intptr_t imm) {
+  ASSERT(IsBTypeImm(imm));
+  uint32_t encoded = 0;
+  encoded |= ((imm >> 12) & 0x1) << 31;
+  encoded |= ((imm >> 5) & 0x3f) << 25;
+  encoded |= ((imm >> 1) & 0xf) << 8;
+  encoded |= ((imm >> 11) & 0x1) << 7;
+  return encoded;
+}
+inline intptr_t DecodeBTypeImm(uint32_t encoded) {
+  uint32_t imm = 0;
+  imm |= (((encoded >> 31) & 0x1) << 12);
+  imm |= (((encoded >> 25) & 0x3f) << 5);
+  imm |= (((encoded >> 8) & 0xf) << 1);
+  imm |= (((encoded >> 7) & 0x1) << 11);
+  return SignExtend(12, imm);
+}
+
+inline bool IsJTypeImm(intptr_t imm) {
+  return Utils::IsInt(20, imm) && Utils::IsAligned(imm, 2);
+}
+inline uint32_t EncodeJTypeImm(intptr_t imm) {
+  ASSERT(IsJTypeImm(imm));
+  uint32_t encoded = 0;
+  encoded |= ((imm >> 20) & 0x1) << 31;
+  encoded |= ((imm >> 1) & 0x3ff) << 21;
+  encoded |= ((imm >> 11) & 0x1) << 20;
+  encoded |= ((imm >> 12) & 0xff) << 12;
+  return encoded;
+}
+inline intptr_t DecodeJTypeImm(uint32_t encoded) {
+  uint32_t imm = 0;
+  imm |= (((encoded >> 31) & 0x1) << 20);
+  imm |= (((encoded >> 21) & 0x3ff) << 1);
+  imm |= (((encoded >> 20) & 0x1) << 11);
+  imm |= (((encoded >> 12) & 0xff) << 12);
+  return SignExtend(20, imm);
+}
+
+inline bool IsITypeImm(intptr_t imm) {
+  return Utils::IsInt(12, imm);
+}
+inline uint32_t EncodeITypeImm(intptr_t imm) {
+  ASSERT(IsITypeImm(imm));
+  return imm << 20;
+}
+inline intptr_t DecodeITypeImm(uint32_t encoded) {
+  return SignExtend(12, encoded >> 20);
+}
+
+inline bool IsUTypeImm(intptr_t imm) {
+  return Utils::IsInt(32, imm) && Utils::IsAligned(imm, 1 << 12);
+}
+inline uint32_t EncodeUTypeImm(intptr_t imm) {
+  ASSERT(IsUTypeImm(imm));
+  return imm;
+}
+inline intptr_t DecodeUTypeImm(uint32_t encoded) {
+  return SignExtend(32, encoded & ~((1 << 12) - 1));
+}
+
+inline bool IsSTypeImm(intptr_t imm) {
+  return Utils::IsInt(12, imm);
+}
+inline uint32_t EncodeSTypeImm(intptr_t imm) {
+  ASSERT(IsSTypeImm(imm));
+  uint32_t encoded = 0;
+  encoded |= ((imm >> 5) & 0x7f) << 25;
+  encoded |= ((imm >> 0) & 0x1f) << 7;
+  return encoded;
+}
+inline intptr_t DecodeSTypeImm(uint32_t encoded) {
+  uint32_t imm = 0;
+  imm |= (((encoded >> 25) & 0x7f) << 5);
+  imm |= (((encoded >> 7) & 0x1f) << 0);
+  return SignExtend(12, imm);
+}
+
+inline bool IsCInstruction(uint16_t parcel) {
+  return (parcel & 3) != 3;
+}
+
+class Instr {
+ public:
+  explicit Instr(uint32_t encoding) : encoding_(encoding) {}
+  uint32_t encoding() const { return encoding_; }
+
+  size_t length() const { return 4; }
+
+  Opcode opcode() const { return DecodeOpcode(encoding_); }
+
+  Register rd() const { return DecodeRd(encoding_); }
+  Register rs1() const { return DecodeRs1(encoding_); }
+  Register rs2() const { return DecodeRs2(encoding_); }
+
+  FRegister frd() const { return DecodeFRd(encoding_); }
+  FRegister frs1() const { return DecodeFRs1(encoding_); }
+  FRegister frs2() const { return DecodeFRs2(encoding_); }
+  FRegister frs3() const { return DecodeFRs3(encoding_); }
+
+  Funct2 funct2() const { return DecodeFunct2(encoding_); }
+  Funct3 funct3() const { return DecodeFunct3(encoding_); }
+  Funct5 funct5() const { return DecodeFunct5(encoding_); }
+  Funct7 funct7() const { return DecodeFunct7(encoding_); }
+  Funct12 funct12() const { return DecodeFunct12(encoding_); }
+
+  uint32_t shamt() const { return DecodeShamt(encoding_); }
+  RoundingMode rounding() const { return DecodeRoundingMode(encoding_); }
+
+  std::memory_order memory_order() const {
+    bool acquire = ((encoding_ >> kAcquireShift) & 1) != 0;
+    bool release = ((encoding_ >> kReleaseShift) & 1) != 0;
+    if (acquire && release) return std::memory_order_acq_rel;
+    if (acquire) return std::memory_order_acquire;
+    if (release) return std::memory_order_release;
+    return std::memory_order_relaxed;
+  }
+
+  intx_t itype_imm() const { return DecodeITypeImm(encoding_); }
+  intx_t stype_imm() const { return DecodeSTypeImm(encoding_); }
+  intx_t btype_imm() const { return DecodeBTypeImm(encoding_); }
+  intx_t utype_imm() const { return DecodeUTypeImm(encoding_); }
+  intx_t jtype_imm() const { return DecodeJTypeImm(encoding_); }
+
+  uint32_t csr() const { return encoding_ >> 20; }
+  uint32_t zimm() const { return rs1(); }
+
+  static const uint32_t kBreakPointInstruction = 0;
+  static const uint32_t kInstrSize = 4;
+  static const uint32_t kSimulatorRedirectInstruction = ECALL << 20 | SYSTEM;
+
+ private:
+  const uint32_t encoding_;
+};
+
+#define DEFINE_REG_ENCODING(type, name, shift)                                 \
+  inline uint32_t Is##name(type r) { return static_cast<uint32_t>(r) < 32; }   \
+  inline uint32_t Encode##name(type r) {                                       \
+    ASSERT(Is##name(r));                                                       \
+    return static_cast<uint32_t>(r) << shift;                                  \
+  }                                                                            \
+  inline type Decode##name(uint32_t encoding) {                                \
+    return type((encoding >> shift) & 31);                                     \
+  }
+
+#define DEFINE_REG_PRIME_ENCODING(type, name, shift)                           \
+  inline uint32_t Is##name(type r) { return (r >= 8) && (r < 16); }            \
+  inline uint32_t Encode##name(type r) {                                       \
+    ASSERT(Is##name(r));                                                       \
+    return (static_cast<uint32_t>(r) & 7) << shift;                            \
+  }                                                                            \
+  inline type Decode##name(uint32_t encoding) {                                \
+    return type(((encoding >> shift) & 7) + 8);                                \
+  }
+
+DEFINE_REG_ENCODING(Register, CRd, 7)
+DEFINE_REG_ENCODING(Register, CRs1, 7)
+DEFINE_REG_ENCODING(Register, CRs2, 2)
+DEFINE_REG_ENCODING(FRegister, CFRd, 7)
+DEFINE_REG_ENCODING(FRegister, CFRs1, 7)
+DEFINE_REG_ENCODING(FRegister, CFRs2, 2)
+DEFINE_REG_PRIME_ENCODING(Register, CRdp, 2)
+DEFINE_REG_PRIME_ENCODING(Register, CRs1p, 7)
+DEFINE_REG_PRIME_ENCODING(Register, CRs2p, 2)
+DEFINE_REG_PRIME_ENCODING(FRegister, CFRdp, 2)
+DEFINE_REG_PRIME_ENCODING(FRegister, CFRs1p, 7)
+DEFINE_REG_PRIME_ENCODING(FRegister, CFRs2p, 2)
+#undef DEFINE_REG_ENCODING
+#undef DEFINE_REG_PRIME_ENCODING
+
+inline bool IsCSPLoad4Imm(intptr_t imm) {
+  return Utils::IsUint(8, imm) && Utils::IsAligned(imm, 4);
+}
+inline uint32_t EncodeCSPLoad4Imm(intptr_t imm) {
+  ASSERT(IsCSPLoad4Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 5) & 0x1) << 12;
+  encoding |= ((imm >> 2) & 0x7) << 4;
+  encoding |= ((imm >> 6) & 0x3) << 2;
+  return encoding;
+}
+inline intx_t DecodeCSPLoad4Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 5;
+  imm |= ((encoding >> 4) & 0x7) << 2;
+  imm |= ((encoding >> 2) & 0x3) << 6;
+  return imm;
+}
+
+inline bool IsCSPLoad8Imm(intptr_t imm) {
+  return Utils::IsUint(9, imm) && Utils::IsAligned(imm, 8);
+}
+inline uint32_t EncodeCSPLoad8Imm(intptr_t imm) {
+  ASSERT(IsCSPLoad8Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 5) & 0x1) << 12;
+  encoding |= ((imm >> 3) & 0x3) << 5;
+  encoding |= ((imm >> 6) & 0x7) << 2;
+  return encoding;
+}
+inline intx_t DecodeCSPLoad8Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 5;
+  imm |= ((encoding >> 5) & 0x3) << 3;
+  imm |= ((encoding >> 2) & 0x7) << 6;
+  return imm;
+}
+
+inline bool IsCSPStore4Imm(intptr_t imm) {
+  return Utils::IsUint(8, imm) && Utils::IsAligned(imm, 4);
+}
+inline uint32_t EncodeCSPStore4Imm(intptr_t imm) {
+  ASSERT(IsCSPStore4Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 2) & 0xF) << 9;
+  encoding |= ((imm >> 6) & 0x3) << 7;
+  return encoding;
+}
+inline intx_t DecodeCSPStore4Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 9) & 0xF) << 2;
+  imm |= ((encoding >> 7) & 0x3) << 6;
+  return imm;
+}
+
+inline bool IsCSPStore8Imm(intptr_t imm) {
+  return Utils::IsUint(9, imm) && Utils::IsAligned(imm, 8);
+}
+inline uint32_t EncodeCSPStore8Imm(intptr_t imm) {
+  ASSERT(IsCSPStore8Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 3) & 0x7) << 10;
+  encoding |= ((imm >> 6) & 0x7) << 7;
+  return encoding;
+}
+inline intx_t DecodeCSPStore8Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 10) & 0x7) << 3;
+  imm |= ((encoding >> 7) & 0x7) << 6;
+  return imm;
+}
+
+inline bool IsCMem4Imm(intptr_t imm) {
+  return Utils::IsUint(7, imm) && Utils::IsAligned(imm, 4);
+}
+inline uint32_t EncodeCMem4Imm(intptr_t imm) {
+  ASSERT(IsCMem4Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 3) & 0x7) << 10;
+  encoding |= ((imm >> 2) & 0x1) << 6;
+  encoding |= ((imm >> 6) & 0x1) << 5;
+  return encoding;
+}
+inline intx_t DecodeCMem4Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 10) & 0x7) << 3;
+  imm |= ((encoding >> 6) & 0x1) << 2;
+  imm |= ((encoding >> 5) & 0x1) << 6;
+  return imm;
+}
+
+inline bool IsCMem8Imm(intptr_t imm) {
+  return Utils::IsUint(8, imm) && Utils::IsAligned(imm, 8);
+}
+inline uint32_t EncodeCMem8Imm(intptr_t imm) {
+  ASSERT(IsCMem8Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 3) & 0x7) << 10;
+  encoding |= ((imm >> 6) & 0x3) << 5;
+  return encoding;
+}
+inline intx_t DecodeCMem8Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 10) & 0x7) << 3;
+  imm |= ((encoding >> 5) & 0x3) << 6;
+  return imm;
+}
+
+inline bool IsCJImm(intptr_t imm) {
+  return Utils::IsInt(11, imm) && Utils::IsAligned(imm, 2);
+}
+inline uint32_t EncodeCJImm(intptr_t imm) {
+  ASSERT(IsCJImm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 11) & 0x1) << 12;
+  encoding |= ((imm >> 4) & 0x1) << 11;
+  encoding |= ((imm >> 8) & 0x3) << 9;
+  encoding |= ((imm >> 10) & 0x1) << 8;
+  encoding |= ((imm >> 6) & 0x1) << 7;
+  encoding |= ((imm >> 7) & 0x1) << 6;
+  encoding |= ((imm >> 1) & 0x7) << 3;
+  encoding |= ((imm >> 5) & 0x1) << 2;
+  return encoding;
+}
+inline intx_t DecodeCJImm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 11;
+  imm |= ((encoding >> 11) & 0x1) << 4;
+  imm |= ((encoding >> 9) & 0x3) << 8;
+  imm |= ((encoding >> 8) & 0x1) << 10;
+  imm |= ((encoding >> 7) & 0x1) << 6;
+  imm |= ((encoding >> 6) & 0x1) << 7;
+  imm |= ((encoding >> 3) & 0x7) << 1;
+  imm |= ((encoding >> 2) & 0x1) << 5;
+  return SignExtend(11, imm);
+}
+
+inline bool IsCBImm(intptr_t imm) {
+  return Utils::IsInt(8, imm) && Utils::IsAligned(imm, 2);
+}
+inline uint32_t EncodeCBImm(intptr_t imm) {
+  ASSERT(IsCBImm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 8) & 0x1) << 12;
+  encoding |= ((imm >> 3) & 0x3) << 10;
+  encoding |= ((imm >> 6) & 0x3) << 5;
+  encoding |= ((imm >> 1) & 0x3) << 3;
+  encoding |= ((imm >> 5) & 0x1) << 2;
+  return encoding;
+}
+inline intx_t DecodeCBImm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 8;
+  imm |= ((encoding >> 10) & 0x3) << 3;
+  imm |= ((encoding >> 5) & 0x3) << 6;
+  imm |= ((encoding >> 3) & 0x3) << 1;
+  imm |= ((encoding >> 2) & 0x1) << 5;
+  return SignExtend(8, imm);
+}
+
+inline bool IsCIImm(intptr_t imm) {
+  return Utils::IsInt(6, imm) && Utils::IsAligned(imm, 1);
+}
+inline uint32_t EncodeCIImm(intptr_t imm) {
+  ASSERT(IsCIImm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 5) & 0x1) << 12;
+  encoding |= ((imm >> 0) & 0x1F) << 2;
+  return encoding;
+}
+inline intx_t DecodeCIImm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 5;
+  imm |= ((encoding >> 2) & 0x1F) << 0;
+  return SignExtend(6, imm);
+}
+
+inline bool IsCUImm(intptr_t imm) {
+  return Utils::IsInt(17, imm) && Utils::IsAligned(imm, 1 << 12);
+}
+inline uint32_t EncodeCUImm(intptr_t imm) {
+  ASSERT(IsCUImm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 17) & 0x1) << 12;
+  encoding |= ((imm >> 12) & 0x1F) << 2;
+  return encoding;
+}
+inline intx_t DecodeCUImm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 17;
+  imm |= ((encoding >> 2) & 0x1F) << 12;
+  return SignExtend(17, imm);
+}
+
+inline bool IsCI16Imm(intptr_t imm) {
+  return Utils::IsInt(10, imm) && Utils::IsAligned(imm, 16);
+}
+inline uint32_t EncodeCI16Imm(intptr_t imm) {
+  ASSERT(IsCI16Imm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 9) & 0x1) << 12;
+  encoding |= ((imm >> 4) & 0x1) << 6;
+  encoding |= ((imm >> 6) & 0x1) << 5;
+  encoding |= ((imm >> 7) & 0x3) << 3;
+  encoding |= ((imm >> 5) & 0x1) << 2;
+  return encoding;
+}
+inline intx_t DecodeCI16Imm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 12) & 0x1) << 9;
+  imm |= ((encoding >> 6) & 0x1) << 4;
+  imm |= ((encoding >> 5) & 0x1) << 6;
+  imm |= ((encoding >> 3) & 0x3) << 7;
+  imm |= ((encoding >> 2) & 0x1) << 5;
+  return SignExtend(10, imm);
+}
+
+inline bool IsCI4SPNImm(intptr_t imm) {
+  return Utils::IsUint(9, imm) && Utils::IsAligned(imm, 4);
+}
+inline uint32_t EncodeCI4SPNImm(intptr_t imm) {
+  ASSERT(IsCI4SPNImm(imm));
+  uint32_t encoding = 0;
+  encoding |= ((imm >> 4) & 0x3) << 11;
+  encoding |= ((imm >> 6) & 0xF) << 7;
+  encoding |= ((imm >> 2) & 0x1) << 6;
+  encoding |= ((imm >> 3) & 0x1) << 5;
+  return encoding;
+}
+inline intx_t DecodeCI4SPNImm(uint32_t encoding) {
+  uint32_t imm = 0;
+  imm |= ((encoding >> 11) & 0x3) << 4;
+  imm |= ((encoding >> 7) & 0xF) << 6;
+  imm |= ((encoding >> 6) & 0x1) << 2;
+  imm |= ((encoding >> 5) & 0x1) << 3;
+  return imm;
+}
+
+enum COpcode {
+  C_OP_MASK = 0b1110000000000011,
+
+  C_ADDI4SPN = 0b0000000000000000,
+  C_FLD = 0b0010000000000000,
+  C_LW = 0b0100000000000000,
+  C_FLW = 0b0110000000000000,
+  C_LD = 0b0110000000000000,
+  C_FSD = 0b1010000000000000,
+  C_SW = 0b1100000000000000,
+  C_FSW = 0b1110000000000000,
+  C_SD = 0b1110000000000000,
+
+  C_ADDI = 0b0000000000000001,
+  C_JAL = 0b0010000000000001,
+  C_ADDIW = 0b0010000000000001,
+  C_LI = 0b0100000000000001,
+  C_ADDI16SP = 0b0110000000000001,
+  C_LUI = 0b0110000000000001,
+
+  C_MISCALU = 0b1000000000000001,
+  C_MISCALU_MASK = 0b1110110000000011,
+  C_SRLI = 0b1000000000000001,
+  C_SRAI = 0b1000010000000001,
+  C_ANDI = 0b1000100000000001,
+  C_RR = 0b1000110000000001,
+  C_RR_MASK = 0b1111110001100011,
+  C_SUB = 0b1000110000000001,
+  C_XOR = 0b1000110000100001,
+  C_OR = 0b1000110001000001,
+  C_AND = 0b1000110001100001,
+  C_SUBW = 0b1001110000000001,
+  C_ADDW = 0b1001110000100001,
+
+  C_J = 0b1010000000000001,
+  C_BEQZ = 0b1100000000000001,
+  C_BNEZ = 0b1110000000000001,
+
+  C_SLLI = 0b0000000000000010,
+  C_FLDSP = 0b0010000000000010,
+  C_LWSP = 0b0100000000000010,
+  C_FLWSP = 0b0110000000000010,
+  C_LDSP = 0b0110000000000010,
+  C_JR = 0b1000000000000010,
+  C_MV = 0b1000000000000010,
+  C_JALR = 0b1001000000000010,
+  C_ADD = 0b1001000000000010,
+  C_FSDSP = 0b1010000000000010,
+  C_SWSP = 0b1100000000000010,
+  C_FSWSP = 0b1110000000000010,
+  C_SDSP = 0b1110000000000010,
+
+  C_NOP = 0b0000000000000001,
+  C_EBREAK = 0b1001000000000010,
+};
+
+class CInstr {
+ public:
+  explicit CInstr(uint16_t encoding) : encoding_(encoding) {}
+  uint16_t encoding() const { return encoding_; }
+
+  static const uint32_t kInstrSize = 2;
+  size_t length() const { return kInstrSize; }
+
+  COpcode opcode() const { return COpcode(encoding_ & C_OP_MASK); }
+
+  Register rd() const { return DecodeCRd(encoding_); }
+  Register rs1() const { return DecodeCRd(encoding_); }
+  Register rs2() const { return DecodeCRs2(encoding_); }
+  Register rdp() const { return DecodeCRdp(encoding_); }
+  Register rs1p() const { return DecodeCRs1p(encoding_); }
+  Register rs2p() const { return DecodeCRs2p(encoding_); }
+  FRegister frd() const { return DecodeCFRd(encoding_); }
+  FRegister frs1() const { return DecodeCFRd(encoding_); }
+  FRegister frs2() const { return DecodeCFRs2(encoding_); }
+  FRegister frdp() const { return DecodeCFRdp(encoding_); }
+  FRegister frs1p() const { return DecodeCFRs1p(encoding_); }
+  FRegister frs2p() const { return DecodeCFRs2p(encoding_); }
+
+  intx_t spload4_imm() { return DecodeCSPLoad4Imm(encoding_); }
+  intx_t spload8_imm() { return DecodeCSPLoad8Imm(encoding_); }
+  intx_t spstore4_imm() { return DecodeCSPStore4Imm(encoding_); }
+  intx_t spstore8_imm() { return DecodeCSPStore8Imm(encoding_); }
+  intx_t mem4_imm() { return DecodeCMem4Imm(encoding_); }
+  intx_t mem8_imm() { return DecodeCMem8Imm(encoding_); }
+  intx_t j_imm() { return DecodeCJImm(encoding_); }
+  intx_t b_imm() { return DecodeCBImm(encoding_); }
+  intx_t i_imm() { return DecodeCIImm(encoding_); }
+  intx_t u_imm() { return DecodeCUImm(encoding_); }
+  intx_t i16_imm() { return DecodeCI16Imm(encoding_); }
+  intx_t i4spn_imm() { return DecodeCI4SPNImm(encoding_); }
+
+ private:
+  const uint16_t encoding_;
+};
+
+#define DEFINE_TYPED_ENUM_SET(name, storage_t)                                 \
+  class name##Set;                                                             \
+  class name {                                                                 \
+   public:                                                                     \
+    constexpr explicit name(storage_t encoding) : encoding_(encoding) {}       \
+    constexpr storage_t encoding() const { return encoding_; }                 \
+    constexpr bool operator==(const name& other) const {                       \
+      return encoding_ == other.encoding_;                                     \
+    }                                                                          \
+    constexpr bool operator!=(const name& other) const {                       \
+      return encoding_ != other.encoding_;                                     \
+    }                                                                          \
+    inline constexpr name##Set operator|(const name& other) const;             \
+    inline constexpr name##Set operator|(const name##Set& other) const;        \
+                                                                               \
+   private:                                                                    \
+    const storage_t encoding_;                                                 \
+  };                                                                           \
+  inline std::ostream& operator<<(std::ostream& stream, const name& element) { \
+    return stream << #name << "(" << element.encoding() << ")";                \
+  }                                                                            \
+  class name##Set {                                                            \
+   public:                                                                     \
+    constexpr /* implicit */ name##Set(name element)                           \
+        : encoding_(1u << element.encoding()) {}                               \
+    constexpr explicit name##Set(storage_t encoding) : encoding_(encoding) {}  \
+    constexpr static name##Set Empty() { return name##Set(0); }                \
+    constexpr bool Includes(const name r) const {                              \
+      return (encoding_ & (1 << r.encoding())) != 0;                           \
+    }                                                                          \
+    constexpr bool IncludesAll(const name##Set other) const {                  \
+      return (encoding_ & other.encoding_) == other.encoding_;                 \
+    }                                                                          \
+    constexpr bool IsEmpty() const { return encoding_ == 0; }                  \
+    constexpr bool operator==(const name##Set& other) const {                  \
+      return encoding_ == other.encoding_;                                     \
+    }                                                                          \
+    constexpr bool operator!=(const name##Set& other) const {                  \
+      return encoding_ != other.encoding_;                                     \
+    }                                                                          \
+    constexpr name##Set operator|(const name& other) const {                   \
+      return name##Set(encoding_ | (1 << other.encoding()));                   \
+    }                                                                          \
+    constexpr name##Set operator|(const name##Set& other) const {              \
+      return name##Set(encoding_ | other.encoding_);                           \
+    }                                                                          \
+    constexpr name##Set operator&(const name##Set& other) const {              \
+      return name##Set(encoding_ & other.encoding_);                           \
+    }                                                                          \
+                                                                               \
+   private:                                                                    \
+    storage_t encoding_;                                                       \
+  };                                                                           \
+  constexpr name##Set name::operator|(const name& other) const {               \
+    return name##Set((1u << encoding_) | (1u << other.encoding_));             \
+  }                                                                            \
+  constexpr name##Set name::operator|(const name##Set& other) const {          \
+    return other | *this;                                                      \
+  }
+
+DEFINE_TYPED_ENUM_SET(Extension, uint32_t)
+static constexpr Extension RV_I(0);  // Integer base
+static constexpr Extension RV_M(1);  // Multiply/divide
+static constexpr Extension RV_A(2);  // Atomic
+static constexpr Extension RV_F(3);  // Single-precision floating point
+static constexpr Extension RV_D(4);  // Double-precision floating point
+static constexpr Extension RV_C(5);  // Compressed instructions
+static constexpr ExtensionSet RV_G = RV_I | RV_M | RV_A | RV_F | RV_D;
+static constexpr ExtensionSet RV_GC = RV_G | RV_C;
+
+#undef R
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_CONSTANTS_RISCV_H_
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 3e7f3c5..2bc9444 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -93,6 +93,8 @@
 // Architecture independent aliases.
 typedef XmmRegister FpuRegister;
 const FpuRegister FpuTMP = XMM15;
+const int kFpuRegisterSize = 16;
+typedef simd128_value_t fpu_register_t;
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
diff --git a/runtime/vm/cpu.h b/runtime/vm/cpu.h
index 2713cab..bc57030 100644
--- a/runtime/vm/cpu.h
+++ b/runtime/vm/cpu.h
@@ -30,6 +30,8 @@
 #include "vm/cpu_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/cpu_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/cpu_riscv.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/cpu_riscv.cc b/runtime/vm/cpu_riscv.cc
new file mode 100644
index 0000000..9d61655
--- /dev/null
+++ b/runtime/vm/cpu_riscv.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/cpu.h"
+#include "vm/cpu_riscv.h"
+
+#include "vm/cpuinfo.h"
+#include "vm/simulator.h"
+
+#if !defined(USING_SIMULATOR)
+#if !defined(DART_HOST_OS_FUCHSIA)
+#include <sys/syscall.h>
+#else
+#include <zircon/syscalls.h>
+#endif
+#include <unistd.h>
+#endif
+
+#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
+#include <libkern/OSCacheControl.h>
+#endif
+
+namespace dart {
+
+void CPU::FlushICache(uword start, uword size) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#elif !defined(USING_SIMULATOR)
+  // Nothing to do. Flushing no instructions.
+  if (size == 0) {
+    return;
+  }
+
+// ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
+//
+// https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code
+//
+// On iOS we use sys_icache_invalidate from Darwin. See:
+//
+// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
+#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
+  sys_icache_invalidate(reinterpret_cast<void*>(start), size);
+#elif defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
+  char* beg = reinterpret_cast<char*>(start);
+  char* end = reinterpret_cast<char*>(start + size);
+  __builtin___clear_cache(beg, end);
+#elif defined(DART_HOST_OS_FUCHSIA)
+  zx_status_t result = zx_cache_flush(reinterpret_cast<const void*>(start),
+                                      size, ZX_CACHE_FLUSH_INSN);
+  ASSERT(result == ZX_OK);
+#else
+#error FlushICache not implemented for this OS
+#endif
+
+#endif
+}
+
+const char* CPU::Id() {
+  return
+#if defined(USING_SIMULATOR)
+      "sim"
+#endif  // !defined(USING_SIMULATOR)
+#if defined(TARGET_ARCH_RISCV32)
+      "riscv32";
+#elif defined(TARGET_ARCH_RISCV64)
+      "riscv64";
+#else
+#error What XLEN?
+#endif
+}
+
+const char* HostCPUFeatures::hardware_ = NULL;
+#if defined(DEBUG)
+bool HostCPUFeatures::initialized_ = false;
+#endif
+
+#if !defined(USING_SIMULATOR)
+void HostCPUFeatures::Init() {
+  CpuInfo::Init();
+  hardware_ = CpuInfo::GetCpuModel();
+#if defined(DEBUG)
+  initialized_ = true;
+#endif
+}
+
+void HostCPUFeatures::Cleanup() {
+  DEBUG_ASSERT(initialized_);
+#if defined(DEBUG)
+  initialized_ = false;
+#endif
+  ASSERT(hardware_ != NULL);
+  free(const_cast<char*>(hardware_));
+  hardware_ = NULL;
+  CpuInfo::Cleanup();
+}
+
+#else  // !defined(USING_SIMULATOR)
+
+void HostCPUFeatures::Init() {
+  CpuInfo::Init();
+  hardware_ = CpuInfo::GetCpuModel();
+#if defined(DEBUG)
+  initialized_ = true;
+#endif
+}
+
+void HostCPUFeatures::Cleanup() {
+  DEBUG_ASSERT(initialized_);
+#if defined(DEBUG)
+  initialized_ = false;
+#endif
+  ASSERT(hardware_ != NULL);
+  free(const_cast<char*>(hardware_));
+  hardware_ = NULL;
+  CpuInfo::Cleanup();
+}
+#endif  // !defined(USING_SIMULATOR)
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/cpu_riscv.h b/runtime/vm/cpu_riscv.h
new file mode 100644
index 0000000..f891a12
--- /dev/null
+++ b/runtime/vm/cpu_riscv.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_CPU_RISCV_H_
+#define RUNTIME_VM_CPU_RISCV_H_
+
+#if !defined(RUNTIME_VM_CPU_H_)
+#error Do not include cpu_riscv.h directly; use cpu.h instead.
+#endif
+
+#include "vm/allocation.h"
+#include "vm/simulator.h"
+
+namespace dart {
+
+// TargetCPUFeatures gives CPU features for the architecture that we are
+// generating code for. HostCPUFeatures gives the CPU features for the
+// architecture that we are actually running on. When the architectures
+// are the same, TargetCPUFeatures will query HostCPUFeatures. When they are
+// different (i.e. we are running in a simulator), HostCPUFeatures will
+// additionally mock the options needed for the target architecture so that
+// they may be altered for testing.
+
+class HostCPUFeatures : public AllStatic {
+ public:
+  static void Init();
+  static void Cleanup();
+  static const char* hardware() {
+    DEBUG_ASSERT(initialized_);
+    return hardware_;
+  }
+
+ private:
+  static const char* hardware_;
+#if defined(DEBUG)
+  static bool initialized_;
+#endif
+};
+
+class TargetCPUFeatures : public AllStatic {
+ public:
+  static void Init() { HostCPUFeatures::Init(); }
+  static void Cleanup() { HostCPUFeatures::Cleanup(); }
+  static const char* hardware() { return HostCPUFeatures::hardware(); }
+  static bool double_truncate_round_supported() { return false; }
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_CPU_RISCV_H_
diff --git a/runtime/vm/cpu_test.cc b/runtime/vm/cpu_test.cc
index d902713..5e59d31 100644
--- a/runtime/vm/cpu_test.cc
+++ b/runtime/vm/cpu_test.cc
@@ -26,6 +26,18 @@
 #else   // defined(HOST_ARCH_ARM64)
   EXPECT_STREQ("simarm64", CPU::Id());
 #endif  // defined(HOST_ARCH_ARM64)
+#elif defined(TARGET_ARCH_RISCV32)
+#if defined(HOST_ARCH_RISCV32)
+  EXPECT_STREQ("riscv32", CPU::Id());
+#else   // defined(HOST_ARCH_RISCV32)
+  EXPECT_STREQ("simriscv32", CPU::Id());
+#endif  // defined(HOST_ARCH_RISCV32)
+#elif defined(TARGET_ARCH_RISCV64)
+#if defined(HOST_ARCH_RISCV64)
+  EXPECT_STREQ("riscv64", CPU::Id());
+#else   // defined(HOST_ARCH_RISCV64)
+  EXPECT_STREQ("simriscv64", CPU::Id());
+#endif  // defined(HOST_ARCH_RISCV64)
 #else
 #error Architecture was not detected as supported by Dart.
 #endif
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index bd900ff..4634057 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -29,6 +29,9 @@
   // Use system calls.
   kCpuInfoSystem,
 
+  // Don't query anything.
+  kCpuInfoNone,
+
   // Use whatever the default is for a particular OS:
   // Linux, Windows -> CpuId,
   // Android, MacOS -> System.
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index 08621ed..27cc16e 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -45,6 +45,10 @@
   fields_[kCpuInfoArchitecture] = "CPU architecture";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::Init();
+#elif defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
+  // We only rely on the base Linux configuration of IMAFDC, so don't need
+  // dynamic feature detection.
+  method_ = kCpuInfoNone;
 #else
 #error Unrecognized target architecture
 #endif
@@ -53,9 +57,10 @@
 void CpuInfo::Cleanup() {
   if (method_ == kCpuInfoCpuId) {
     CpuId::Cleanup();
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
+  } else if (method_ == kCpuInfoSystem) {
     ProcCpuInfo::Cleanup();
+  } else {
+    ASSERT(method_ == kCpuInfoNone);
   }
 }
 
@@ -65,18 +70,20 @@
     bool contains = (strstr(field, search_string) != NULL);
     free(const_cast<char*>(field));
     return contains;
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
+  } else if (method_ == kCpuInfoSystem) {
     return ProcCpuInfo::FieldContains(FieldName(idx), search_string);
+  } else {
+    UNREACHABLE();
   }
 }
 
 const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
   if (method_ == kCpuInfoCpuId) {
     return CpuId::field(idx);
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
+  } else if (method_ == kCpuInfoSystem) {
     return ProcCpuInfo::ExtractField(FieldName(idx));
+  } else {
+    UNREACHABLE();
   }
 }
 
@@ -86,9 +93,12 @@
            (strcmp(field, fields_[kCpuInfoModel]) == 0) ||
            (strcmp(field, fields_[kCpuInfoHardware]) == 0) ||
            (strcmp(field, fields_[kCpuInfoFeatures]) == 0);
-  } else {
-    ASSERT(method_ == kCpuInfoSystem);
+  } else if (method_ == kCpuInfoSystem) {
     return ProcCpuInfo::HasField(field);
+  } else if (method_ == kCpuInfoNone) {
+    return false;
+  } else {
+    UNREACHABLE();
   }
 }
 
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 21fbaec..278039a 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -306,7 +306,6 @@
 VM_UNIT_TEST_CASE(CustomIsolates) {
   bool saved_flag = FLAG_trace_shutdown;
   FLAG_trace_shutdown = true;
-  FLAG_verify_handles = true;
   event_queue = new EventQueue();
 
   Dart_Isolate dart_isolate = TestCase::CreateTestIsolate();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 9f78ed8..e4e2869 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -7,7 +7,6 @@
 
 #include "vm/dart.h"
 
-#include "platform/thread_sanitizer.h"
 #include "vm/app_snapshot.h"
 #include "vm/code_observers.h"
 #include "vm/compiler/runtime_offsets_extracted.h"
@@ -51,19 +50,10 @@
 #include "vm/virtual_memory.h"
 #include "vm/zone.h"
 
-#if defined(USING_THREAD_SANITIZER)
-// TODO(https://github.com/dart-lang/sdk/issues/46699): Remove.
-// TODO(https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=83298): Remove.
-#include "unicode/uchar.h"
-#include "unicode/uniset.h"
-#endif
-
 namespace dart {
 
 DECLARE_FLAG(bool, print_class_table);
-DEFINE_FLAG(bool, keep_code, false, "Keep deoptimized code for profiling.");
 DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
-DECLARE_FLAG(bool, strong);
 
 Isolate* Dart::vm_isolate_ = NULL;
 int64_t Dart::start_time_micros_ = 0;
@@ -71,6 +61,7 @@
 DebugInfo* Dart::pprof_symbol_generator_ = NULL;
 ReadOnlyHandles* Dart::predefined_handles_ = NULL;
 Snapshot::Kind Dart::vm_snapshot_kind_ = Snapshot::kInvalid;
+Dart_ThreadStartCallback Dart::thread_start_callback_ = NULL;
 Dart_ThreadExitCallback Dart::thread_exit_callback_ = NULL;
 Dart_FileOpenCallback Dart::file_open_callback_ = NULL;
 Dart_FileReadCallback Dart::file_read_callback_ = NULL;
@@ -262,6 +253,7 @@
                      Dart_IsolateShutdownCallback shutdown,
                      Dart_IsolateCleanupCallback cleanup,
                      Dart_IsolateGroupCleanupCallback cleanup_group,
+                     Dart_ThreadStartCallback thread_start,
                      Dart_ThreadExitCallback thread_exit,
                      Dart_FileOpenCallback file_open,
                      Dart_FileReadCallback file_read,
@@ -273,13 +265,6 @@
                      Dart_CodeObserver* observer,
                      Dart_PostTaskCallback post_task,
                      void* post_task_data) {
-#if defined(USING_THREAD_SANITIZER)
-  // Trigger lazy initialization in ICU to avoid spurious TSAN warning.
-  // TODO(https://github.com/dart-lang/sdk/issues/46699): Remove.
-  // TODO(https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=83298): Remove.
-  u_getPropertyValueEnum(UCHAR_SCRIPT, "foo");
-#endif
-
   CheckOffsets();
 
   if (!Flags::Initialized()) {
@@ -311,6 +296,7 @@
 
   UntaggedFrame::Init();
 
+  set_thread_start_callback(thread_start);
   set_thread_exit_callback(thread_exit);
   SetFileCallbacks(file_open, file_read, file_write, file_close);
   set_entropy_source_callback(entropy_source);
@@ -343,6 +329,7 @@
   Isolate::InitVM();
   UserTags::Init();
   PortMap::Init();
+  Service::Init();
   FreeListElement::Init();
   ForwardingCorpse::Init();
   Api::Init();
@@ -546,6 +533,7 @@
                  Dart_IsolateShutdownCallback shutdown,
                  Dart_IsolateCleanupCallback cleanup,
                  Dart_IsolateGroupCleanupCallback cleanup_group,
+                 Dart_ThreadStartCallback thread_start,
                  Dart_ThreadExitCallback thread_exit,
                  Dart_FileOpenCallback file_open,
                  Dart_FileReadCallback file_read,
@@ -566,9 +554,9 @@
   char* retval =
       DartInit(vm_isolate_snapshot, instructions_snapshot, create_group,
                initialize_isolate, shutdown, cleanup, cleanup_group,
-               thread_exit, file_open, file_read, file_write, file_close,
-               entropy_source, get_service_assets, start_kernel_isolate,
-               observer, post_task, post_task_data);
+               thread_start, thread_exit, file_open, file_read, file_write,
+               file_close, entropy_source, get_service_assets,
+               start_kernel_isolate, observer, post_task, post_task_data);
   if (retval != NULL) {
     init_state_.ResetInitializing();
     return retval;
@@ -802,6 +790,7 @@
   ShutdownIsolate();
   vm_isolate_ = NULL;
   ASSERT(Isolate::IsolateListLength() == 0);
+  Service::Cleanup();
   PortMap::Cleanup();
   UserTags::Cleanup();
   IsolateGroup::Cleanup();
@@ -1204,7 +1193,10 @@
 #else
     buffer.AddString(" x64-sysv");
 #endif
-
+#elif defined(TARGET_ARCH_RISCV32)
+    buffer.AddString(" riscv32");
+#elif defined(TARGET_ARCH_RISCV64)
+    buffer.AddString(" riscv64");
 #else
 #error What architecture?
 #endif
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index a8c4a56..5a170c2 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -36,6 +36,7 @@
                     Dart_IsolateShutdownCallback shutdown,
                     Dart_IsolateCleanupCallback cleanup,
                     Dart_IsolateGroupCleanupCallback cleanup_group,
+                    Dart_ThreadStartCallback thread_start,
                     Dart_ThreadExitCallback thread_exit,
                     Dart_FileOpenCallback file_open,
                     Dart_FileReadCallback file_read,
@@ -119,6 +120,12 @@
                               Snapshot::Kind kind);
   static Snapshot::Kind vm_snapshot_kind() { return vm_snapshot_kind_; }
 
+  static Dart_ThreadStartCallback thread_start_callback() {
+    return thread_start_callback_;
+  }
+  static void set_thread_start_callback(Dart_ThreadStartCallback cback) {
+    thread_start_callback_ = cback;
+  }
   static Dart_ThreadExitCallback thread_exit_callback() {
     return thread_exit_callback_;
   }
@@ -176,6 +183,7 @@
                         Dart_IsolateShutdownCallback shutdown,
                         Dart_IsolateCleanupCallback cleanup,
                         Dart_IsolateGroupCleanupCallback cleanup_group,
+                        Dart_ThreadStartCallback thread_start,
                         Dart_ThreadExitCallback thread_exit,
                         Dart_FileOpenCallback file_open,
                         Dart_FileReadCallback file_read,
@@ -199,6 +207,7 @@
   static DebugInfo* pprof_symbol_generator_;
   static ReadOnlyHandles* predefined_handles_;
   static Snapshot::Kind vm_snapshot_kind_;
+  static Dart_ThreadStartCallback thread_start_callback_;
   static Dart_ThreadExitCallback thread_exit_callback_;
   static Dart_FileOpenCallback file_open_callback_;
   static Dart_FileReadCallback file_read_callback_;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index fe7dcc4..9e8ab9a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -66,7 +66,6 @@
 #define Z (T->zone())
 
 DECLARE_FLAG(bool, print_class_table);
-DECLARE_FLAG(bool, verify_handles);
 #if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
 DEFINE_FLAG(bool,
             check_function_fingerprints,
@@ -95,6 +94,8 @@
 Dart_Handle Api::false_handle_ = NULL;
 Dart_Handle Api::null_handle_ = NULL;
 Dart_Handle Api::empty_string_handle_ = NULL;
+Dart_Handle Api::no_callbacks_error_handle_ = NULL;
+Dart_Handle Api::unwind_in_progress_error_handle_ = NULL;
 
 const char* CanonicalFunction(const char* func) {
   if (strncmp(func, "dart::", 6) == 0) {
@@ -370,10 +371,6 @@
   ASSERT(thread->execution_state() == Thread::kThreadInVM);
   ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate() != NULL);
-  ASSERT(!FLAG_verify_handles || thread->IsValidLocalHandle(object) ||
-         thread->isolate()->group()->api_state()->IsActivePersistentHandle(
-             reinterpret_cast<Dart_PersistentHandle>(object)) ||
-         Dart::IsReadOnlyApiHandle(object));
   ASSERT(FinalizablePersistentHandle::ptr_offset() == 0 &&
          PersistentHandle::ptr_offset() == 0 && LocalHandle::ptr_offset() == 0);
 #endif
@@ -478,23 +475,6 @@
   return Api::NewHandle(T, error.ptr());
 }
 
-Dart_Handle Api::AcquiredError(IsolateGroup* isolate_group) {
-  ApiState* state = isolate_group->api_state();
-  ASSERT(state != NULL);
-  PersistentHandle* acquired_error_handle = state->AcquiredError();
-  return reinterpret_cast<Dart_Handle>(acquired_error_handle);
-}
-
-Dart_Handle Api::UnwindInProgressError() {
-  Thread* T = Thread::Current();
-  CHECK_API_SCOPE(T);
-  TransitionToVM transition(T);
-  HANDLESCOPE(T);
-  const String& message = String::Handle(
-      Z, String::New("No api calls are allowed while unwind is in progress"));
-  return Api::NewHandle(T, UnwindError::New(message));
-}
-
 bool Api::IsValid(Dart_Handle handle) {
   Isolate* isolate = Isolate::Current();
   Thread* thread = Thread::Current();
@@ -551,6 +531,14 @@
 
   ASSERT(empty_string_handle_ == NULL);
   empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().ptr());
+
+  ASSERT(no_callbacks_error_handle_ == NULL);
+  no_callbacks_error_handle_ =
+      InitNewReadOnlyApiHandle(Object::no_callbacks_error().ptr());
+
+  ASSERT(unwind_in_progress_error_handle_ == NULL);
+  unwind_in_progress_error_handle_ =
+      InitNewReadOnlyApiHandle(Object::unwind_in_progress_error().ptr());
 }
 
 void Api::Cleanup() {
@@ -558,6 +546,8 @@
   false_handle_ = NULL;
   null_handle_ = NULL;
   empty_string_handle_ = NULL;
+  no_callbacks_error_handle_ = NULL;
+  unwind_in_progress_error_handle_ = NULL;
 }
 
 bool Api::StringGetPeerHelper(NativeArguments* arguments,
@@ -1156,9 +1146,9 @@
   ApiState* state = isolate_group->api_state();
   ASSERT(state != NULL);
   ASSERT(state->IsActivePersistentHandle(object));
-  PersistentHandle* ref = PersistentHandle::Cast(object);
-  ASSERT(!state->IsProtectedHandle(ref));
-  if (!state->IsProtectedHandle(ref)) {
+  ASSERT(!Api::IsProtectedHandle(object));
+  if (!Api::IsProtectedHandle(object)) {
+    PersistentHandle* ref = PersistentHandle::Cast(object);
     state->FreePersistentHandle(ref);
   }
 }
@@ -1211,14 +1201,15 @@
         "Invalid Dart_InitializeParams version.");
   }
 
-  return Dart::Init(
-      params->vm_snapshot_data, params->vm_snapshot_instructions,
-      params->create_group, params->initialize_isolate,
-      params->shutdown_isolate, params->cleanup_isolate, params->cleanup_group,
-      params->thread_exit, params->file_open, params->file_read,
-      params->file_write, params->file_close, params->entropy_source,
-      params->get_service_assets, params->start_kernel_isolate,
-      params->code_observer, params->post_task, params->post_task_data);
+  return Dart::Init(params->vm_snapshot_data, params->vm_snapshot_instructions,
+                    params->create_group, params->initialize_isolate,
+                    params->shutdown_isolate, params->cleanup_isolate,
+                    params->cleanup_group, params->thread_start,
+                    params->thread_exit, params->file_open, params->file_read,
+                    params->file_write, params->file_close,
+                    params->entropy_source, params->get_service_assets,
+                    params->start_kernel_isolate, params->code_observer,
+                    params->post_task, params->post_task_data);
 }
 
 DART_EXPORT char* Dart_Cleanup() {
@@ -1816,17 +1807,6 @@
   return Api::NewHandle(T, I->sticky_error());
 }
 
-DART_EXPORT void Dart_HintFreed(intptr_t size) {
-  if (size < 0) {
-    FATAL1("%s requires a non-negative size", CURRENT_FUNC);
-  }
-  Thread* T = Thread::Current();
-  CHECK_ISOLATE(T->isolate());
-  API_TIMELINE_BEGIN_END(T);
-  TransitionNativeToVM transition(T);
-  T->heap()->HintFreed(size);
-}
-
 DART_EXPORT void Dart_NotifyIdle(int64_t deadline) {
   Thread* T = Thread::Current();
   CHECK_ISOLATE(T->isolate());
@@ -4149,10 +4129,22 @@
     }
   }
   if (FLAG_verify_acquired_data) {
-    if (external) {
-      ASSERT(!T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
-    } else {
-      ASSERT(T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+    {
+      NoSafepointScope no_safepoint(T);
+      bool sweep_in_progress;
+      {
+        PageSpace* old_space = T->heap()->old_space();
+        MonitorLocker ml(old_space->tasks_lock());
+        sweep_in_progress = (old_space->phase() == PageSpace::kSweepingLarge) ||
+                            (old_space->phase() == PageSpace::kSweepingRegular);
+      }
+      if (!sweep_in_progress) {
+        if (external) {
+          ASSERT(!T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+        } else {
+          ASSERT(T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+        }
+      }
     }
     const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
     WeakTable* table = I->group()->api_state()->acquired_table();
@@ -6076,7 +6068,7 @@
   result = KernelIsolate::CompileToKernel(
       script_uri, platform_kernel, platform_kernel_size, 0, NULL,
       incremental_compile, snapshot_compile, package_config, NULL, NULL,
-      verbosity);
+      FLAG_sound_null_safety, verbosity);
   if (result.status == Dart_KernelCompilationStatus_Ok) {
     Dart_KernelCompilationResult accept_result =
         KernelIsolate::AcceptCompilation();
@@ -6091,6 +6083,34 @@
   return result;
 }
 
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileToKernelWithGivenNullsafety(
+    const char* script_uri,
+    const uint8_t* platform_kernel,
+    intptr_t platform_kernel_size,
+    bool snapshot_compile,
+    const char* package_config,
+    bool null_safety,
+    Dart_KernelCompilationVerbosityLevel verbosity) {
+  API_TIMELINE_DURATION(Thread::Current());
+
+  Dart_KernelCompilationResult result = {};
+#if defined(DART_PRECOMPILED_RUNTIME)
+  result.status = Dart_KernelCompilationStatus_Unknown;
+  result.error = Utils::StrDup("Dart_CompileToKernel is unsupported.");
+#else
+  intptr_t null_safety_option =
+      null_safety ? kNullSafetyOptionStrong : kNullSafetyOptionWeak;
+  result = KernelIsolate::CompileToKernel(
+      script_uri, platform_kernel, platform_kernel_size,
+      /*source_files_count=*/0, /*source_files=*/nullptr,
+      /*incremental_compile=*/false, snapshot_compile, package_config,
+      /*multiroot_filepaths=*/nullptr, /*multiroot_scheme=*/nullptr,
+      null_safety_option, verbosity);
+#endif
+  return result;
+}
+
 DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
   Dart_KernelCompilationResult result = {};
 #if defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 47f9b7a..73f681f 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -181,12 +181,6 @@
   // Gets the handle used to designate successful return.
   static Dart_Handle Success() { return Api::True(); }
 
-  // Gets the handle which holds the pre-created acquired error object.
-  static Dart_Handle AcquiredError(IsolateGroup* isolate_group);
-
-  // Gets the handle for unwind-is-in-progress error.
-  static Dart_Handle UnwindInProgressError();
-
   // Returns true if the handle holds a Smi.
   static bool IsSmi(Dart_Handle handle) {
     // Important: we do not require current thread to be in VM state because
@@ -241,6 +235,22 @@
   // Gets a handle to EmptyString.
   static Dart_Handle EmptyString() { return empty_string_handle_; }
 
+  // Gets the handle which holds the pre-created acquired error object.
+  static Dart_Handle NoCallbacksError() { return no_callbacks_error_handle_; }
+
+  // Gets the handle for unwind-is-in-progress error.
+  static Dart_Handle UnwindInProgressError() {
+    return unwind_in_progress_error_handle_;
+  }
+
+  static bool IsProtectedHandle(Dart_Handle object) {
+    if (object == NULL) return false;
+    return (object == true_handle_) || (object == false_handle_) ||
+           (object == null_handle_) || (object == empty_string_handle_) ||
+           (object == no_callbacks_error_handle_) ||
+           (object == unwind_in_progress_error_handle_);
+  }
+
   // Retrieves the top ApiLocalScope.
   static ApiLocalScope* TopScope(Thread* thread);
 
@@ -314,6 +324,8 @@
   static Dart_Handle false_handle_;
   static Dart_Handle null_handle_;
   static Dart_Handle empty_string_handle_;
+  static Dart_Handle no_callbacks_error_handle_;
+  static Dart_Handle unwind_in_progress_error_handle_;
 
   friend class ApiNativeScope;
 };
@@ -326,8 +338,7 @@
 
 #define CHECK_CALLBACK_STATE(thread)                                           \
   if (thread->no_callback_scope_depth() != 0) {                                \
-    return reinterpret_cast<Dart_Handle>(                                      \
-        Api::AcquiredError(thread->isolate_group()));                          \
+    return reinterpret_cast<Dart_Handle>(Api::NoCallbacksError());             \
   }                                                                            \
   if (thread->is_unwind_in_progress()) {                                       \
     return reinterpret_cast<Dart_Handle>(Api::UnwindInProgressError());        \
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 02cbfa3..5691670 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2602,9 +2602,7 @@
   // Now try allocating a string with outstanding Acquires and it should
   // return an error.
   result = NewString("We expect an error here");
-  EXPECT_ERROR(result,
-               "Internal Dart data pointers have been acquired, "
-               "please release them using Dart_TypedDataReleaseData.");
+  EXPECT_ERROR(result, "Callbacks into the Dart VM are currently prohibited");
 
   // Now modify the values in the directly accessible array and then check
   // it we see the changes back in dart.
@@ -9527,39 +9525,6 @@
   }
 }
 
-static void HintFreedNative(Dart_NativeArguments args) {
-  int64_t size = 0;
-  EXPECT_VALID(Dart_GetNativeIntegerArgument(args, 0, &size));
-  Dart_HintFreed(size);
-}
-
-static Dart_NativeFunction HintFreed_native_lookup(Dart_Handle name,
-                                                   int argument_count,
-                                                   bool* auto_setup_scope) {
-  return HintFreedNative;
-}
-
-TEST_CASE(DartAPI_HintFreed) {
-  const char* kScriptChars = R"(
-@pragma("vm:external-name", "Test_nativeFunc")
-external void hintFreed(int size);
-void main() {
-  var v;
-  for (var i = 0; i < 100; i++) {
-    var t = [];
-    for (var j = 0; j < 10000; j++) {
-      t.add(List.filled(100, null));
-    }
-    v = t;
-    hintFreed(100 * 10000 * 4);
-  }
-})";
-  Dart_Handle lib =
-      TestCase::LoadTestScript(kScriptChars, &HintFreed_native_lookup);
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-}
-
 static void NotifyIdleShortNative(Dart_NativeArguments args) {
   Dart_NotifyIdle(Dart_TimelineGetMicros() + 10 * kMicrosecondsPerMillisecond);
 }
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index e23252e..f3f9775 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -702,31 +702,7 @@
 // group basis and destroyed when the isolate group is shutdown.
 class ApiState {
  public:
-  ApiState()
-      : persistent_handles_(),
-        weak_persistent_handles_(),
-        null_(NULL),
-        true_(NULL),
-        false_(NULL),
-        acquired_error_(NULL) {}
-  ~ApiState() {
-    if (null_ != NULL) {
-      persistent_handles_.FreeHandle(null_);
-      null_ = NULL;
-    }
-    if (true_ != NULL) {
-      persistent_handles_.FreeHandle(true_);
-      true_ = NULL;
-    }
-    if (false_ != NULL) {
-      persistent_handles_.FreeHandle(false_);
-      false_ = NULL;
-    }
-    if (acquired_error_ != NULL) {
-      persistent_handles_.FreeHandle(acquired_error_);
-      acquired_error_ = NULL;
-    }
-  }
+  ApiState() : persistent_handles_(), weak_persistent_handles_() {}
 
   void MergeOtherApiState(ApiState* api_state);
 
@@ -790,30 +766,11 @@
            !weak_persistent_handles_.IsFreeHandle(object);
   }
 
-  bool IsProtectedHandle(PersistentHandle* object) {
-    MutexLocker ml(&mutex_);
-    if (object == NULL) return false;
-    return object == null_ || object == true_ || object == false_;
-  }
-
   int CountPersistentHandles() {
     MutexLocker ml(&mutex_);
     return persistent_handles_.CountHandles();
   }
 
-  PersistentHandle* AcquiredError() {
-    // The ApiError pre-allocated in the "vm-isolate" since we will not be able
-    // to allocate it when the error actually occurs.
-    // When the error occurs there will be outstanding acquires to internal
-    // data pointers making it unsafe to allocate objects on the dart heap.
-    MutexLocker ml(&mutex_);
-    if (acquired_error_ == nullptr) {
-      acquired_error_ = persistent_handles_.AllocateHandle();
-      acquired_error_->set_ptr(ApiError::typed_data_acquire_error());
-    }
-    return acquired_error_;
-  }
-
   void RunWithLockedPersistentHandles(
       std::function<void(PersistentHandles&)> fun) {
     MutexLocker ml(&mutex_);
@@ -835,12 +792,6 @@
   FinalizablePersistentHandles weak_persistent_handles_;
   WeakTable acquired_table_;
 
-  // Persistent handles to important objects.
-  PersistentHandle* null_;
-  PersistentHandle* true_;
-  PersistentHandle* false_;
-  PersistentHandle* acquired_error_;
-
   DISALLOW_COPY_AND_ASSIGN(ApiState);
 };
 
diff --git a/runtime/vm/debugger_riscv.cc b/runtime/vm/debugger_riscv.cc
new file mode 100644
index 0000000..37e3804
--- /dev/null
+++ b/runtime/vm/debugger_riscv.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/code_patcher.h"
+#include "vm/cpu.h"
+#include "vm/debugger.h"
+#include "vm/instructions.h"
+#include "vm/stub_code.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+
+CodePtr CodeBreakpoint::OrigStubAddress() const {
+  return saved_value_;
+}
+
+void CodeBreakpoint::PatchCode() {
+  ASSERT(!IsEnabled());
+  const Code& code = Code::Handle(code_);
+  switch (breakpoint_kind_) {
+    case UntaggedPcDescriptors::kIcCall: {
+      Object& data = Object::Handle();
+      saved_value_ = CodePatcher::GetInstanceCallAt(pc_, code, &data);
+      CodePatcher::PatchInstanceCallAt(pc_, code, data,
+                                       StubCode::ICCallBreakpoint());
+      break;
+    }
+    case UntaggedPcDescriptors::kUnoptStaticCall: {
+      saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
+      CodePatcher::PatchPoolPointerCallAt(
+          pc_, code, StubCode::UnoptStaticCallBreakpoint());
+      break;
+    }
+    case UntaggedPcDescriptors::kRuntimeCall: {
+      saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
+      CodePatcher::PatchPoolPointerCallAt(pc_, code,
+                                          StubCode::RuntimeCallBreakpoint());
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+void CodeBreakpoint::RestoreCode() {
+  ASSERT(IsEnabled());
+  const Code& code = Code::Handle(code_);
+  switch (breakpoint_kind_) {
+    case UntaggedPcDescriptors::kIcCall: {
+      Object& data = Object::Handle();
+      CodePatcher::GetInstanceCallAt(pc_, code, &data);
+      CodePatcher::PatchInstanceCallAt(pc_, code, data,
+                                       Code::Handle(saved_value_));
+      break;
+    }
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+    case UntaggedPcDescriptors::kRuntimeCall: {
+      CodePatcher::PatchPoolPointerCallAt(pc_, code,
+                                          Code::Handle(saved_value_));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+#endif  // !PRODUCT
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/dispatch_table.cc b/runtime/vm/dispatch_table.cc
index 56e2449..7aa3eca 100644
--- a/runtime/vm/dispatch_table.cc
+++ b/runtime/vm/dispatch_table.cc
@@ -18,6 +18,12 @@
 #elif defined(TARGET_ARCH_ARM64)
   // Max consecutive sub immediate value
   return 4096;
+#elif defined(TARGET_ARCH_RISCV32)
+  // Max consecutive sub immediate value
+  return 2048 / 4;
+#elif defined(TARGET_ARCH_RISCV64)
+  // Max consecutive sub immediate value
+  return 2048 / 8;
 #else
   // No AOT on IA32
   UNREACHABLE();
@@ -35,6 +41,12 @@
 #elif defined(TARGET_ARCH_ARM64)
   // Origin + Max consecutive add immediate value
   return 8192;
+#elif defined(TARGET_ARCH_RISCV32)
+  // Origin + Max consecutive add immediate value
+  return 4096 / 4;
+#elif defined(TARGET_ARCH_RISCV64)
+  // Origin + Max consecutive add immediate value
+  return 4096 / 8;
 #else
   // No AOT on IA32
   UNREACHABLE();
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 28e8224..77d6949 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -1908,6 +1908,8 @@
   stream->WriteHalf(elf::EM_ARM);
 #elif defined(TARGET_ARCH_ARM64)
   stream->WriteHalf(elf::EM_AARCH64);
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+  stream->WriteHalf(elf::EM_RISCV);
 #else
   FATAL("Unknown ELF architecture");
 #endif
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index fc6e47b..41c46cf 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -650,6 +650,9 @@
   ExcpHandler func =
       reinterpret_cast<ExcpHandler>(StubCode::JumpToFrame().EntryPoint());
 
+  if (thread->is_unwind_in_progress()) {
+    thread->SetUnwindErrorInProgress(true);
+  }
   func(program_counter, stack_pointer, frame_pointer, thread);
 
 #endif
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index f272686..5200b16 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -6,7 +6,7 @@
 // Instead modify 'tools/experimental_features.yaml' and run
 // 'dart tools/generate_experimental_flags.dart' to update.
 //
-// Current version: 2.16.0
+// Current version: 2.17.0
 
 #include "vm/experimental_features.h"
 
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index 020ba59..d1a5abb 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -6,7 +6,7 @@
 // Instead modify 'tools/experimental_features.yaml' and run
 // 'dart tools/generate_experimental_flags.dart' to update.
 //
-// Current version: 2.16.0
+// Current version: 2.17.0
 
 #ifndef RUNTIME_VM_EXPERIMENTAL_FEATURES_H_
 #define RUNTIME_VM_EXPERIMENTAL_FEATURES_H_
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index cccfdfb..b5cde40 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -140,9 +140,14 @@
   P(scavenger_tasks, int, 2,                                                   \
     "The number of tasks to spawn during scavenging (0 means "                 \
     "perform all marking on main thread).")                                    \
+  P(mark_when_idle, bool, false,                                               \
+    "The Dart thread will assist in concurrent marking during idle time and "  \
+    "is counted as one marker task")                                           \
   P(marker_tasks, int, 2,                                                      \
     "The number of tasks to spawn during old gen GC marking (0 means "         \
     "perform all marking on main thread).")                                    \
+  P(hash_map_probes_limit, int, kMaxInt32,                                     \
+    "Limit number of probes while doing lookups in hash maps.")                \
   P(max_polymorphic_checks, int, 4,                                            \
     "Maximum number of polymorphic check, otherwise it is megamorphic.")       \
   P(max_equality_polymorphic_checks, int, 32,                                  \
@@ -184,7 +189,6 @@
   P(reorder_basic_blocks, bool, true, "Reorder basic blocks")                  \
   C(stress_async_stacks, false, false, bool, false,                            \
     "Stress test async stack traces")                                          \
-  P(use_table_dispatch, bool, true, "Enable dispatch table based calls.")      \
   P(retain_function_objects, bool, true,                                       \
     "Serialize function objects for all code objects even if not otherwise "   \
     "needed in the precompiled runtime.")                                      \
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 46cd706..1a3d6c0 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -95,11 +95,10 @@
 #define ONLY_IN_PRECOMPILED(code)
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
-#define ONLY_IN_ARM_ARM64_X64(code) code
+#if defined(TARGET_ARCH_IA32)
+#define NOT_IN_IA32(code)
 #else
-#define ONLY_IN_ARM_ARM64_X64(code)
+#define NOT_IN_IA32(code) code
 #endif
 
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -198,13 +197,15 @@
 #endif  // !defined(DART_HOST_OS_WINDOWS))
 
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
+    defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_RISCV32) ||                \
+    defined(TARGET_ARCH_RISCV64)
 #define TARGET_USES_OBJECT_POOL 1
 #endif
 
 #if defined(DART_PRECOMPILER) &&                                               \
     (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM) ||                   \
-     defined(TARGET_ARCH_ARM64))
+     defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV32) ||             \
+     defined(TARGET_ARCH_RISCV64))
 #define DART_SUPPORT_PRECOMPILATION 1
 #endif
 
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index b088957..8b44b78 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -17,8 +17,6 @@
 
 namespace dart {
 
-DEFINE_FLAG(bool, verify_handles, false, "Verify handles.");
-
 void VMHandles::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   return Handles<kVMHandleSizeInWords, kVMHandlesPerChunk,
                  kOffsetOfRawPtr>::VisitObjectPointers(visitor);
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index f2f9005..d59a1ba 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -50,8 +50,6 @@
 class ObjectPointerVisitor;
 class HandleVisitor;
 
-DECLARE_FLAG(bool, verify_handles);
-
 template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
 class Handles {
  public:
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index aacbf87..a55f683 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -6,6 +6,7 @@
 #define RUNTIME_VM_HASH_MAP_H_
 
 #include "platform/utils.h"
+#include "vm/flags.h"
 #include "vm/growable_array.h"  // For Malloc, EmptyBase
 #include "vm/hash.h"
 #include "vm/zone.h"
@@ -132,6 +133,7 @@
   uint32_t mask = hash_table_size_ - 1;
   uint32_t hash_index = hash & mask;
   uint32_t start = hash_index;
+  intptr_t probes = 0;
   for (;;) {
     uint32_t pair_index = hash_table_[hash_index];
     if (pair_index == kEmpty) {
@@ -139,6 +141,7 @@
     }
     if (pair_index != kDeleted) {
       ASSERT(pair_index < pairs_size_);
+      RELEASE_ASSERT(++probes < FLAG_hash_map_probes_limit);
       if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
         return &pairs_[pair_index];
       }
@@ -233,6 +236,7 @@
   uint32_t mask = hash_table_size_ - 1;
   uint32_t hash_index = hash & mask;
   uint32_t start = hash_index;
+  intptr_t probes = 0;
   for (;;) {
     uint32_t pair_index = hash_table_[hash_index];
     if ((pair_index == kEmpty) || (pair_index == kDeleted)) {
@@ -241,6 +245,7 @@
       next_pair_index_++;
       break;
     }
+    RELEASE_ASSERT(++probes < FLAG_hash_map_probes_limit);
     ASSERT(pair_index < pairs_size_);
     hash_index = (hash_index + 1) & mask;
     // Hashtable must contain at least one empty marker.
@@ -273,6 +278,7 @@
   uint32_t mask = hash_table_size_ - 1;
   uint32_t hash_index = hash & mask;
   uint32_t start = hash_index;
+  intptr_t probes = 0;
   for (;;) {
     uint32_t pair_index = hash_table_[hash_index];
     if (pair_index == kEmpty) {
@@ -280,6 +286,7 @@
     }
     if (pair_index != kDeleted) {
       ASSERT(pair_index < pairs_size_);
+      RELEASE_ASSERT(++probes < FLAG_hash_map_probes_limit);
       if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
         hash_table_[hash_index] = kDeleted;
         pairs_[pair_index] = typename KeyValueTrait::Pair();
diff --git a/runtime/vm/heap/freelist_test.cc b/runtime/vm/heap/freelist_test.cc
index 5778886..6a0c19c 100644
--- a/runtime/vm/heap/freelist_test.cc
+++ b/runtime/vm/heap/freelist_test.cc
@@ -213,6 +213,8 @@
   const uint8_t ret[4] = {0x1e, 0xff, 0x2f, 0xe1};  // bx lr
 #elif defined(HOST_ARCH_ARM64)
   const uint8_t ret[4] = {0xc0, 0x03, 0x5f, 0xd6};  // ret
+#elif defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
+  const uint8_t ret[2] = {0x82, 0x80};  // c.ret
 #else
 #error "Unknown architecture."
 #endif
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index fe3956d..286206f 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -243,6 +243,7 @@
 #endif
     while ((old_space_->tasks() > 0) ||
            (old_space_->phase() != PageSpace::kDone)) {
+      old_space_->AssistTasks(&ml);
       if (old_space_->phase() == PageSpace::kAwaitingFinalization) {
         ml.Exit();
         heap_->CollectOldSpaceGarbage(thread, GCType::kMarkSweep,
@@ -356,10 +357,6 @@
   return raw_obj;
 }
 
-void Heap::HintFreed(intptr_t size) {
-  old_space_.HintFreed(size);
-}
-
 void Heap::NotifyIdle(int64_t deadline) {
   Thread* thread = Thread::Current();
   TIMELINE_FUNCTION_GC_DURATION(thread, "NotifyIdle");
@@ -412,6 +409,8 @@
     }
   }
 
+  old_space_.NotifyIdle(deadline);
+
   if (OS::GetCurrentMonotonicMicros() < deadline) {
     SemiSpace::DrainCache();
   }
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 2360700..121e075 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -104,7 +104,6 @@
   ObjectPtr FindNewObject(FindObjectVisitor* visitor);
   ObjectPtr FindObject(FindObjectVisitor* visitor);
 
-  void HintFreed(intptr_t size);
   void NotifyIdle(int64_t deadline);
   void NotifyLowMemory();
 
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 43b4c62..adbaab4 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -78,15 +78,37 @@
   }
 
   void DrainMarkingStack() {
+    while (ProcessMarkingStack()) {
+    }
+  }
+
+  void ProcessMarkingStackUntil(int64_t deadline) {
+    // We check the clock *before* starting a batch of work, but we want to
+    // *end* work before the deadline. So we compare to the deadline adjusted
+    // by a conservative estimate of the duration of one batch of work.
+    deadline -= 1500;
+
+    while ((OS::GetCurrentMonotonicMicros() < deadline) &&
+           ProcessMarkingStack()) {
+    }
+  }
+
+  bool ProcessMarkingStack() {
     ObjectPtr raw_obj = work_list_.Pop();
     if ((raw_obj == nullptr) && ProcessPendingWeakProperties()) {
       raw_obj = work_list_.Pop();
     }
 
     if (raw_obj == nullptr) {
-      return;
+      return false;  // No more work.
     }
 
+    // A 512kB budget is choosen to be large enough that we don't waste too much
+    // time on the overhead of exiting this function, querying the clock, and
+    // re-entering, and small enough that a few batches can fit in the idle time
+    // between animation frames. This amount of marking takes ~1ms on a Pixel
+    // phone.
+    intptr_t remaining_budget = 512 * KB;
     do {
       do {
         // First drain the marking stacks.
@@ -100,6 +122,10 @@
           size = ProcessWeakProperty(raw_weak, /* did_mark */ true);
         }
         marked_bytes_ += size;
+        remaining_budget -= size;
+        if (remaining_budget < 0) {
+          return true;  // More to mark.
+        }
 
         raw_obj = work_list_.Pop();
       } while (raw_obj != nullptr);
@@ -111,6 +137,8 @@
       // by the handling of weak properties.
       raw_obj = work_list_.Pop();
     } while (raw_obj != nullptr);
+
+    return false;  // No more work.
   }
 
   // Races: The concurrent marker is racing with the mutator, but this race is
@@ -767,6 +795,9 @@
                                            &deferred_marking_stack_);
 
   const intptr_t num_tasks = FLAG_marker_tasks;
+  RELEASE_ASSERT(num_tasks >= 1);
+  const intptr_t num_concurrent_tasks =
+      num_tasks - (FLAG_mark_when_idle ? 1 : 0);
 
   {
     // Bulk increase task count before starting any task, instead of
@@ -775,9 +806,9 @@
     MonitorLocker ml(page_space->tasks_lock());
     ASSERT(page_space->phase() == PageSpace::kDone);
     page_space->set_phase(PageSpace::kMarking);
-    page_space->set_tasks(page_space->tasks() + num_tasks);
+    page_space->set_tasks(page_space->tasks() + num_concurrent_tasks);
     page_space->set_concurrent_marker_tasks(
-        page_space->concurrent_marker_tasks() + num_tasks);
+        page_space->concurrent_marker_tasks() + num_concurrent_tasks);
   }
 
   ResetSlices();
@@ -793,7 +824,7 @@
           this, isolate_group_, page_space, visitor);
       ASSERT(result);
     } else {
-      // Last worker is the main thread, which will only mark roots.
+      // For the last visitor, mark roots on the main thread.
       TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ConcurrentMark");
       int64_t start = OS::GetCurrentMonotonicMicros();
       IterateRoots(visitor);
@@ -803,10 +834,16 @@
         THR_Print("Task marked %" Pd " bytes in %" Pd64 " micros.\n",
                   visitor->marked_bytes(), visitor->marked_micros());
       }
-      // Continue non-root marking concurrently.
-      bool result = Dart::thread_pool()->Run<ConcurrentMarkTask>(
-          this, isolate_group_, page_space, visitor);
-      ASSERT(result);
+      if (FLAG_mark_when_idle) {
+        // Not spawning a thread to continue processing with the last visitor.
+        // This visitor is instead left available for the main thread to
+        // contribute to marking during idle time.
+      } else {
+        // Continue non-root marking concurrently.
+        bool result = Dart::thread_pool()->Run<ConcurrentMarkTask>(
+            this, isolate_group_, page_space, visitor);
+        ASSERT(result);
+      }
     }
   }
 
@@ -819,6 +856,31 @@
   }
 }
 
+void GCMarker::AssistConcurrentMark() {
+  if (!FLAG_mark_when_idle) return;
+
+  SyncMarkingVisitor* visitor = visitors_[FLAG_marker_tasks - 1];
+  ASSERT(visitor != nullptr);
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Mark");
+  int64_t start = OS::GetCurrentMonotonicMicros();
+  visitor->DrainMarkingStack();
+  int64_t stop = OS::GetCurrentMonotonicMicros();
+  visitor->AddMicros(stop - start);
+}
+
+void GCMarker::NotifyIdle(int64_t deadline) {
+  if (!FLAG_mark_when_idle) return;
+
+  SyncMarkingVisitor* visitor = visitors_[FLAG_marker_tasks - 1];
+  if (visitor == nullptr) return;
+
+  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IncrementalMark");
+  int64_t start = OS::GetCurrentMonotonicMicros();
+  visitor->ProcessMarkingStackUntil(deadline);
+  int64_t stop = OS::GetCurrentMonotonicMicros();
+  visitor->AddMicros(stop - start);
+}
+
 void GCMarker::MarkObjects(PageSpace* page_space) {
   if (isolate_group_->marking_stack() != NULL) {
     isolate_group_->DisableIncrementalBarrier();
diff --git a/runtime/vm/heap/marker.h b/runtime/vm/heap/marker.h
index 2fde0d8..ec36170 100644
--- a/runtime/vm/heap/marker.h
+++ b/runtime/vm/heap/marker.h
@@ -38,6 +38,13 @@
   // Marking must later be finalized by calling MarkObjects.
   void StartConcurrentMark(PageSpace* page_space);
 
+  // Called when a synchronous GC is required, but concurrent marking is still
+  // in progress.
+  void AssistConcurrentMark();
+
+  // Perform incremental marking if available.
+  void NotifyIdle(int64_t deadline);
+
   // (Re)mark roots, drain the marking queue and finalize weak references.
   // Does not required StartConcurrentMark to have been previously called.
   void MarkObjects(PageSpace* page_space);
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index f17e8e6..48fbd5f 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -263,6 +263,7 @@
 PageSpace::~PageSpace() {
   {
     MonitorLocker ml(tasks_lock());
+    AssistTasks(&ml);
     while (tasks() > 0) {
       ml.Wait();
     }
@@ -1036,6 +1037,26 @@
   return estimated_mark_compact_completion <= deadline;
 }
 
+void PageSpace::NotifyIdle(int64_t deadline) {
+  if (marker_ != nullptr) {
+    marker_->NotifyIdle(deadline);
+  }
+}
+
+void PageSpace::AssistTasks(MonitorLocker* ml) {
+  if (phase() == PageSpace::kMarking) {
+    ml->Exit();
+    marker_->AssistConcurrentMark();
+    ml->Enter();
+  }
+  if ((phase() == kSweepingLarge) || (phase() == kSweepingRegular)) {
+    ml->Exit();
+    Sweep(/*exclusive*/ false);
+    SweepLarge();
+    ml->Enter();
+  }
+}
+
 void PageSpace::TryReleaseReservation() {
   ASSERT(phase() != kSweepingLarge);
   ASSERT(phase() != kSweepingRegular);
@@ -1107,6 +1128,7 @@
       return;
     }
 
+    AssistTasks(&locker);
     while (tasks() > 0) {
       locker.Wait();
     }
@@ -1247,16 +1269,39 @@
 
   bool has_reservation = MarkReservation();
 
+  {
+    // Move pages to sweeper work lists.
+    MutexLocker ml(&pages_lock_);
+    ASSERT(sweep_large_ == nullptr);
+    sweep_large_ = large_pages_;
+    large_pages_ = large_pages_tail_ = nullptr;
+    ASSERT(sweep_regular_ == nullptr);
+    if (!compact) {
+      sweep_regular_ = pages_;
+      pages_ = pages_tail_ = nullptr;
+    }
+  }
+
+  bool can_verify;
   if (compact) {
     SweepLarge();
     Compact(thread);
     set_phase(kDone);
+    can_verify = true;
   } else if (FLAG_concurrent_sweep && has_reservation) {
     ConcurrentSweep(isolate_group);
+    can_verify = false;
   } else {
     SweepLarge();
-    Sweep();
+    Sweep(/*exclusive*/ true);
     set_phase(kDone);
+    can_verify = true;
+  }
+
+  if (FLAG_verify_after_gc && can_verify) {
+    OS::PrintErr("Verifying after sweeping...");
+    heap_->VerifyGC(kForbidMarked);
+    OS::PrintErr(" done.\n");
   }
 
   TryReserveForOOM();
@@ -1294,65 +1339,79 @@
   TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "SweepLarge");
 
   GCSweeper sweeper;
-  OldPage* prev_page = nullptr;
-  OldPage* page = large_pages_;
-  while (page != nullptr) {
-    OldPage* next_page = page->next();
-    const intptr_t words_to_end = sweeper.SweepLargePage(page);
+  MutexLocker ml(&pages_lock_);
+  while (sweep_large_ != nullptr) {
+    OldPage* page = sweep_large_;
+    sweep_large_ = page->next();
+    page->set_next(nullptr);
+    ASSERT(page->type() == OldPage::kData);
+
+    ml.Unlock();
+    intptr_t words_to_end = sweeper.SweepLargePage(page);
+    intptr_t size;
     if (words_to_end == 0) {
-      FreeLargePage(page, prev_page);
+      size = page->memory_->size();
+      page->Deallocate();
+      ml.Lock();
+      IncreaseCapacityInWordsLocked(-(size >> kWordSizeLog2));
     } else {
       TruncateLargePage(page, words_to_end << kWordSizeLog2);
-      prev_page = page;
+      ml.Lock();
+      AddLargePageLocked(page);
     }
-    // Advance to the next page.
-    page = next_page;
   }
 }
 
-void PageSpace::Sweep() {
+void PageSpace::Sweep(bool exclusive) {
   TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Sweep");
 
   GCSweeper sweeper;
 
   intptr_t shard = 0;
   const intptr_t num_shards = Utils::Maximum(FLAG_scavenger_tasks, 1);
-  for (intptr_t i = 0; i < num_shards; i++) {
-    DataFreeList(i)->mutex()->Lock();
-  }
-
-  OldPage* prev_page = nullptr;
-  OldPage* page = pages_;
-  while (page != nullptr) {
-    OldPage* next_page = page->next();
-    ASSERT(page->type() == OldPage::kData);
-    shard = (shard + 1) % num_shards;
-    bool page_in_use =
-        sweeper.SweepPage(page, DataFreeList(shard), true /*is_locked*/);
-    if (page_in_use) {
-      prev_page = page;
-    } else {
-      FreePage(page, prev_page);
+  if (exclusive) {
+    for (intptr_t i = 0; i < num_shards; i++) {
+      DataFreeList(i)->mutex()->Lock();
     }
-    // Advance to the next page.
-    page = next_page;
   }
 
-  for (intptr_t i = 0; i < num_shards; i++) {
-    DataFreeList(i)->mutex()->Unlock();
+  MutexLocker ml(&pages_lock_);
+  while (sweep_regular_ != nullptr) {
+    OldPage* page = sweep_regular_;
+    sweep_regular_ = page->next();
+    page->set_next(nullptr);
+    ASSERT(page->type() == OldPage::kData);
+
+    ml.Unlock();
+    // Cycle through the shards round-robin so that free space is roughly
+    // evenly distributed among the freelists and so roughly evenly available
+    // to each scavenger worker.
+    shard = (shard + 1) % num_shards;
+    bool page_in_use = sweeper.SweepPage(page, DataFreeList(shard), exclusive);
+    intptr_t size;
+    if (!page_in_use) {
+      size = page->memory_->size();
+      page->Deallocate();
+    }
+    ml.Lock();
+
+    if (page_in_use) {
+      AddPageLocked(page);
+    } else {
+      IncreaseCapacityInWordsLocked(-(size >> kWordSizeLog2));
+    }
   }
 
-  if (FLAG_verify_after_gc) {
-    OS::PrintErr("Verifying after sweeping...");
-    heap_->VerifyGC(kForbidMarked);
-    OS::PrintErr(" done.\n");
+  if (exclusive) {
+    for (intptr_t i = 0; i < num_shards; i++) {
+      DataFreeList(i)->mutex()->Unlock();
+    }
   }
 }
 
 void PageSpace::ConcurrentSweep(IsolateGroup* isolate_group) {
   // Start the concurrent sweeper task now.
-  GCSweeper::SweepConcurrent(isolate_group, pages_, pages_tail_, large_pages_,
-                             large_pages_tail_, &freelists_[OldPage::kData]);
+  GCSweeper::SweepConcurrent(isolate_group);
 }
 
 void PageSpace::Compact(Thread* thread) {
@@ -1692,17 +1751,6 @@
   }
 }
 
-void PageSpaceController::HintFreed(intptr_t size) {
-  intptr_t size_in_words = size << kWordSizeLog2;
-  if (size_in_words > idle_gc_threshold_in_words_) {
-    idle_gc_threshold_in_words_ = 0;
-  } else {
-    idle_gc_threshold_in_words_ -= size_in_words;
-  }
-
-  // TODO(rmacnak): Hasten the soft threshold at some discount?
-}
-
 void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start,
                                                                  int64_t end) {
   Entry entry;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 9d039e1..5a3c5c0 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -265,7 +265,6 @@
                                  int64_t start,
                                  int64_t end);
   void EvaluateAfterLoading(SpaceUsage after);
-  void HintFreed(intptr_t size);
 
   void set_last_usage(SpaceUsage current) { last_usage_ = current; }
 
@@ -359,7 +358,6 @@
   void EvaluateAfterLoading() {
     page_space_controller_.EvaluateAfterLoading(usage_);
   }
-  void HintFreed(intptr_t size) { page_space_controller_.HintFreed(size); }
 
   int64_t UsedInWords() const { return usage_.used_in_words; }
   int64_t CapacityInWords() const {
@@ -436,6 +434,8 @@
 
   bool ShouldStartIdleMarkSweep(int64_t deadline);
   bool ShouldPerformIdleMarkCompact(int64_t deadline);
+  void NotifyIdle(int64_t deadline);
+  void AssistTasks(MonitorLocker* ml);
 
   void AddGCTime(int64_t micros) { gc_time_micros_ += micros; }
 
@@ -578,7 +578,7 @@
                             int64_t pre_wait_for_sweepers,
                             int64_t pre_safe_point);
   void SweepLarge();
-  void Sweep();
+  void Sweep(bool exclusive);
   void ConcurrentSweep(IsolateGroup* isolate_group);
   void Compact(Thread* thread);
 
@@ -616,6 +616,8 @@
   OldPage* large_pages_ = nullptr;
   OldPage* large_pages_tail_ = nullptr;
   OldPage* image_pages_ = nullptr;
+  OldPage* sweep_regular_ = nullptr;
+  OldPage* sweep_large_ = nullptr;
 
   // Various sizes being tracked for this generation.
   intptr_t max_capacity_in_words_;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index ca75d9a..bc626a5 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -439,7 +439,9 @@
   RelaxedAtomic<bool> failed_to_promote_;
   RelaxedAtomic<bool> abort_;
 
-  bool growth_control_;
+  // When the isolate group is ready it will enable growth control via
+  // InitGrowthControl.
+  bool growth_control_ = false;
 
   // Protects new space during the allocation of new TLABs
   mutable Mutex space_lock_;
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index d814521..11900bb 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -109,127 +109,54 @@
 
 class ConcurrentSweeperTask : public ThreadPool::Task {
  public:
-  ConcurrentSweeperTask(IsolateGroup* isolate_group,
-                        PageSpace* old_space,
-                        OldPage* first,
-                        OldPage* last,
-                        OldPage* large_first,
-                        OldPage* large_last)
-      : task_isolate_group_(isolate_group),
-        old_space_(old_space),
-        first_(first),
-        last_(last),
-        large_first_(large_first),
-        large_last_(large_last) {
-    ASSERT(task_isolate_group_ != NULL);
-    ASSERT(first_ != NULL);
-    ASSERT(old_space_ != NULL);
-    ASSERT(last_ != NULL);
-    MonitorLocker ml(old_space_->tasks_lock());
-    old_space_->set_tasks(old_space_->tasks() + 1);
-    old_space_->set_phase(PageSpace::kSweepingLarge);
+  explicit ConcurrentSweeperTask(IsolateGroup* isolate_group)
+      : isolate_group_(isolate_group) {
+    ASSERT(isolate_group != nullptr);
+    PageSpace* old_space = isolate_group->heap()->old_space();
+    MonitorLocker ml(old_space->tasks_lock());
+    old_space->set_tasks(old_space->tasks() + 1);
+    old_space->set_phase(PageSpace::kSweepingLarge);
   }
 
   virtual void Run() {
     bool result = Thread::EnterIsolateGroupAsHelper(
-        task_isolate_group_, Thread::kSweeperTask, /*bypass_safepoint=*/true);
+        isolate_group_, Thread::kSweeperTask, /*bypass_safepoint=*/true);
     ASSERT(result);
+    PageSpace* old_space = isolate_group_->heap()->old_space();
     {
       Thread* thread = Thread::Current();
       ASSERT(thread->BypassSafepoints());  // Or we should be checking in.
       TIMELINE_FUNCTION_GC_DURATION(thread, "ConcurrentSweep");
-      GCSweeper sweeper;
 
-      OldPage* page = large_first_;
-      OldPage* prev_page = NULL;
-      while (page != NULL) {
-        OldPage* next_page;
-        if (page == large_last_) {
-          // Don't access page->next(), which would be a race with mutator
-          // allocating new pages.
-          next_page = NULL;
-        } else {
-          next_page = page->next();
-        }
-        ASSERT(page->type() == OldPage::kData);
-        const intptr_t words_to_end = sweeper.SweepLargePage(page);
-        if (words_to_end == 0) {
-          old_space_->FreeLargePage(page, prev_page);
-        } else {
-          old_space_->TruncateLargePage(page, words_to_end << kWordSizeLog2);
-          prev_page = page;
-        }
-        page = next_page;
-      }
+      old_space->SweepLarge();
 
       {
-        MonitorLocker ml(old_space_->tasks_lock());
-        ASSERT(old_space_->phase() == PageSpace::kSweepingLarge);
-        old_space_->set_phase(PageSpace::kSweepingRegular);
+        MonitorLocker ml(old_space->tasks_lock());
+        ASSERT(old_space->phase() == PageSpace::kSweepingLarge);
+        old_space->set_phase(PageSpace::kSweepingRegular);
         ml.NotifyAll();
       }
 
-      intptr_t shard = 0;
-      const intptr_t num_shards = Utils::Maximum(FLAG_scavenger_tasks, 1);
-      page = first_;
-      prev_page = NULL;
-      while (page != NULL) {
-        OldPage* next_page;
-        if (page == last_) {
-          // Don't access page->next(), which would be a race with mutator
-          // allocating new pages.
-          next_page = NULL;
-        } else {
-          next_page = page->next();
-        }
-        ASSERT(page->type() == OldPage::kData);
-        shard = (shard + 1) % num_shards;
-        bool page_in_use =
-            sweeper.SweepPage(page, old_space_->DataFreeList(shard), false);
-        if (page_in_use) {
-          prev_page = page;
-        } else {
-          old_space_->FreePage(page, prev_page);
-        }
-        {
-          // Notify the mutator thread that we have added elements to the free
-          // list or that more capacity is available.
-          MonitorLocker ml(old_space_->tasks_lock());
-          ml.Notify();
-        }
-        page = next_page;
-      }
+      old_space->Sweep(/*exclusive*/ false);
     }
     // Exit isolate cleanly *before* notifying it, to avoid shutdown race.
     Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/true);
     // This sweeper task is done. Notify the original isolate.
     {
-      MonitorLocker ml(old_space_->tasks_lock());
-      old_space_->set_tasks(old_space_->tasks() - 1);
-      ASSERT(old_space_->phase() == PageSpace::kSweepingRegular);
-      old_space_->set_phase(PageSpace::kDone);
+      MonitorLocker ml(old_space->tasks_lock());
+      old_space->set_tasks(old_space->tasks() - 1);
+      ASSERT(old_space->phase() == PageSpace::kSweepingRegular);
+      old_space->set_phase(PageSpace::kDone);
       ml.NotifyAll();
     }
   }
 
  private:
-  IsolateGroup* task_isolate_group_;
-  PageSpace* old_space_;
-  OldPage* first_;
-  OldPage* last_;
-  OldPage* large_first_;
-  OldPage* large_last_;
+  IsolateGroup* isolate_group_;
 };
 
-void GCSweeper::SweepConcurrent(IsolateGroup* isolate_group,
-                                OldPage* first,
-                                OldPage* last,
-                                OldPage* large_first,
-                                OldPage* large_last,
-                                FreeList* freelist) {
-  bool result = Dart::thread_pool()->Run<ConcurrentSweeperTask>(
-      isolate_group, isolate_group->heap()->old_space(), first, last,
-      large_first, large_last);
+void GCSweeper::SweepConcurrent(IsolateGroup* isolate_group) {
+  bool result = Dart::thread_pool()->Run<ConcurrentSweeperTask>(isolate_group);
   ASSERT(result);
 }
 
diff --git a/runtime/vm/heap/sweeper.h b/runtime/vm/heap/sweeper.h
index ca9b6c4..8b781d4 100644
--- a/runtime/vm/heap/sweeper.h
+++ b/runtime/vm/heap/sweeper.h
@@ -34,13 +34,8 @@
   // last marked object.
   intptr_t SweepLargePage(OldPage* page);
 
-  // Sweep the regular sized data pages between first and last inclusive.
-  static void SweepConcurrent(IsolateGroup* isolate_group,
-                              OldPage* first,
-                              OldPage* last,
-                              OldPage* large_first,
-                              OldPage* large_last,
-                              FreeList* freelist);
+  // Sweep the large and regular sized data pages.
+  static void SweepConcurrent(IsolateGroup* isolate_group);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 71ea299..1a726dd 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -107,16 +107,6 @@
     : thread_(thread), instanceHandle_(Instance::Handle(thread->zone())) {}
 
 void VerifyCanonicalVisitor::VisitObject(ObjectPtr obj) {
-  // The caller of this function is walking heap pages using the
-  // ExclusivePageIterator - which holds the pages lock.
-  //
-  // If we allow handle verification, then any assignment to a handle will call
-  // `heap()->Contains()` for heap objects, which in return is implemented by
-  // walking pages using ExclusivePageIterator, which can cause a deadlock.
-  //
-  // Therefore we disable the handle verification here.
-  const bool old_verify_flag = FLAG_verify_handles;
-  FLAG_verify_handles = false;
   if (!IsInternalOnlyClassId(obj->GetClassId()) &&
       (obj->GetClassId() != kTypeArgumentsCid)) {
     if (obj->untag()->IsCanonical()) {
@@ -129,7 +119,6 @@
       ASSERT(is_canonical);
     }
   }
-  FLAG_verify_handles = old_verify_flag;
 }
 #endif  // defined(DEBUG)
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index e812345..3661d07 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -529,7 +529,7 @@
       const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
       const intptr_t payload_size = map.payload_size();
       stream->WriteFixed<uint32_t>(
-          map.ptr()->untag()->payload()->flags_and_size);
+          map.ptr()->untag()->payload()->flags_and_size());
       stream->WriteBytes(map.ptr()->untag()->payload()->data(), payload_size);
     } else if (obj.IsCodeSourceMap()) {
       const CodeSourceMap& map = CodeSourceMap::Cast(obj);
@@ -884,7 +884,8 @@
     ASSERT_EQUAL(remaining, 4);
     bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
   }
-#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) ||                 \
+    defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
   // The break instruction is a single byte, repeated to fill a word.
   bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
 #else
diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h
index 76b929d..5dbe5d6 100644
--- a/runtime/vm/instructions.h
+++ b/runtime/vm/instructions.h
@@ -15,6 +15,8 @@
 #include "vm/instructions_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/instructions_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/instructions_riscv.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 3a9f84d..ecacd45 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -87,30 +87,6 @@
 // Decodes a load sequence ending at 'end' (the last instruction of the load
 // sequence is the instruction before the one at end).  Returns a pointer to
 // the first instruction in the sequence.  Returns the register being loaded
-// and the loaded object in the output parameters 'reg' and 'obj'
-// respectively.
-uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const ObjectPool& object_pool,
-                                           Register* reg,
-                                           Object* obj) {
-  uword start = 0;
-  Instr* instr = Instr::At(end - Instr::kInstrSize);
-  if ((instr->InstructionBits() & 0xfff00000) == 0xe5900000) {
-    // ldr reg, [reg, #+offset]
-    intptr_t index = 0;
-    start = DecodeLoadWordFromPool(end, reg, &index);
-    *obj = object_pool.ObjectAt(index);
-  } else {
-    intptr_t value = 0;
-    start = DecodeLoadWordImmediate(end, reg, &value);
-    *obj = static_cast<ObjectPtr>(value);
-  }
-  return start;
-}
-
-// Decodes a load sequence ending at 'end' (the last instruction of the load
-// sequence is the instruction before the one at end).  Returns a pointer to
-// the first instruction in the sequence.  Returns the register being loaded
 // and the loaded immediate value in the output parameters 'reg' and 'value'
 // respectively.
 uword InstructionPattern::DecodeLoadWordImmediate(uword end,
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index 5bfc9bd..96ccf6c 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -32,16 +32,6 @@
   // Decodes a load sequence ending at 'end' (the last instruction of the
   // load sequence is the instruction before the one at end).  Returns the
   // address of the first instruction in the sequence.  Returns the register
-  // being loaded and the loaded object in the output parameters 'reg' and
-  // 'obj' respectively.
-  static uword DecodeLoadObject(uword end,
-                                const ObjectPool& object_pool,
-                                Register* reg,
-                                Object* obj);
-
-  // Decodes a load sequence ending at 'end' (the last instruction of the
-  // load sequence is the instruction before the one at end).  Returns the
-  // address of the first instruction in the sequence.  Returns the register
   // being loaded and the loaded immediate value in the output parameters
   // 'reg' and 'value' respectively.
   static uword DecodeLoadWordImmediate(uword end,
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index 35d0250..0c64963 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -88,34 +88,6 @@
 // Decodes a load sequence ending at 'end' (the last instruction of the load
 // sequence is the instruction before the one at end).  Returns a pointer to
 // the first instruction in the sequence.  Returns the register being loaded
-// and the loaded object in the output parameters 'reg' and 'obj'
-// respectively.
-uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const ObjectPool& object_pool,
-                                           Register* reg,
-                                           Object* obj) {
-  // 1. LoadWordFromPool
-  // or
-  // 2. LoadDecodableImmediate
-  uword start = 0;
-  Instr* instr = Instr::At(end - Instr::kInstrSize);
-  if (instr->IsLoadStoreRegOp()) {
-    // Case 1.
-    intptr_t index = 0;
-    start = DecodeLoadWordFromPool(end, reg, &index);
-    *obj = object_pool.ObjectAt(index);
-  } else {
-    // Case 2.
-    intptr_t value = 0;
-    start = DecodeLoadWordImmediate(end, reg, &value);
-    *obj = static_cast<ObjectPtr>(value);
-  }
-  return start;
-}
-
-// Decodes a load sequence ending at 'end' (the last instruction of the load
-// sequence is the instruction before the one at end).  Returns a pointer to
-// the first instruction in the sequence.  Returns the register being loaded
 // and the loaded immediate value in the output parameters 'reg' and 'value'
 // respectively.
 uword InstructionPattern::DecodeLoadWordImmediate(uword end,
@@ -344,6 +316,19 @@
   }
   // TODO(rmacnak): Loads with offsets beyond 12 bits.
 
+  if (instr->IsAddSubImmOp() && instr->SFField() &&
+      (instr->RnField() == NULL_REG)) {
+    uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
+                                         : (instr->Imm12Field());
+    if (imm == kTrueOffsetFromNull) {
+      *obj = Object::bool_true().ptr();
+      return true;
+    } else if (imm == kFalseOffsetFromNull) {
+      *obj = Object::bool_false().ptr();
+      return true;
+    }
+  }
+
   return false;
 }
 
diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h
index ecfecb6..b135c63 100644
--- a/runtime/vm/instructions_arm64.h
+++ b/runtime/vm/instructions_arm64.h
@@ -31,16 +31,6 @@
   // Decodes a load sequence ending at 'end' (the last instruction of the
   // load sequence is the instruction before the one at end).  Returns the
   // address of the first instruction in the sequence.  Returns the register
-  // being loaded and the loaded object in the output parameters 'reg' and
-  // 'obj' respectively.
-  static uword DecodeLoadObject(uword end,
-                                const ObjectPool& object_pool,
-                                Register* reg,
-                                Object* obj);
-
-  // Decodes a load sequence ending at 'end' (the last instruction of the
-  // load sequence is the instruction before the one at end).  Returns the
-  // address of the first instruction in the sequence.  Returns the register
   // being loaded and the loaded immediate value in the output parameters
   // 'reg' and 'value' respectively.
   static uword DecodeLoadWordImmediate(uword end,
diff --git a/runtime/vm/instructions_riscv.cc b/runtime/vm/instructions_riscv.cc
new file mode 100644
index 0000000..161db93
--- /dev/null
+++ b/runtime/vm/instructions_riscv.cc
@@ -0,0 +1,462 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV*.
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/instructions.h"
+#include "vm/instructions_riscv.h"
+
+#include "vm/constants.h"
+#include "vm/cpu.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/reverse_pc_lookup_cache.h"
+
+namespace dart {
+
+CallPattern::CallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      target_code_pool_index_(-1) {
+  ASSERT(code.ContainsInstructionAt(pc));
+  //          [lui,add,]lx CODE_REG, ##(pp)
+  // xxxxxxxx lx ra, ##(CODE_REG)
+  //     xxxx jalr ra
+
+  // Last instruction: jalr ra.
+  ASSERT(*reinterpret_cast<uint16_t*>(pc - 2) == 0x9082);
+  Register reg;
+  InstructionPattern::DecodeLoadWordFromPool(pc - 6, &reg,
+                                             &target_code_pool_index_);
+  ASSERT(reg == CODE_REG);
+}
+
+ICCallPattern::ICCallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      target_pool_index_(-1),
+      data_pool_index_(-1) {
+  ASSERT(code.ContainsInstructionAt(pc));
+  //          [lui,add,]lx IC_DATA_REG, ##(pp)
+  //          [lui,add,]lx CODE_REG, ##(pp)
+  // xxxxxxxx lx ra, ##(CODE_REG)
+  //     xxxx jalr ra
+
+  // Last instruction: jalr ra.
+  ASSERT(*reinterpret_cast<uint16_t*>(pc - 2) == 0x9082);
+
+  Register reg;
+  uword data_load_end = InstructionPattern::DecodeLoadWordFromPool(
+      pc - 6, &reg, &target_pool_index_);
+  ASSERT(reg == CODE_REG);
+
+  InstructionPattern::DecodeLoadWordFromPool(data_load_end, &reg,
+                                             &data_pool_index_);
+  ASSERT(reg == IC_DATA_REG);
+}
+
+NativeCallPattern::NativeCallPattern(uword pc, const Code& code)
+    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
+      end_(pc),
+      native_function_pool_index_(-1),
+      target_code_pool_index_(-1) {
+  ASSERT(code.ContainsInstructionAt(pc));
+  //          [lui,add,]lx t5, ##(pp)
+  //          [lui,add,]lx CODE_REG, ##(pp)
+  // xxxxxxxx lx ra, ##(CODE_REG)
+  //     xxxx jalr ra
+
+  // Last instruction: jalr ra.
+  ASSERT(*reinterpret_cast<uint16_t*>(pc - 2) == 0x9082);
+
+  Register reg;
+  uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool(
+      pc - 6, &reg, &target_code_pool_index_);
+  ASSERT(reg == CODE_REG);
+  InstructionPattern::DecodeLoadWordFromPool(native_function_load_end, &reg,
+                                             &native_function_pool_index_);
+  ASSERT(reg == T5);
+}
+
+CodePtr NativeCallPattern::target() const {
+  return static_cast<CodePtr>(object_pool_.ObjectAt(target_code_pool_index_));
+}
+
+void NativeCallPattern::set_target(const Code& target) const {
+  object_pool_.SetObjectAt(target_code_pool_index_, target);
+  // No need to flush the instruction cache, since the code is not modified.
+}
+
+NativeFunction NativeCallPattern::native_function() const {
+  return reinterpret_cast<NativeFunction>(
+      object_pool_.RawValueAt(native_function_pool_index_));
+}
+
+void NativeCallPattern::set_native_function(NativeFunction func) const {
+  object_pool_.SetRawValueAt(native_function_pool_index_,
+                             reinterpret_cast<uword>(func));
+}
+
+// Decodes a load sequence ending at 'end' (the last instruction of the load
+// sequence is the instruction before the one at end).  Returns a pointer to
+// the first instruction in the sequence.  Returns the register being loaded
+// and the loaded immediate value in the output parameters 'reg' and 'value'
+// respectively.
+uword InstructionPattern::DecodeLoadWordImmediate(uword end,
+                                                  Register* reg,
+                                                  intptr_t* value) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+static bool DecodeLoadX(uword end,
+                        Register* dst,
+                        Register* base,
+                        intptr_t* offset,
+                        intptr_t* length) {
+  Instr instr(*reinterpret_cast<uint32_t*>(end - 4));
+#if XLEN == 32
+  if (instr.opcode() == LOAD && instr.funct3() == LW) {
+#elif XLEN == 64
+  if (instr.opcode() == LOAD && instr.funct3() == LD) {
+#endif
+    *dst = instr.rd();
+    *base = instr.rs1();
+    *offset = instr.itype_imm();
+    *length = 4;
+    return true;
+  }
+
+  CInstr cinstr(*reinterpret_cast<uint16_t*>(end - 2));
+#if XLEN == 32
+  if (cinstr.opcode() == C_LW) {
+#elif XLEN == 64
+  if (cinstr.opcode() == C_LD) {
+#endif
+    *dst = cinstr.rdp();
+    *base = cinstr.rs1p();
+#if XLEN == 32
+    *offset = cinstr.mem4_imm();
+#elif XLEN == 64
+    *offset = cinstr.mem8_imm();
+#endif
+    *length = 2;
+    return true;
+  }
+
+  return false;
+}
+
+static bool DecodeLUI(uword end,
+                      Register* dst,
+                      intptr_t* imm,
+                      intptr_t* length) {
+  Instr instr(*reinterpret_cast<uint32_t*>(end - 4));
+  if (instr.opcode() == LUI) {
+    *dst = instr.rd();
+    *imm = instr.utype_imm();
+    *length = 4;
+    return true;
+  }
+
+  CInstr cinstr(*reinterpret_cast<uint16_t*>(end - 2));
+  if (cinstr.opcode() == C_LUI) {
+    *dst = cinstr.rd();
+    *imm = cinstr.u_imm();
+    *length = 2;
+    return true;
+  }
+
+  return false;
+}
+
+// See comment in instructions_arm64.h
+uword InstructionPattern::DecodeLoadWordFromPool(uword end,
+                                                 Register* reg,
+                                                 intptr_t* index) {
+  // [c.]lx dst, offset(pp)
+  // or
+  // [c.]lui dst, hi
+  // c.add dst, dst, pp
+  // [c.]lx dst, lo(dst)
+
+  Register base;
+  intptr_t lo, length;
+  if (!DecodeLoadX(end, reg, &base, &lo, &length)) {
+    UNREACHABLE();
+  }
+
+  if (base == PP) {
+    // PP is untagged on RISCV.
+    *index = ObjectPool::IndexFromOffset(lo - kHeapObjectTag);
+    return end - length;
+  }
+  ASSERT(base == *reg);
+  end -= length;
+
+  CInstr add_instr(*reinterpret_cast<uint16_t*>(end - 2));
+  ASSERT(add_instr.opcode() ==
+         C_MV);  // Not C_ADD, which extends past the opcode proper.
+  ASSERT(add_instr.rd() == base);
+  ASSERT(add_instr.rs1() == base);
+  ASSERT(add_instr.rs2() == PP);
+  end -= 2;
+
+  Register dst;
+  intptr_t hi;
+  if (!DecodeLUI(end, &dst, &hi, &length)) {
+    UNREACHABLE();
+  }
+  ASSERT(dst == base);
+  // PP is untagged on RISC-V.
+  *index = ObjectPool::IndexFromOffset(hi + lo - kHeapObjectTag);
+  return end - length;
+}
+
+bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) {
+  ASSERT(code.ContainsInstructionAt(pc));
+  uint16_t parcel = *reinterpret_cast<uint16_t*>(pc);
+  if (IsCInstruction(parcel)) {
+    CInstr instr(parcel);
+#if XLEN == 32
+    if (instr.opcode() == C_LW) {
+      intptr_t offset = instr.mem4_imm();
+#elif XLEN == 64
+    if (instr.opcode() == C_LD) {
+      intptr_t offset = instr.mem8_imm();
+#endif
+      if (instr.rs1p() == PP) {
+        // PP is untagged on RISC-V.
+        ASSERT(Utils::IsAligned(offset, kWordSize));
+        intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
+        const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool());
+        if (!pool.IsNull() && (index < pool.Length()) &&
+            (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+          *obj = pool.ObjectAt(index);
+          return true;
+        }
+      } else if (instr.rs1p() == THR) {
+        return Thread::ObjectAtOffset(offset, obj);
+      }
+    }
+  } else {
+    Instr instr(*reinterpret_cast<uint32_t*>(pc));
+#if XLEN == 32
+    if (instr.opcode() == LOAD && instr.funct3() == LW) {
+#elif XLEN == 64
+    if (instr.opcode() == LOAD && instr.funct3() == LD) {
+#endif
+      intptr_t offset = instr.itype_imm();
+      if (instr.rs1() == PP) {
+        // PP is untagged on RISC-V.
+        ASSERT(Utils::IsAligned(offset, kWordSize));
+        intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
+        const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool());
+        if (!pool.IsNull() && (index < pool.Length()) &&
+            (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+          *obj = pool.ObjectAt(index);
+          return true;
+        }
+      } else if (instr.rs1() == THR) {
+        return Thread::ObjectAtOffset(offset, obj);
+      }
+    }
+    if ((instr.opcode() == OPIMM) && (instr.funct3() == ADDI) &&
+        (instr.rs1() == NULL_REG)) {
+      if (instr.itype_imm() == 0) {
+        *obj = Object::null();
+        return true;
+      }
+      if (instr.itype_imm() == kTrueOffsetFromNull) {
+        *obj = Object::bool_true().ptr();
+        return true;
+      }
+      if (instr.itype_imm() == kFalseOffsetFromNull) {
+        *obj = Object::bool_false().ptr();
+        return true;
+      }
+    }
+  }
+
+  // TODO(riscv): Loads with offsets beyond 12 bits.
+  return false;
+}
+
+// Encodes a load sequence ending at 'end'. Encodes a fixed length two
+// instruction load from the pool pointer in PP using the destination
+// register reg as a temporary for the base address.
+// Assumes that the location has already been validated for patching.
+void InstructionPattern::EncodeLoadWordFromPoolFixed(uword end,
+                                                     int32_t offset) {
+  UNIMPLEMENTED();
+}
+
+CodePtr CallPattern::TargetCode() const {
+  return static_cast<CodePtr>(object_pool_.ObjectAt(target_code_pool_index_));
+}
+
+void CallPattern::SetTargetCode(const Code& target) const {
+  object_pool_.SetObjectAt(target_code_pool_index_, target);
+  // No need to flush the instruction cache, since the code is not modified.
+}
+
+ObjectPtr ICCallPattern::Data() const {
+  return object_pool_.ObjectAt(data_pool_index_);
+}
+
+void ICCallPattern::SetData(const Object& data) const {
+  ASSERT(data.IsArray() || data.IsICData() || data.IsMegamorphicCache());
+  object_pool_.SetObjectAt(data_pool_index_, data);
+}
+
+CodePtr ICCallPattern::TargetCode() const {
+  return static_cast<CodePtr>(object_pool_.ObjectAt(target_pool_index_));
+}
+
+void ICCallPattern::SetTargetCode(const Code& target) const {
+  object_pool_.SetObjectAt(target_pool_index_, target);
+  // No need to flush the instruction cache, since the code is not modified.
+}
+
+SwitchableCallPatternBase::SwitchableCallPatternBase(
+    const ObjectPool& object_pool)
+    : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {}
+
+ObjectPtr SwitchableCallPatternBase::data() const {
+  return object_pool_.ObjectAt(data_pool_index_);
+}
+
+void SwitchableCallPatternBase::SetData(const Object& data) const {
+  ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
+  object_pool_.SetObjectAt(data_pool_index_, data);
+}
+
+SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
+    : SwitchableCallPatternBase(ObjectPool::Handle(code.GetObjectPool())) {
+  ASSERT(code.ContainsInstructionAt(pc));
+  UNIMPLEMENTED();
+}
+
+uword SwitchableCallPattern::target_entry() const {
+  return Code::Handle(Code::RawCast(object_pool_.ObjectAt(target_pool_index_)))
+      .MonomorphicEntryPoint();
+}
+
+void SwitchableCallPattern::SetTarget(const Code& target) const {
+  ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
+  object_pool_.SetObjectAt(target_pool_index_, target);
+}
+
+BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc)
+    : SwitchableCallPatternBase(ObjectPool::Handle(
+          IsolateGroup::Current()->object_store()->global_object_pool())) {
+  //      [lui,add,]lx RA, ##(pp)
+  //      [lui,add,]lx IC_DATA_REG, ##(pp)
+  // xxxx jalr RA
+
+  // Last instruction: jalr ra.
+  ASSERT(*reinterpret_cast<uint16_t*>(pc - 2) == 0x9082);
+
+  Register reg;
+  uword target_load_end = InstructionPattern::DecodeLoadWordFromPool(
+      pc - 2, &reg, &data_pool_index_);
+  ASSERT_EQUAL(reg, IC_DATA_REG);
+
+  InstructionPattern::DecodeLoadWordFromPool(target_load_end, &reg,
+                                             &target_pool_index_);
+  ASSERT_EQUAL(reg, RA);
+}
+
+uword BareSwitchableCallPattern::target_entry() const {
+  return object_pool_.RawValueAt(target_pool_index_);
+}
+
+void BareSwitchableCallPattern::SetTarget(const Code& target) const {
+  ASSERT(object_pool_.TypeAt(target_pool_index_) ==
+         ObjectPool::EntryType::kImmediate);
+  object_pool_.SetRawValueAt(target_pool_index_,
+                             target.MonomorphicEntryPoint());
+}
+
+ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {}
+
+bool ReturnPattern::IsValid() const {
+  return *reinterpret_cast<uint16_t*>(pc_) == 0x8082;
+}
+
+bool PcRelativeCallPattern::IsValid() const {
+  Instr aupic(*reinterpret_cast<uint32_t*>(pc_));
+  if (aupic.opcode() != AUIPC) return false;
+  Instr jalr(*reinterpret_cast<uint32_t*>(pc_ + 4));
+  if (jalr.opcode() != JALR) return false;
+  if (aupic.rd() != jalr.rs1()) return false;
+  if (jalr.rd() != RA) return false;
+  return true;
+}
+
+bool PcRelativeTailCallPattern::IsValid() const {
+  Instr aupic(*reinterpret_cast<uint32_t*>(pc_));
+  if (aupic.opcode() != AUIPC) return false;
+  Instr jr(*reinterpret_cast<uint32_t*>(pc_ + 4));
+  if (jr.opcode() != JALR) return false;
+  if (aupic.rd() != jr.rs1()) return false;
+  if (jr.rd() != ZR) return false;
+  return true;
+}
+
+void PcRelativeTrampolineJumpPattern::Initialize() {
+  UNREACHABLE();
+}
+
+int32_t PcRelativeTrampolineJumpPattern::distance() {
+  UNREACHABLE();
+  return 0;
+}
+
+void PcRelativeTrampolineJumpPattern::set_distance(int32_t distance) {
+  UNREACHABLE();
+}
+
+bool PcRelativeTrampolineJumpPattern::IsValid() const {
+  UNREACHABLE();
+  return false;
+}
+
+intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
+  // Calls to the type testing stubs look like:
+  //   lx s3, ...
+  //   lx Rn, idx(pp)
+  //   jalr s3
+  // where Rn = TypeTestABI::kSubtypeTestCacheReg.
+
+  // Ensure the caller of the type testing stub (whose return address is [pc_])
+  // branched via `blr R9` or a pc-relative call.
+  if (*reinterpret_cast<uint16_t*>(pc_ - 2) == 0x9982) {  // jalr s3
+    // indirect call
+    //     xxxx c.jalr s3
+    Register reg;
+    intptr_t pool_index = -1;
+    InstructionPattern::DecodeLoadWordFromPool(pc_ - 2, &reg, &pool_index);
+    ASSERT_EQUAL(reg, TypeTestABI::kSubtypeTestCacheReg);
+    return pool_index;
+  } else {
+    ASSERT(FLAG_precompiled_mode);
+    // pc-relative call
+    // xxxxxxxx aupic ra, hi
+    // xxxxxxxx jalr ra, lo
+    Instr jalr(*reinterpret_cast<uint32_t*>(pc_ - 4));
+    ASSERT(jalr.opcode() == JALR);
+    Instr auipc(*reinterpret_cast<uint32_t*>(pc_ - 8));
+    ASSERT(auipc.opcode() == AUIPC);
+
+    Register reg;
+    intptr_t pool_index = -1;
+    InstructionPattern::DecodeLoadWordFromPool(pc_ - 8, &reg, &pool_index);
+    ASSERT_EQUAL(reg, TypeTestABI::kSubtypeTestCacheReg);
+    return pool_index;
+  }
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/instructions_riscv.h b/runtime/vm/instructions_riscv.h
new file mode 100644
index 0000000..bdea5d0
--- /dev/null
+++ b/runtime/vm/instructions_riscv.h
@@ -0,0 +1,254 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Classes that describe assembly patterns as used by inline caches.
+
+#ifndef RUNTIME_VM_INSTRUCTIONS_RISCV_H_
+#define RUNTIME_VM_INSTRUCTIONS_RISCV_H_
+
+#ifndef RUNTIME_VM_INSTRUCTIONS_H_
+#error Do not include instructions_riscv.h directly; use instructions.h instead.
+#endif
+
+#include "vm/allocation.h"
+#include "vm/constants.h"
+#include "vm/native_function.h"
+#include "vm/tagged_pointer.h"
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/compiler/assembler/assembler.h"
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+namespace dart {
+
+class Code;
+class ICData;
+class Object;
+class ObjectPool;
+
+class InstructionPattern : public AllStatic {
+ public:
+  // Decodes a load sequence ending at 'end' (the last instruction of the
+  // load sequence is the instruction before the one at end).  Returns the
+  // address of the first instruction in the sequence.  Returns the register
+  // being loaded and the loaded immediate value in the output parameters
+  // 'reg' and 'value' respectively.
+  static uword DecodeLoadWordImmediate(uword end,
+                                       Register* reg,
+                                       intptr_t* value);
+
+  // Decodes a load sequence ending at 'end' (the last instruction of the
+  // load sequence is the instruction before the one at end).  Returns the
+  // address of the first instruction in the sequence.  Returns the register
+  // being loaded and the index in the pool being read from in the output
+  // parameters 'reg' and 'index' respectively.
+  // IMPORANT: When generating code loading values from pool on ARM64 use
+  // LoadWordFromPool macro instruction instead of emitting direct load.
+  // The macro instruction takes care of pool offsets that can't be
+  // encoded as immediates.
+  static uword DecodeLoadWordFromPool(uword end,
+                                      Register* reg,
+                                      intptr_t* index);
+
+  // Encodes a load sequence ending at 'end'. Encodes a fixed length two
+  // instruction load from the pool pointer in PP using the destination
+  // register reg as a temporary for the base address.
+  static void EncodeLoadWordFromPoolFixed(uword end, int32_t offset);
+};
+
+class CallPattern : public ValueObject {
+ public:
+  CallPattern(uword pc, const Code& code);
+
+  CodePtr TargetCode() const;
+  void SetTargetCode(const Code& target) const;
+
+ private:
+  const ObjectPool& object_pool_;
+
+  intptr_t target_code_pool_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(CallPattern);
+};
+
+class ICCallPattern : public ValueObject {
+ public:
+  ICCallPattern(uword pc, const Code& caller_code);
+
+  ObjectPtr Data() const;
+  void SetData(const Object& data) const;
+
+  CodePtr TargetCode() const;
+  void SetTargetCode(const Code& target) const;
+
+ private:
+  const ObjectPool& object_pool_;
+
+  intptr_t target_pool_index_;
+  intptr_t data_pool_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(ICCallPattern);
+};
+
+class NativeCallPattern : public ValueObject {
+ public:
+  NativeCallPattern(uword pc, const Code& code);
+
+  CodePtr target() const;
+  void set_target(const Code& target) const;
+
+  NativeFunction native_function() const;
+  void set_native_function(NativeFunction target) const;
+
+ private:
+  const ObjectPool& object_pool_;
+
+  uword end_;
+  intptr_t native_function_pool_index_;
+  intptr_t target_code_pool_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(NativeCallPattern);
+};
+
+// Instance call that can switch between a direct monomorphic call, an IC call,
+// and a megamorphic call.
+//   load guarded cid            load ICData             load MegamorphicCache
+//   load monomorphic target <-> load ICLookup stub  ->  load MMLookup stub
+//   call target.entry           call stub.entry         call stub.entry
+class SwitchableCallPatternBase : public ValueObject {
+ public:
+  explicit SwitchableCallPatternBase(const ObjectPool& object_pool);
+
+  ObjectPtr data() const;
+  void SetData(const Object& data) const;
+
+ protected:
+  const ObjectPool& object_pool_;
+  intptr_t data_pool_index_;
+  intptr_t target_pool_index_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SwitchableCallPatternBase);
+};
+
+// See [SwitchableCallBase] for a switchable calls in general.
+//
+// The target slot is always a [Code] object: Either the code of the
+// monomorphic function or a stub code.
+class SwitchableCallPattern : public SwitchableCallPatternBase {
+ public:
+  SwitchableCallPattern(uword pc, const Code& code);
+
+  uword target_entry() const;
+  void SetTarget(const Code& target) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SwitchableCallPattern);
+};
+
+// See [SwitchableCallBase] for a switchable calls in general.
+//
+// The target slot is always a direct entrypoint address: Either the entry point
+// of the monomorphic function or a stub entry point.
+class BareSwitchableCallPattern : public SwitchableCallPatternBase {
+ public:
+  explicit BareSwitchableCallPattern(uword pc);
+
+  uword target_entry() const;
+  void SetTarget(const Code& target) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BareSwitchableCallPattern);
+};
+
+class ReturnPattern : public ValueObject {
+ public:
+  explicit ReturnPattern(uword pc);
+
+  // ret = 1 compressed instruction
+  static const intptr_t kLengthInBytes = 2;
+
+  int pattern_length_in_bytes() const { return kLengthInBytes; }
+
+  bool IsValid() const;
+
+ private:
+  const uword pc_;
+};
+
+class PcRelativePatternBase : public ValueObject {
+ public:
+  static constexpr intptr_t kLengthInBytes = 8;
+  static constexpr intptr_t kLowerCallingRange =
+      static_cast<int32_t>(0x80000000);
+  static constexpr intptr_t kUpperCallingRange =
+      static_cast<int32_t>(0x7FFFFFFE);
+
+  explicit PcRelativePatternBase(uword pc) : pc_(pc) {}
+
+  int32_t distance() {
+    Instr auipc(*reinterpret_cast<uint32_t*>(pc_));
+    Instr jalr(*reinterpret_cast<uint32_t*>(pc_ + 4));
+    return auipc.utype_imm() + jalr.itype_imm();
+  }
+
+  void set_distance(int32_t distance) {
+    Instr auipc(*reinterpret_cast<uint32_t*>(pc_));
+    Instr jalr(*reinterpret_cast<uint32_t*>(pc_ + 4));
+    intx_t imm = distance;
+    intx_t lo = imm << (XLEN - 12) >> (XLEN - 12);
+    intx_t hi = (imm - lo) << (XLEN - 32) >> (XLEN - 32);
+    *reinterpret_cast<uint32_t*>(pc_) =
+        EncodeUTypeImm(hi) | EncodeRd(auipc.rd()) | EncodeOpcode(AUIPC);
+    *reinterpret_cast<uint32_t*>(pc_ + 4) =
+        EncodeITypeImm(lo) | EncodeRs1(jalr.rs1()) | EncodeFunct3(F3_0) |
+        EncodeRd(jalr.rd()) | EncodeOpcode(JALR);
+  }
+
+  bool IsValid() const;
+
+ protected:
+  uword pc_;
+};
+
+class PcRelativeCallPattern : public PcRelativePatternBase {
+ public:
+  explicit PcRelativeCallPattern(uword pc) : PcRelativePatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
+class PcRelativeTailCallPattern : public PcRelativePatternBase {
+ public:
+  explicit PcRelativeTailCallPattern(uword pc) : PcRelativePatternBase(pc) {}
+
+  bool IsValid() const;
+};
+
+// RISC-V never uses trampolines since the range of the regular pc-relative call
+// is enough.
+class PcRelativeTrampolineJumpPattern : public ValueObject {
+ public:
+  static constexpr intptr_t kLengthInBytes = 8;
+  static constexpr intptr_t kLowerCallingRange =
+      -(DART_INT64_C(1) << 31) + kLengthInBytes;
+  static constexpr intptr_t kUpperCallingRange = (DART_INT64_C(1) << 31) - 1;
+
+  explicit PcRelativeTrampolineJumpPattern(uword pattern_start)
+      : pattern_start_(pattern_start) {
+    USE(pattern_start_);
+  }
+
+  void Initialize();
+
+  int32_t distance();
+  void set_distance(int32_t distance);
+  bool IsValid() const;
+
+ private:
+  uword pattern_start_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_INSTRUCTIONS_RISCV_H_
diff --git a/runtime/vm/instructions_riscv_test.cc b/runtime/vm/instructions_riscv_test.cc
new file mode 100644
index 0000000..4f7ecb1
--- /dev/null
+++ b/runtime/vm/instructions_riscv_test.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/cpu.h"
+#include "vm/instructions.h"
+#include "vm/stub_code.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+#define __ assembler->
+
+ASSEMBLER_TEST_GENERATE(Call, assembler) {
+  // Code is generated, but not executed. Just parsed with CallPattern
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  __ JumpAndLinkPatchable(StubCode::InvokeDartCode());
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Call, test) {
+  // The return address, which must be the address of an instruction contained
+  // in the code, points to the Ret instruction above, i.e. one instruction
+  // before the end of the code buffer.
+  uword end = test->payload_start() + test->code().Size();
+  CallPattern call(end - CInstr::kInstrSize, test->code());
+  EXPECT_EQ(StubCode::InvokeDartCode().ptr(), call.TargetCode());
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 1048e4e..39e320c 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -489,6 +489,11 @@
         EnableAssertsBit::update(value, isolate_group_flags_);
   }
 
+  void set_branch_coverage(bool value) {
+    isolate_group_flags_ =
+        BranchCoverageBit::update(value, isolate_group_flags_);
+  }
+
 #if !defined(PRODUCT)
 #if !defined(DART_PRECOMPILED_RUNTIME)
   bool HasAttemptedReload() const {
@@ -1347,6 +1352,13 @@
     UpdateIsolateFlagsBit<IsKernelIsolateBit>(value);
   }
 
+  bool is_service_registered() const {
+    return LoadIsolateFlagsBit<IsServiceRegisteredBit>();
+  }
+  void set_is_service_registered(bool value) {
+    UpdateIsolateFlagsBit<IsServiceRegisteredBit>(value);
+  }
+
   const DispatchTable* dispatch_table() const {
     return group()->dispatch_table();
   }
@@ -1540,7 +1552,8 @@
   V(HasAttemptedStepping)                                                      \
   V(ShouldPausePostServiceRequest)                                             \
   V(CopyParentCode)                                                            \
-  V(IsSystemIsolate)
+  V(IsSystemIsolate)                                                           \
+  V(IsServiceRegistered)
 
   // Isolate specific flags.
   enum FlagBits {
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 11d116a..c61d766 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -991,7 +991,11 @@
     TransitionVMToNative transition(Thread::Current());
     retval = KernelIsolate::CompileToKernel(
         root_lib_url, nullptr, 0, modified_scripts_count, modified_scripts,
-        true, false, nullptr);
+        /*incremental_compile=*/true,
+        /*snapshot_compile=*/false,
+        /*package_config=*/nullptr,
+        /*multiroot_filepaths=*/nullptr,
+        /*multiroot_scheme=*/nullptr, FLAG_sound_null_safety);
   }
   if (retval.status != Dart_KernelCompilationStatus_Ok) {
     if (retval.kernel != nullptr) {
@@ -1556,9 +1560,8 @@
           ASSERT(new_cls.is_enum_class() == old_cls.is_enum_class());
           if (new_cls.is_enum_class() && new_cls.is_finalized()) {
             new_cls.ReplaceEnum(this, old_cls);
-          } else {
-            new_cls.CopyStaticFieldValues(this, old_cls);
           }
+          new_cls.CopyStaticFieldValues(this, old_cls);
           old_cls.PatchFieldsAndFunctions();
           old_cls.MigrateImplicitStaticClosures(this, new_cls);
         }
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index dfac508..1d6e8ac 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -37,7 +37,9 @@
       param_values_(NULL),
       num_params_(0),
       offset_(0),
-      count_(-1) {
+      count_(-1),
+      include_private_members_(true),
+      ignore_object_depth_(0) {
   ObjectIdRing* ring = NULL;
   Isolate* isolate = Isolate::Current();
   if (isolate != NULL) {
@@ -90,6 +92,10 @@
                  "request %s\n",
                  Dart::UptimeMillis(), main_port, isolate_name, method_);
   }
+  const char* kIncludePrivateMembersKey = "_includePrivateMembers";
+  if (HasParam(kIncludePrivateMembersKey)) {
+    include_private_members_ = ParamIs(kIncludePrivateMembersKey, "true");
+  }
   buffer()->Printf("{\"jsonrpc\":\"2.0\", \"result\":");
 }
 
@@ -368,49 +374,61 @@
   PrintProperty("id", id_zone_->GetServiceId(o));
 }
 
+#define PRIVATE_NAME_CHECK()                                                   \
+  if (!IsAllowableKey(name) || ignore_object_depth_ > 0) return
+
 void JSONStream::PrintProperty(const char* name, const ServiceEvent* event) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(event);
 }
 
 void JSONStream::PrintProperty(const char* name, Breakpoint* bpt) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(bpt);
 }
 
 void JSONStream::PrintProperty(const char* name, TokenPosition tp) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(tp);
 }
 
 void JSONStream::PrintProperty(const char* name, Metric* metric) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(metric);
 }
 
 void JSONStream::PrintProperty(const char* name, MessageQueue* queue) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(queue);
 }
 
 void JSONStream::PrintProperty(const char* name, Isolate* isolate) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(isolate);
 }
 
 void JSONStream::PrintProperty(const char* name,
                                const TimelineEvent* timeline_event) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(timeline_event);
 }
 
 void JSONStream::PrintProperty(const char* name,
                                const TimelineEventBlock* timeline_event_block) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(timeline_event_block);
 }
 
 void JSONStream::PrintfProperty(const char* name, const char* format, ...) {
+  PRIVATE_NAME_CHECK();
   va_list args;
   va_start(args, format);
   writer_.VPrintfProperty(name, format, args);
@@ -462,11 +480,13 @@
 }
 
 void JSONStream::PrintProperty(const char* name, const Object& o, bool ref) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValue(o, ref);
 }
 
 void JSONStream::PrintPropertyVM(const char* name, bool ref) {
+  PRIVATE_NAME_CHECK();
   PrintPropertyName(name);
   PrintValueVM(ref);
 }
@@ -503,6 +523,13 @@
   if (end_token_pos.IsReal()) {
     location.AddProperty("endTokenPos", end_token_pos);
   }
+  intptr_t line = -1;
+  intptr_t column = -1;
+  // Add line and column information if token_pos is real.
+  if (script.GetTokenLocation(token_pos, &line, &column)) {
+    location.AddProperty("line", line);
+    location.AddProperty("column", column);
+  }
 }
 
 void JSONObject::AddLocation(const BreakpointLocation* bpt_loc) const {
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index a00f266..5b37379 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -9,6 +9,7 @@
 #include "platform/allocation.h"
 #include "platform/text_buffer.h"
 #include "vm/json_writer.h"
+#include "vm/os.h"
 #include "vm/service.h"
 #include "vm/token_position.h"
 
@@ -102,6 +103,18 @@
 
   void set_reply_port(Dart_Port port);
 
+  bool include_private_members() const { return include_private_members_; }
+  void set_include_private_members(bool include_private_members) {
+    include_private_members_ = include_private_members;
+  }
+
+  bool IsAllowableKey(const char* key) {
+    if (include_private_members_) {
+      return true;
+    }
+    return *key != '_';
+  }
+
   void SetParams(const char** param_keys,
                  const char** param_values,
                  intptr_t num_params);
@@ -167,15 +180,41 @@
   void PostNullReply(Dart_Port port);
 
   void OpenObject(const char* property_name = NULL) {
+    if (ignore_object_depth_ > 0 ||
+        (property_name != nullptr && !IsAllowableKey(property_name))) {
+      ignore_object_depth_++;
+      return;
+    }
     writer_.OpenObject(property_name);
   }
-  void CloseObject() { writer_.CloseObject(); }
-  void UncloseObject() { writer_.UncloseObject(); }
+  void CloseObject() {
+    if (ignore_object_depth_ > 0) {
+      ignore_object_depth_--;
+      return;
+    }
+    writer_.CloseObject();
+  }
+  void UncloseObject() {
+    // This should be updated to handle unclosing a private object if we need
+    // to handle that case, which we don't currently.
+    writer_.UncloseObject();
+  }
 
   void OpenArray(const char* property_name = NULL) {
+    if (ignore_object_depth_ > 0 ||
+        (property_name != nullptr && !IsAllowableKey(property_name))) {
+      ignore_object_depth_++;
+      return;
+    }
     writer_.OpenArray(property_name);
   }
-  void CloseArray() { writer_.CloseArray(); }
+  void CloseArray() {
+    if (ignore_object_depth_ > 0) {
+      ignore_object_depth_--;
+      return;
+    }
+    writer_.CloseArray();
+  }
 
   void PrintValueNull() { writer_.PrintValueNull(); }
   void PrintValueBool(bool b) { writer_.PrintValueBool(b); }
@@ -211,46 +250,67 @@
 
   void PrintServiceId(const Object& o);
 
+#define PRIVATE_NAME_CHECK()                                                   \
+  if (!IsAllowableKey(name) || ignore_object_depth_ > 0) {                     \
+    return;                                                                    \
+  }
+
   void PrintPropertyBool(const char* name, bool b) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintPropertyBool(name, b);
   }
   void PrintProperty(const char* name, intptr_t i) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty(name, i);
   }
   void PrintProperty64(const char* name, int64_t i) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty64(name, i);
   }
   void PrintPropertyTimeMillis(const char* name, int64_t millis) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty64(name, millis);
   }
   void PrintPropertyTimeMicros(const char* name, int64_t micros) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty64(name, micros);
   }
   void PrintProperty(const char* name, double d) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty(name, d);
   }
   void PrintPropertyBase64(const char* name,
                            const uint8_t* bytes,
                            intptr_t length) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintPropertyBase64(name, bytes, length);
   }
   void PrintProperty(const char* name, const char* s) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintProperty(name, s);
   }
   bool PrintPropertyStr(const char* name,
                         const String& s,
                         intptr_t offset,
                         intptr_t count) {
+    if (!IsAllowableKey(name)) {
+      return false;
+    }
     return writer_.PrintPropertyStr(name, s, offset, count);
   }
   void PrintPropertyNoEscape(const char* name, const char* s) {
+    PRIVATE_NAME_CHECK();
     writer_.PrintPropertyNoEscape(name, s);
   }
   void PrintfProperty(const char* name, const char* format, ...)
       PRINTF_ATTRIBUTE(3, 4);
   void VPrintfProperty(const char* name, const char* format, va_list args) {
+    PRIVATE_NAME_CHECK();
     writer_.VPrintfProperty(name, format, args);
   }
+
+#undef PRIVATE_NAME_CHECK
+
   void PrintProperty(const char* name, const Object& o, bool ref = true);
 
   void PrintProperty(const char* name, const ServiceEvent* event);
@@ -285,7 +345,8 @@
   intptr_t offset_;
   intptr_t count_;
   int64_t setup_time_micros_;
-
+  bool include_private_members_;
+  intptr_t ignore_object_depth_;
   friend class JSONObject;
   friend class JSONArray;
   friend class TimelineEvent;
diff --git a/runtime/vm/json_test.cc b/runtime/vm/json_test.cc
index ed619c2..672369c 100644
--- a/runtime/vm/json_test.cc
+++ b/runtime/vm/json_test.cc
@@ -182,7 +182,8 @@
       "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"Null\",\"location\":{"
       "\"type\":\"SourceLocation\",\"script\":{\"type\":\"@Script\","
       "\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core\\/null.dart\",\"_"
-      "kind\":\"kernel\"},\"tokenPos\":925,\"endTokenPos\":1165},\"library\":{"
+      "kind\":\"kernel\"},\"tokenPos\":925,\"endTokenPos\":1165,\"line\":23,"
+      "\"column\":1},\"library\":{"
       "\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\",\"name\":\"dart."
       "core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\",\"fixedId\":true,"
       "\"id\":\"\",\"valueAsString\":\"null\"},{\"object_key\":{\"type\":\"@"
@@ -190,7 +191,8 @@
       "\"fixedId\":true,\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"dart:core\\/null.dart\",\"_kind\":\"kernel\"},"
-      "\"tokenPos\":925,\"endTokenPos\":1165},\"library\":{\"type\":\"@"
+      "\"tokenPos\":925,\"endTokenPos\":1165,\"line\":23,\"column\":1},"
+      "\"library\":{\"type\":\"@"
       "Library\",\"fixedId\":true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":"
       "\"dart:core\"}},\"kind\":\"Null\",\"fixedId\":true,\"id\":\"\","
       "\"valueAsString\":\"null\"}}]",
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 891a2b7..ff0cfa2 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
 
 // Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 75;
-static const uint32_t kMaxSupportedKernelFormatVersion = 75;
+static const uint32_t kMinSupportedKernelFormatVersion = 76;
+static const uint32_t kMaxSupportedKernelFormatVersion = 76;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 8926b5d..7e098bf 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -721,6 +721,7 @@
       const char* package_config,
       const char* multiroot_filepaths,
       const char* multiroot_scheme,
+      intptr_t default_null_safety,
       const MallocGrowableArray<char*>* experimental_flags,
       const char* original_working_directory,
       Dart_KernelCompilationVerbosityLevel verbosity) {
@@ -809,7 +810,7 @@
         (isolate_group != nullptr)
             ? (isolate_group->null_safety() ? kNullSafetyOptionStrong
                                             : kNullSafetyOptionWeak)
-            : FLAG_sound_null_safety;
+            : default_null_safety;
 
     intptr_t num_experimental_flags = experimental_flags->length();
     Dart_CObject** experimental_flags_array =
@@ -1052,6 +1053,7 @@
     const char* package_config,
     const char* multiroot_filepaths,
     const char* multiroot_scheme,
+    intptr_t default_null_safety,
     Dart_KernelCompilationVerbosityLevel verbosity) {
   // Start the kernel Isolate if it is not already running.
   if (!Start()) {
@@ -1076,8 +1078,8 @@
       kCompileTag, kernel_port, script_uri, platform_kernel,
       platform_kernel_size, source_file_count, source_files,
       incremental_compile, snapshot_compile, package_config,
-      multiroot_filepaths, multiroot_scheme, experimental_flags_, NULL,
-      verbosity);
+      multiroot_filepaths, multiroot_scheme, default_null_safety,
+      experimental_flags_, NULL, verbosity);
 }
 
 bool KernelIsolate::DetectNullSafety(const char* script_uri,
@@ -1095,7 +1097,8 @@
   KernelCompilationRequest request;
   Dart_KernelCompilationResult result = request.SendAndWaitForResponse(
       kDetectNullabilityTag, kernel_port, script_uri, nullptr, -1, 0, nullptr,
-      false, false, package_config, nullptr, nullptr, experimental_flags_,
+      false, false, package_config, nullptr, nullptr,
+      /*default_null_safety=*/kNullSafetyOptionUnspecified, experimental_flags_,
       original_working_directory, Dart_KernelCompilationVerbosityLevel_Error);
   return result.null_safety;
 }
@@ -1112,8 +1115,8 @@
   KernelCompilationRequest request;
   return request.SendAndWaitForResponse(
       kListDependenciesTag, kernel_port, NULL, NULL, 0, 0, NULL, false, false,
-      NULL, NULL, NULL, experimental_flags_, NULL,
-      Dart_KernelCompilationVerbosityLevel_Error);
+      NULL, NULL, NULL, /*default_null_safety=*/kNullSafetyOptionUnspecified,
+      experimental_flags_, NULL, Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 Dart_KernelCompilationResult KernelIsolate::AcceptCompilation() {
@@ -1130,8 +1133,8 @@
   KernelCompilationRequest request;
   return request.SendAndWaitForResponse(
       kAcceptTag, kernel_port, NULL, NULL, 0, 0, NULL, true, false, NULL, NULL,
-      NULL, experimental_flags_, NULL,
-      Dart_KernelCompilationVerbosityLevel_Error);
+      NULL, /*default_null_safety=*/kNullSafetyOptionUnspecified,
+      experimental_flags_, NULL, Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
@@ -1177,8 +1180,9 @@
   KernelCompilationRequest request;
   return request.SendAndWaitForResponse(
       kUpdateSourcesTag, kernel_port, NULL, NULL, 0, source_files_count,
-      source_files, true, false, NULL, NULL, NULL, experimental_flags_, NULL,
-      Dart_KernelCompilationVerbosityLevel_Error);
+      source_files, true, false, NULL, NULL, NULL,
+      /*default_null_safety=*/kNullSafetyOptionUnspecified, experimental_flags_,
+      NULL, Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 void KernelIsolate::NotifyAboutIsolateGroupShutdown(
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index 5880beb..d5d5297 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -55,6 +55,7 @@
       const char* package_config = NULL,
       const char* multiroot_filepaths = NULL,
       const char* multiroot_scheme = NULL,
+      intptr_t default_null_safety = kNullSafetyOptionUnspecified,
       Dart_KernelCompilationVerbosityLevel verbosity =
           Dart_KernelCompilationVerbosityLevel_All);
 
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 39689f6..0507227 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -706,6 +706,7 @@
 
   // Load the "evaluate:source" expression evaluation library.
   ASSERT(expression_evaluation_library_.IsNull());
+  ASSERT(H.GetExpressionEvaluationClass().IsNull());
   ASSERT(H.GetExpressionEvaluationFunction().IsNull());
   H.SetExpressionEvaluationRealClass(real_class);
   const Object& result = Object::Handle(Z, LoadProgram(true));
@@ -1449,6 +1450,9 @@
   // they are not reachable anymore and we never look them up by name.
   const bool register_class =
       library.ptr() != expression_evaluation_library_.ptr();
+  if (!register_class) {
+    H.SetExpressionEvaluationClass(*out_class);
+  }
 
   if (loading_native_wrappers_library_ || !register_class) {
     FinishClassLoading(*out_class, library, toplevel_class, class_offset,
diff --git a/runtime/vm/malloc_hooks_unsupported.cc b/runtime/vm/malloc_hooks_unsupported.cc
index 5b666d1..11bc115 100644
--- a/runtime/vm/malloc_hooks_unsupported.cc
+++ b/runtime/vm/malloc_hooks_unsupported.cc
@@ -69,25 +69,7 @@
     return true;
   }
 #endif
-#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
-#if defined(DART_USE_MALLINFO2)
-  struct mallinfo2 info = mallinfo2();
-#else
-  struct mallinfo info = mallinfo();
-#endif  // defined(DART_USE_MALLINFO2)
-  *used = info.uordblks;
-  *capacity = *used + info.fordblks;
-  *implementation = "unknown";
-  return true;
-#elif defined(DART_HOST_OS_MACOS)
-  struct mstats stats = mstats();
-  *used = stats.bytes_used;
-  *capacity = stats.bytes_total;
-  *implementation = "macos";
-  return true;
-#else
   return false;
-#endif
 #else
   return false;
 #endif
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 6fd3ef4..d3cb9c6 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1035,8 +1035,7 @@
     CompressedStackMaps::initializeHandle(
         empty_compressed_stackmaps_,
         static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
-    empty_compressed_stackmaps_->StoreNonPointer(
-        &empty_compressed_stackmaps_->untag()->payload()->flags_and_size, 0);
+    empty_compressed_stackmaps_->untag()->payload()->set_flags_and_size(0);
     empty_compressed_stackmaps_->SetCanonical();
   }
 
@@ -1159,10 +1158,14 @@
 
   String& error_str = String::Handle();
   error_str = String::New(
-      "Internal Dart data pointers have been acquired, please release them "
-      "using Dart_TypedDataReleaseData.",
+      "Callbacks into the Dart VM are currently prohibited. Either there are "
+      "outstanding pointers from Dart_TypedDataAcquireData that have not been "
+      "released with Dart_TypedDataReleaseData, or a finalizer is running.",
       Heap::kOld);
-  *typed_data_acquire_error_ = ApiError::New(error_str, Heap::kOld);
+  *no_callbacks_error_ = ApiError::New(error_str, Heap::kOld);
+  error_str = String::New(
+      "No api calls are allowed while unwind is in progress", Heap::kOld);
+  *unwind_in_progress_error_ = UnwindError::New(error_str, Heap::kOld);
   error_str = String::New("SnapshotWriter Error", Heap::kOld);
   *snapshot_writer_error_ =
       LanguageError::New(error_str, Report::kError, Heap::kOld);
@@ -1239,8 +1242,10 @@
   ASSERT(bool_false_->IsBool());
   ASSERT(smi_illegal_cid_->IsSmi());
   ASSERT(smi_zero_->IsSmi());
-  ASSERT(!typed_data_acquire_error_->IsSmi());
-  ASSERT(typed_data_acquire_error_->IsApiError());
+  ASSERT(!no_callbacks_error_->IsSmi());
+  ASSERT(no_callbacks_error_->IsApiError());
+  ASSERT(!unwind_in_progress_error_->IsSmi());
+  ASSERT(unwind_in_progress_error_->IsUnwindError());
   ASSERT(!snapshot_writer_error_->IsSmi());
   ASSERT(snapshot_writer_error_->IsLanguageError());
   ASSERT(!branch_offset_error_->IsSmi());
@@ -2505,15 +2510,6 @@
 
 #if defined(DEBUG)
 bool Object::InVMIsolateHeap() const {
-  if (FLAG_verify_handles && ptr()->untag()->InVMIsolateHeap()) {
-    Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
-    uword addr = UntaggedObject::ToAddr(ptr());
-    if (!vm_isolate_heap->Contains(addr)) {
-      ASSERT(FLAG_write_protect_code);
-      addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr()));
-      ASSERT(vm_isolate_heap->Contains(addr));
-    }
-  }
   return ptr()->untag()->InVMIsolateHeap();
 }
 #endif  // DEBUG
@@ -2605,19 +2601,6 @@
       cid = kInstanceCid;
     }
     ASSERT(vtable() == builtin_vtables_[cid]);
-    if (FLAG_verify_handles && ptr_->IsHeapObject()) {
-      Heap* isolate_heap = IsolateGroup::Current()->heap();
-      if (!isolate_heap->new_space()->scavenging()) {
-        Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
-        uword addr = UntaggedObject::ToAddr(ptr_);
-        if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
-          ASSERT(FLAG_write_protect_code);
-          addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr_));
-          ASSERT(isolate_heap->Contains(addr) ||
-                 vm_isolate_heap->Contains(addr));
-        }
-      }
-    }
   }
 #endif
 }
@@ -7135,9 +7118,12 @@
 }
 
 uword Function::Hash() const {
-  const uword hash = String::HashRawSymbol(name());
+  uword hash = String::HashRawSymbol(name());
+  if (IsClosureFunction()) {
+    hash = hash ^ token_pos().Hash();
+  }
   if (untag()->owner()->IsClass()) {
-    return hash ^ Class::RawCast(untag()->owner())->untag()->id();
+    hash = hash ^ Class::RawCast(untag()->owner())->untag()->id();
   }
   return hash;
 }
@@ -8168,9 +8154,11 @@
   // being inlined (for now).
   if (ForceOptimize()) {
     if (IsFfiTrampoline()) {
-      // The CallSiteInliner::InlineCall asserts in PrepareGraphs that
-      // GraphEntryInstr::SuccessorCount() == 1, but FFI trampoline has two
-      // entries (a normal and a catch entry).
+      // We currently don't support inlining FFI trampolines. Some of them
+      // are naturally non-inlinable because they contain a try/catch block,
+      // but this condition is broader than strictly necessary.
+      // The work necessary for inlining FFI trampolines is tracked by
+      // http://dartbug.com/45055.
       return false;
     }
     return CompilerState::Current().is_aot();
@@ -8180,7 +8168,7 @@
     return false;
   }
 
-  return is_inlinable() && !is_external() && !is_generated_body();
+  return is_inlinable() && !is_generated_body();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -10162,8 +10150,9 @@
     return true;
   }
 
-  // If table dispatch is disabled, all instance calls use switchable calls.
-  if (!(FLAG_precompiled_mode && FLAG_use_table_dispatch)) {
+  // AOT mode uses table dispatch.
+  // In JIT mode all instance calls use switchable calls.
+  if (!FLAG_precompiled_mode) {
     return true;
   }
 
@@ -14805,7 +14794,11 @@
   THR_Print("ObjectPool len:%" Pd " {\n", Length());
   for (intptr_t i = 0; i < Length(); i++) {
     intptr_t offset = OffsetFromIndex(i);
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+    THR_Print("  %" Pd "(pp) ", offset + kHeapObjectTag);
+#else
     THR_Print("  [pp+0x%" Px "] ", offset);
+#endif
     if (TypeAt(i) == EntryType::kTaggedObject) {
       const Object& obj = Object::Handle(ObjectAt(i));
       THR_Print("%s (obj)\n", obj.ToCString());
@@ -15074,12 +15067,10 @@
         Heap::kOld, CompressedStackMaps::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(
-        &result.untag()->payload()->flags_and_size,
+    result.untag()->payload()->set_flags_and_size(
         UntaggedCompressedStackMaps::GlobalTableBit::encode(is_global_table) |
-            UntaggedCompressedStackMaps::UsesTableBit::encode(
-                uses_global_table) |
-            UntaggedCompressedStackMaps::SizeField::encode(size));
+        UntaggedCompressedStackMaps::UsesTableBit::encode(uses_global_table) |
+        UntaggedCompressedStackMaps::SizeField::encode(size));
     auto cursor =
         result.UnsafeMutableNonPointer(result.untag()->payload()->data());
     memcpy(cursor, payload, size);  // NOLINT
@@ -21296,10 +21287,8 @@
   ASSERT(Utils::IsUint(sizeof(untag()->type_class_id_) * kBitsPerByte, id));
   // We should never need a Type object for a top-level class.
   ASSERT(!ClassTable::IsTopLevelCid(id));
-  // We must allow Types with kIllegalCid type class ids, because the class
-  // used for evaluating expressions inside a instance method call context
-  // from the debugger is not registered (and thus has kIllegalCid as an id).
-  ASSERT(id == kIllegalCid || !IsInternalOnlyClassId(id));
+  ASSERT(id != kIllegalCid);
+  ASSERT(!IsInternalOnlyClassId(id));
   StoreNonPointer(&untag()->type_class_id_, id);
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 67a9e89..b830f12 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -68,6 +68,7 @@
 class CodeStatistics;
 class IsolateGroupReloadContext;
 class ObjectGraphCopier;
+class NativeArguments;
 
 #define REUSABLE_FORWARD_DECLARATION(name) class Reusable##name##HandleScope;
 REUSABLE_HANDLE_LIST(REUSABLE_FORWARD_DECLARATION)
@@ -236,6 +237,8 @@
   OBJECT_SERVICE_SUPPORT(object)                                               \
   friend class Object;
 
+extern "C" void DFLRT_ExitSafepoint(NativeArguments __unusable_);
+
 #define HEAP_OBJECT_IMPLEMENTATION(object, super)                              \
   OBJECT_IMPLEMENTATION(object, super);                                        \
   Untagged##object* untag() const {                                            \
@@ -244,7 +247,8 @@
   }                                                                            \
   SNAPSHOT_SUPPORT(object)                                                     \
   friend class StackFrame;                                                     \
-  friend class Thread;
+  friend class Thread;                                                         \
+  friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);
 
 // This macro is used to denote types that do not have a sub-type.
 #define FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)        \
@@ -270,7 +274,8 @@
   SNAPSHOT_SUPPORT(rettype)                                                    \
   friend class Object;                                                         \
   friend class StackFrame;                                                     \
-  friend class Thread;
+  friend class Thread;                                                         \
+  friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);
 
 #define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)                        \
   FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, object, super)
@@ -453,7 +458,8 @@
   V(Bool, bool_false)                                                          \
   V(Smi, smi_illegal_cid)                                                      \
   V(Smi, smi_zero)                                                             \
-  V(ApiError, typed_data_acquire_error)                                        \
+  V(ApiError, no_callbacks_error)                                              \
+  V(UnwindError, unwind_in_progress_error)                                     \
   V(LanguageError, snapshot_writer_error)                                      \
   V(LanguageError, branch_offset_error)                                        \
   V(LanguageError, speculative_inlining_error)                                 \
@@ -5417,6 +5423,16 @@
   static const intptr_t kPolymorphicEntryOffsetJIT = 48;
   static const intptr_t kMonomorphicEntryOffsetAOT = 8;
   static const intptr_t kPolymorphicEntryOffsetAOT = 20;
+#elif defined(TARGET_ARCH_RISCV32)
+  static const intptr_t kMonomorphicEntryOffsetJIT = 6;
+  static const intptr_t kPolymorphicEntryOffsetJIT = 42;
+  static const intptr_t kMonomorphicEntryOffsetAOT = 6;
+  static const intptr_t kPolymorphicEntryOffsetAOT = 16;
+#elif defined(TARGET_ARCH_RISCV64)
+  static const intptr_t kMonomorphicEntryOffsetJIT = 6;
+  static const intptr_t kPolymorphicEntryOffsetJIT = 42;
+  static const intptr_t kMonomorphicEntryOffsetAOT = 6;
+  static const intptr_t kPolymorphicEntryOffsetAOT = 16;
 #else
 #error Missing entry offsets for current architecture
 #endif
@@ -5507,8 +5523,11 @@
     return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
   }
 
-  uint32_t Hash() const {
-    return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart()), Size());
+  uint32_t Hash() const { return Hash(ptr()); }
+
+  static uint32_t Hash(const InstructionsPtr instr) {
+    return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
+                     Size(instr));
   }
 
   CodeStatistics* stats() const;
@@ -5868,6 +5887,11 @@
     return memcmp(untag(), other.untag(), InstanceSize(Length())) == 0;
   }
 
+  uint32_t Hash() const {
+    NoSafepointScope no_safepoint;
+    return HashBytes(Data(), Length());
+  }
+
   void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
 
  private:
@@ -5883,7 +5907,7 @@
   uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
   static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
     return UntaggedCompressedStackMaps::SizeField::decode(
-        raw->untag()->payload()->flags_and_size);
+        raw->untag()->payload()->flags_and_size());
   }
 
   const uint8_t* data() const { return ptr()->untag()->payload()->data(); }
@@ -5891,8 +5915,8 @@
   // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
   bool Equals(const CompressedStackMaps& other) const {
     // All of the table flags and payload size must match.
-    if (untag()->payload()->flags_and_size !=
-        other.untag()->payload()->flags_and_size) {
+    if (untag()->payload()->flags_and_size() !=
+        other.untag()->payload()->flags_and_size()) {
       return false;
     }
     NoSafepointScope no_safepoint;
@@ -5902,7 +5926,7 @@
 
   static intptr_t HeaderSize() {
     return sizeof(UntaggedCompressedStackMaps) +
-           sizeof(UntaggedCompressedStackMaps::Payload);
+           sizeof(UntaggedCompressedStackMaps::Payload::FlagsAndSizeHeader);
   }
   static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
     return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
@@ -5920,13 +5944,13 @@
   bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
   static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
     return UntaggedCompressedStackMaps::UsesTableBit::decode(
-        raw->untag()->payload()->flags_and_size);
+        raw->untag()->payload()->flags_and_size());
   }
 
   bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
   static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
     return UntaggedCompressedStackMaps::GlobalTableBit::decode(
-        raw->untag()->payload()->flags_and_size);
+        raw->untag()->payload()->flags_and_size());
   }
 
   static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
@@ -5976,18 +6000,18 @@
 
     uintptr_t payload_size() const {
       return UntaggedCompressedStackMaps::SizeField::decode(
-          payload()->flags_and_size);
+          payload()->flags_and_size());
     }
     const uint8_t* data() const { return payload()->data(); }
 
     bool UsesGlobalTable() const {
       return UntaggedCompressedStackMaps::UsesTableBit::decode(
-          payload()->flags_and_size);
+          payload()->flags_and_size());
     }
 
     bool IsGlobalTable() const {
       return UntaggedCompressedStackMaps::GlobalTableBit::decode(
-          payload()->flags_and_size);
+          payload()->flags_and_size());
     }
 
    private:
@@ -6683,7 +6707,7 @@
   // embedded objects in the instructions using pointer_offsets.
 
   static const intptr_t kBytesPerElement =
-      sizeof(reinterpret_cast<UntaggedCode*>(0)->data()[0]);
+      sizeof(reinterpret_cast<UntaggedCode*>(kOffsetOfPtr)->data()[0]);
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   struct ArrayTraits {
@@ -12110,22 +12134,6 @@
     cid = kInstanceCid;
   }
   set_vtable(builtin_vtables_[cid]);
-#if defined(DEBUG)
-  if (FLAG_verify_handles && ptr_->IsHeapObject() && (ptr_ != Object::null())) {
-    Heap* isolate_heap = IsolateGroup::Current()->heap();
-    // TODO(rmacnak): Remove after rewriting StackFrame::VisitObjectPointers
-    // to not use handles.
-    if (!isolate_heap->new_space()->scavenging()) {
-      Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
-      uword addr = UntaggedObject::ToAddr(ptr_);
-      if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
-        ASSERT(FLAG_write_protect_code);
-        addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr_));
-        ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
-      }
-    }
-  }
-#endif
 }
 
 intptr_t Field::HostOffset() const {
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 5ed79a5..87874b8 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -192,9 +192,6 @@
 
 void Class::CopyStaticFieldValues(ProgramReloadContext* reload_context,
                                   const Class& old_cls) const {
-  // We only update values for non-enum classes.
-  const bool update_values = !is_enum_class();
-
   const Array& old_field_list = Array::Handle(old_cls.fields());
   Field& old_field = Field::Handle();
   String& old_name = String::Handle();
@@ -215,7 +212,7 @@
         if (field.is_static()) {
           // We only copy values if requested and if the field is not a const
           // field. We let const fields be updated with a reload.
-          if (update_values && !field.is_const()) {
+          if (!field.is_const()) {
             // Make new field point to the old field value so that both
             // old and new code see and update same value.
             reload_context->isolate_group()->FreeStaticField(field);
@@ -305,17 +302,18 @@
   ASSERT(is_finalized());
   ASSERT(old_enum.is_finalized());
 
-  Zone* zone = Thread::Current()->zone();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
 
-  Array& enum_fields = Array::Handle(zone);
   Field& field = Field::Handle(zone);
   String& enum_ident = String::Handle();
   Instance& old_enum_value = Instance::Handle(zone);
   Instance& enum_value = Instance::Handle(zone);
   // The E.values array.
-  Instance& old_enum_values = Instance::Handle(zone);
+  Array& old_enum_values = Array::Handle(zone);
   // The E.values array.
-  Instance& enum_values = Instance::Handle(zone);
+  Array& enum_values = Array::Handle(zone);
   // The E._deleted_enum_sentinel instance.
   Instance& old_deleted_enum_sentinel = Instance::Handle(zone);
   // The E._deleted_enum_sentinel instance.
@@ -327,31 +325,29 @@
   TIR_Print("Replacing enum `%s`\n", String::Handle(Name()).ToCString());
 
   {
+    field = old_enum.LookupStaticField(Symbols::Values());
+    if (!field.IsNull()) {
+      ASSERT(field.is_static() && field.is_const());
+      old_enum_values ^= field.StaticConstFieldValue();
+      ASSERT(!old_enum_values.IsNull());
+    } else {
+      old_enum_values = Array::empty_array().ptr();
+    }
+
+    field = old_enum.LookupStaticField(Symbols::_DeletedEnumSentinel());
+    ASSERT(!field.IsNull() && field.is_static() && field.is_const());
+    old_deleted_enum_sentinel ^= field.StaticConstFieldValue();
+    ASSERT(!old_deleted_enum_sentinel.IsNull());
+
+    field = object_store->enum_name_field();
+    ASSERT(!field.IsNull());
+
     UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.ptr());
     // Build a map of all enum name -> old enum instance.
-    enum_fields = old_enum.fields();
-    for (intptr_t i = 0; i < enum_fields.Length(); i++) {
-      field = Field::RawCast(enum_fields.At(i));
-      enum_ident = field.name();
-      if (!field.is_static()) {
-        // Enum instances are only held in static fields.
-        continue;
-      }
-      ASSERT(field.is_const());
-      if (enum_ident.Equals(Symbols::Values())) {
-        old_enum_values = Instance::RawCast(field.StaticConstFieldValue());
-        // Non-enum instance.
-        continue;
-      }
-      if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
-        old_deleted_enum_sentinel =
-            Instance::RawCast(field.StaticConstFieldValue());
-        // Non-enum instance.
-        continue;
-      }
-      old_enum_value = Instance::RawCast(field.StaticConstFieldValue());
-
+    for (intptr_t i = 0, n = old_enum_values.Length(); i < n; ++i) {
+      old_enum_value ^= old_enum_values.At(i);
       ASSERT(!old_enum_value.IsNull());
+      enum_ident ^= old_enum_value.GetField(field);
       VTIR_Print("Element %s being added to mapping\n", enum_ident.ToCString());
       bool update = enum_map.UpdateOrInsert(enum_ident, old_enum_value);
       VTIR_Print("Element %s added to mapping\n", enum_ident.ToCString());
@@ -364,31 +360,30 @@
 
   bool enums_deleted = false;
   {
+    field = LookupStaticField(Symbols::Values());
+    if (!field.IsNull()) {
+      ASSERT(field.is_static() && field.is_const());
+      enum_values ^= field.StaticConstFieldValue();
+      ASSERT(!enum_values.IsNull());
+    } else {
+      enum_values = Array::empty_array().ptr();
+    }
+
+    field = LookupStaticField(Symbols::_DeletedEnumSentinel());
+    ASSERT(!field.IsNull() && field.is_static() && field.is_const());
+    deleted_enum_sentinel ^= field.StaticConstFieldValue();
+    ASSERT(!deleted_enum_sentinel.IsNull());
+
+    field = object_store->enum_name_field();
+    ASSERT(!field.IsNull());
+
     UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.ptr());
     // Add a become mapping from the old instances to the new instances.
-    enum_fields = fields();
-    for (intptr_t i = 0; i < enum_fields.Length(); i++) {
-      field = Field::RawCast(enum_fields.At(i));
-      enum_ident = field.name();
-      if (!field.is_static()) {
-        // Enum instances are only held in static fields.
-        continue;
-      }
-      ASSERT(field.is_const());
-      if (enum_ident.Equals(Symbols::Values())) {
-        enum_values = Instance::RawCast(field.StaticConstFieldValue());
-        // Non-enum instance.
-        continue;
-      }
-      if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
-        deleted_enum_sentinel =
-            Instance::RawCast(field.StaticConstFieldValue());
-        // Non-enum instance.
-        continue;
-      }
-      enum_value = Instance::RawCast(field.StaticConstFieldValue());
-
+    for (intptr_t i = 0, n = enum_values.Length(); i < n; ++i) {
+      enum_value ^= enum_values.At(i);
       ASSERT(!enum_value.IsNull());
+      enum_ident ^= enum_value.GetField(field);
+
       old_enum_value ^= enum_map.GetOrNull(enum_ident);
       if (old_enum_value.IsNull()) {
         VTIR_Print("New element %s was not found in mapping\n",
@@ -408,13 +403,9 @@
   }
 
   // Map the old E.values array to the new E.values array.
-  ASSERT(!old_enum_values.IsNull());
-  ASSERT(!enum_values.IsNull());
   reload_context->AddBecomeMapping(old_enum_values, enum_values);
 
   // Map the old E._deleted_enum_sentinel to the new E._deleted_enum_sentinel.
-  ASSERT(!old_deleted_enum_sentinel.IsNull());
-  ASSERT(!deleted_enum_sentinel.IsNull());
   reload_context->AddBecomeMapping(old_deleted_enum_sentinel,
                                    deleted_enum_sentinel);
 
diff --git a/runtime/vm/object_riscv_test.cc b/runtime/vm/object_riscv_test.cc
new file mode 100644
index 0000000..2b798c9
--- /dev/null
+++ b/runtime/vm/object_riscv_test.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/assert.h"
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/object.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+#define __ assembler->
+
+// Generate a simple dart code sequence.
+// This is used to test Code and Instruction object creation.
+void GenerateIncrement(compiler::Assembler* assembler) {
+  __ EnterFrame(1 * kWordSize);
+  __ li(A0, 0);
+  __ PushRegister(A0);
+  __ addi(A0, A0, 1);
+  __ sx(A0, compiler::Address(SP));
+  __ lx(A1, compiler::Address(SP));
+  __ addi(A1, A1, 1);
+  __ PopRegister(A0);
+  __ mv(A0, A1);
+  __ LeaveFrame();
+  __ ret();
+}
+
+// Generate a dart code sequence that embeds a string object in it.
+// This is used to test Embedded String objects in the instructions.
+void GenerateEmbedStringInCode(compiler::Assembler* assembler,
+                               const char* str) {
+  const String& string_object =
+      String::ZoneHandle(String::New(str, Heap::kOld));
+  __ EnterStubFrame();
+  __ LoadObject(A0, string_object);
+  __ LeaveStubFrame();
+  __ ret();
+}
+
+// Generate a dart code sequence that embeds a smi object in it.
+// This is used to test Embedded Smi objects in the instructions.
+void GenerateEmbedSmiInCode(compiler::Assembler* assembler, intptr_t value) {
+  const Smi& smi_object = Smi::ZoneHandle(Smi::New(value));
+  const intx_t val = static_cast<intx_t>(smi_object.ptr());
+  __ LoadImmediate(A0, val);
+  __ ret();
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 9fc1c99..8ce45e3 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -87,6 +87,10 @@
   set_preallocated_unhandled_exception(UnhandledException::Handle(
       zone, UnhandledException::New(Instance::Cast(out_of_memory),
                                     preallocated_stack_trace)));
+  const UnwindError& preallocated_unwind_error =
+      UnwindError::Handle(zone, UnwindError::New(String::Handle(
+                                    zone, String::New("isolate is exiting"))));
+  set_preallocated_unwind_error(preallocated_unwind_error);
 
   return Error::null();
 }
@@ -357,6 +361,8 @@
   if (list_class_.load() == Type::null()) {
     ASSERT(non_nullable_list_rare_type_.load() == Type::null());
     ASSERT(non_nullable_map_rare_type_.load() == Type::null());
+    ASSERT(enum_index_field_.load() == Field::null());
+    ASSERT(enum_name_field_.load() == Field::null());
     ASSERT(_object_equals_function_.load() == Function::null());
     ASSERT(_object_hash_code_function_.load() == Function::null());
     ASSERT(_object_to_string_function_.load() == Function::null());
@@ -378,6 +384,21 @@
     type ^= cls.RareType();
     non_nullable_map_rare_type_.store(type.ptr());
 
+    auto& field = Field::Handle(zone);
+
+    cls = core_lib.LookupClassAllowPrivate(Symbols::_Enum());
+    ASSERT(!cls.IsNull());
+    const auto& error = cls.EnsureIsFinalized(thread);
+    ASSERT(error == Error::null());
+
+    field = cls.LookupInstanceField(Symbols::Index());
+    ASSERT(!field.IsNull());
+    enum_index_field_.store(field.ptr());
+
+    field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name());
+    ASSERT(!field.IsNull());
+    enum_name_field_.store(field.ptr());
+
     auto& function = Function::Handle(zone);
 
     function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 03125b2..3d77c61 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -47,6 +47,8 @@
   LAZY_CORE(Class, list_class)                                                 \
   LAZY_CORE(Type, non_nullable_list_rare_type)                                 \
   LAZY_CORE(Type, non_nullable_map_rare_type)                                  \
+  LAZY_CORE(Field, enum_index_field)                                           \
+  LAZY_CORE(Field, enum_name_field)                                            \
   LAZY_CORE(Function, _object_equals_function)                                 \
   LAZY_CORE(Function, _object_hash_code_function)                              \
   LAZY_CORE(Function, _object_to_string_function)                              \
@@ -308,6 +310,7 @@
 #define ISOLATE_OBJECT_STORE_FIELD_LIST(R_, RW)                                \
   RW(UnhandledException, preallocated_unhandled_exception)                     \
   RW(StackTrace, preallocated_stack_trace)                                     \
+  RW(UnwindError, preallocated_unwind_error)                                   \
   RW(Array, dart_args_1)                                                       \
   RW(Array, dart_args_2)                                                       \
   R_(GrowableObjectArray, resume_capabilities)                                 \
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 5d78dc1..aed7558 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -276,6 +276,7 @@
   static const uint32_t EM_X86_64 = 62;
   static const uint32_t EM_ARM = 40;
   static const uint32_t EM_AARCH64 = 183;
+  static const uint32_t EM_RISCV = 243;
 
   static uint32_t GetElfMachineArchitecture() {
 #if TARGET_ARCH_IA32
@@ -286,6 +287,8 @@
     return EM_ARM;
 #elif TARGET_ARCH_ARM64
     return EM_AARCH64;
+#elif TARGET_ARCH_RISCV32 || TARGET_ARCH_RISCV64
+    return EM_RISCV;
 #else
     UNREACHABLE();
     return 0;
@@ -501,7 +504,8 @@
 // into a architecture specific file e.g: os_ia32_linux.cc
 intptr_t OS::ActivationFrameAlignment() {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64)
+    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV32) ||              \
+    defined(TARGET_ARCH_RISCV64)
   const int kMinimumAlignment = 16;
 #elif defined(TARGET_ARCH_ARM)
   const int kMinimumAlignment = 8;
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index f1f721b..8ff785b 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -535,12 +535,8 @@
   }
   return false;
 }
-#elif defined(TARGET_ARCH_ARM)
-bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
-  ASSERT(return_address != NULL);
-  return false;
-}
-#elif defined(TARGET_ARCH_ARM64)
+#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                \
+    defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
   ASSERT(return_address != NULL);
   return false;
@@ -796,6 +792,30 @@
   uword* fp_;
 };
 
+// The layout of C stack frames.
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) ||                       \
+    defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+// +-------------+
+// | saved IP/LR |
+// +-------------+
+// | saved FP    |  <- FP
+// +-------------+
+static constexpr intptr_t kHostSavedCallerPcSlotFromFp = 1;
+static constexpr intptr_t kHostSavedCallerFpSlotFromFp = 0;
+#elif defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
+// +-------------+
+// |             | <- FP
+// +-------------+
+// | saved RA    |
+// +-------------+
+// | saved FP    |
+// +-------------+
+static constexpr intptr_t kHostSavedCallerPcSlotFromFp = -1;
+static constexpr intptr_t kHostSavedCallerFpSlotFromFp = -2;
+#else
+#error What architecture?
+#endif
+
 // If the VM is compiled without frame pointers (which is the default on
 // recent GCC versions with optimizing enabled) the stack walking code may
 // fail.
@@ -893,7 +913,7 @@
  private:
   uword* CallerPC(uword* fp) const {
     ASSERT(fp != NULL);
-    uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp;
+    uword* caller_pc_ptr = fp + kHostSavedCallerPcSlotFromFp;
     // This may actually be uninitialized, by design (see class comment above).
     MSAN_UNPOISON(caller_pc_ptr, kWordSize);
     ASAN_UNPOISON(caller_pc_ptr, kWordSize);
@@ -902,7 +922,7 @@
 
   uword* CallerFP(uword* fp) const {
     ASSERT(fp != NULL);
-    uword* caller_fp_ptr = fp + kSavedCallerFpSlotFromFp;
+    uword* caller_fp_ptr = fp + kHostSavedCallerFpSlotFromFp;
     // This may actually be uninitialized, by design (see class comment above).
     MSAN_UNPOISON(caller_fp_ptr, kWordSize);
     ASAN_UNPOISON(caller_fp_ptr, kWordSize);
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 9d57230..d813ce9 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -1020,7 +1020,7 @@
 
   static inline uword Hash(Key key) {
     ASSERT(!key->IsNull());
-    return Utils::WordHash(key->Length());
+    return Utils::WordHash(key->Hash());
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
@@ -1070,7 +1070,14 @@
 
   static inline uword Hash(Key key) {
     ASSERT(!key->IsNull());
-    return Utils::WordHash(key->Length());
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
+    const intptr_t len = key->Length();
+    uint32_t hash = Utils::WordHash(len);
+    for (intptr_t i = 0; i < len; ++i) {
+      hash =
+          CombineHashes(hash, Utils::WordHash(static_cast<uword>(key->At(i))));
+    }
+    return hash;
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
@@ -1128,6 +1135,9 @@
   };
 
   StackZone stack_zone(thread);
+  // ArrayKeyValueTrait::Hash is based on object addresses, so make
+  // sure GC doesn't happen and doesn't move objects.
+  NoSafepointScope no_safepoint;
   DedupListsVisitor visitor(thread->zone());
   WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
 }
@@ -1178,7 +1188,12 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline uword Hash(Key key) { return Utils::WordHash(key->Size()); }
+  static inline uword Hash(Key key) {
+    ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
+    return Utils::WordHash(
+        CombineHashes(Instructions::Hash(key->instructions()),
+                      static_cast<uword>(key->static_calls_target_table())));
+  }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     // In AOT, disabled code objects should not be considered for deduplication.
@@ -1385,6 +1400,9 @@
 
   if (FLAG_precompiled_mode) {
     StackZone stack_zone(thread);
+    // CodeKeyValueTrait::Hash is based on object addresses, so make
+    // sure GC doesn't happen and doesn't move objects.
+    NoSafepointScope no_safepoint;
     DedupInstructionsWithSameMetadataVisitor visitor(thread->zone());
     WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
     visitor.PostProcess(thread->isolate_group());
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b0b62cd..ff0a766 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1987,11 +1987,26 @@
   VISIT_NOTHING();
 
  public:
-  struct Payload {
+  // Note: AOT snapshots pack these structures without any padding in between
+  // so payload structure should not have any alignment requirements.
+  // alignas(1) is here to trigger a compiler error if we violate this.
+  struct alignas(1) Payload {
+    using FlagsAndSizeHeader = uint32_t;
+
     // The most significant bits are the length of the encoded payload, in
     // bytes (excluding the header itself). The low bits determine the
     // expected payload contents, as described below.
-    uint32_t flags_and_size;
+    DART_FORCE_INLINE FlagsAndSizeHeader flags_and_size() const {
+      // Note: |this| does not necessarily satisfy alignment requirements
+      // of uint32_t so we should use bit_cast.
+      return bit_copy<FlagsAndSizeHeader, Payload>(*this);
+    }
+
+    DART_FORCE_INLINE void set_flags_and_size(FlagsAndSizeHeader value) {
+      // Note: |this| does not necessarily satisfy alignment requirements
+      // of uint32_t hence the byte copy below.
+      memcpy(reinterpret_cast<void*>(this), &value, sizeof(value));  // NOLINT
+    }
 
     // Variable length data follows here. The contents of the payload depend on
     // the type of CompressedStackMaps (CSM) being represented. There are three
@@ -2044,10 +2059,15 @@
     // done where the payload is decoded up to the entry whose PC offset
     // is greater or equal to the given PC.
 
-    uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
-    const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+    uint8_t* data() {
+      return reinterpret_cast<uint8_t*>(this) + sizeof(FlagsAndSizeHeader);
+    }
+
+    const uint8_t* data() const {
+      return reinterpret_cast<const uint8_t*>(this) +
+             sizeof(FlagsAndSizeHeader);
+    }
   };
-  static_assert(sizeof(Payload) == sizeof(uint32_t));
 
  private:
   // We are using OPEN_ARRAY_START rather than embedding Payload directly into
@@ -2055,17 +2075,20 @@
   // padding at the end of UntaggedCompressedStackMaps - so we would not be
   // able to use sizeof(UntaggedCompressedStackMaps) as the size of the header
   // anyway.
-  Payload* payload() { OPEN_ARRAY_START(Payload, uint32_t); }
-  const Payload* payload() const { OPEN_ARRAY_START(Payload, uint32_t); }
+  Payload* payload() { OPEN_ARRAY_START(Payload, uint8_t); }
+  const Payload* payload() const { OPEN_ARRAY_START(Payload, uint8_t); }
 
-  class GlobalTableBit : public BitField<uint32_t, bool, 0, 1> {};
-  class UsesTableBit
-      : public BitField<uint32_t, bool, GlobalTableBit::kNextBit, 1> {};
+  class GlobalTableBit
+      : public BitField<Payload::FlagsAndSizeHeader, bool, 0, 1> {};
+  class UsesTableBit : public BitField<Payload::FlagsAndSizeHeader,
+                                       bool,
+                                       GlobalTableBit::kNextBit,
+                                       1> {};
   class SizeField
-      : public BitField<uint32_t,
-                        uint32_t,
+      : public BitField<Payload::FlagsAndSizeHeader,
+                        Payload::FlagsAndSizeHeader,
                         UsesTableBit::kNextBit,
-                        sizeof(Payload::flags_and_size) * kBitsPerByte -
+                        sizeof(Payload::FlagsAndSizeHeader) * kBitsPerByte -
                             UsesTableBit::kNextBit> {};
 
   friend class Object;
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index a6ad932..1d2ea7a 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -2684,7 +2684,7 @@
   intptr_t preload_characters =
       Utils::Minimum(static_cast<intptr_t>(4), eats_at_least);
   if (compiler->one_byte()) {
-#if !defined(DART_COMPRESSED_POINTERS)
+#if !defined(DART_COMPRESSED_POINTERS) && !defined(TARGET_ARCH_RISCV32)
     if (preload_characters > 4) preload_characters = 4;
     // We can't preload 3 characters because there is no machine instruction
     // to do that.  We can't just load 4 because we could be reading
@@ -2696,7 +2696,7 @@
     if (preload_characters > 2) preload_characters = 2;
 #endif
   } else {
-#if !defined(DART_COMPRESSED_POINTERS)
+#if !defined(DART_COMPRESSED_POINTERS) && !defined(TARGET_ARCH_RISCV32)
     if (preload_characters > 2) preload_characters = 2;
 #else
     // Ensure LoadCodeUnitsInstr can always produce a Smi. See
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index c693c02..b5b7854 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3608,11 +3608,47 @@
   ASSERT(thread->top_exit_frame_info() != 0);
 
   ASSERT(thread->execution_state() == Thread::kThreadInVM);
+  if (thread->is_unwind_in_progress()) {
+    // Clean up safepoint unwind error marker to prevent safepoint tripping.
+    // The safepoint marker will get restored just before jumping back
+    // to generated code.
+    thread->SetUnwindErrorInProgress(false);
+    NoSafepointScope no_safepoint;
+    Error unwind_error;
+    unwind_error ^=
+        thread->isolate()->isolate_object_store()->preallocated_unwind_error();
+    Exceptions::PropagateError(unwind_error);
+  }
   thread->ExitSafepoint();
+
   TRACE_RUNTIME_CALL("%s", "ExitSafepoint done");
 }
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint);
 
+// This is expected to be invoked when jumping to destination frame,
+// during exception handling.
+extern "C" void DFLRT_ExitSafepointIgnoreUnwindInProgress(
+    NativeArguments __unusable_) {
+  CHECK_STACK_ALIGNMENT;
+  TRACE_RUNTIME_CALL("%s", "ExitSafepointIgnoreUnwindInProgress");
+  Thread* thread = Thread::Current();
+  ASSERT(thread->top_exit_frame_info() != 0);
+
+  ASSERT(thread->execution_state() == Thread::kThreadInVM);
+
+  // Compared to ExitSafepoint above we are going to ignore
+  // is_unwind_in_progress flag because this is called as part of JumpToFrame
+  // exception handler - we want this transition to complete so that the next
+  // safepoint check does error propagation.
+  thread->ExitSafepoint();
+
+  TRACE_RUNTIME_CALL("%s", "ExitSafepointIgnoreUnwindInProgress done");
+}
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepointIgnoreUnwindInProgress,
+                              0,
+                              false,
+                              &DFLRT_ExitSafepointIgnoreUnwindInProgress);
+
 // Not registered as a runtime entry because we can't use Thread to look it up.
 static Thread* GetThreadForNativeCallback(uword callback_id,
                                           uword return_address) {
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 0870d45..e08ebbd 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -58,8 +58,11 @@
     __ LoadImmediate(TMP, VMTag::kDartTagId);
     __ str(TMP,
            compiler::Address(THR, compiler::target::Thread::vm_tag_offset()));
-    COMPILE_ASSERT(IsAbiPreservedRegister(THR));
-    COMPILE_ASSERT(IsAbiPreservedRegister(PP));
+    // These registers must be preserved by runtime functions, otherwise
+    // we'd need to restore them here.
+    COMPILE_ASSERT(IsCalleeSavedRegister(THR));
+    COMPILE_ASSERT(IsCalleeSavedRegister(PP));
+    COMPILE_ASSERT(IsCalleeSavedRegister(CODE_REG));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 465c0fd9..05efb72 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -73,13 +73,14 @@
     __ str(TMP, compiler::Address(THR, Thread::vm_tag_offset()));
     __ mov(SP, kCallLeafRuntimeCalleeSaveScratch2);
     __ mov(CSP, kCallLeafRuntimeCalleeSaveScratch1);
-    COMPILE_ASSERT(IsAbiPreservedRegister(THR));
-    COMPILE_ASSERT(IsAbiPreservedRegister(PP));
-    COMPILE_ASSERT(IsAbiPreservedRegister(NULL_REG));
-    COMPILE_ASSERT(IsAbiPreservedRegister(HEAP_BITS));
-    COMPILE_ASSERT(IsAbiPreservedRegister(DISPATCH_TABLE_REG));
-    // These registers must be preserved by the runtime functions, otherwise
+    // These registers must be preserved by runtime functions, otherwise
     // we'd need to restore them here.
+    COMPILE_ASSERT(IsCalleeSavedRegister(THR));
+    COMPILE_ASSERT(IsCalleeSavedRegister(PP));
+    COMPILE_ASSERT(IsCalleeSavedRegister(CODE_REG));
+    COMPILE_ASSERT(IsCalleeSavedRegister(NULL_REG));
+    COMPILE_ASSERT(IsCalleeSavedRegister(HEAP_BITS));
+    COMPILE_ASSERT(IsCalleeSavedRegister(DISPATCH_TABLE_REG));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/runtime_entry_ia32.cc b/runtime/vm/runtime_entry_ia32.cc
index 8bba816..bbf92c5 100644
--- a/runtime/vm/runtime_entry_ia32.cc
+++ b/runtime/vm/runtime_entry_ia32.cc
@@ -37,6 +37,9 @@
     __ call(EAX);
     __ movl(compiler::Assembler::VMTagAddress(),
             compiler::Immediate(VMTag::kDartTagId));
+    // These registers must be preserved by runtime functions, otherwise
+    // we'd need to restore them here.
+    COMPILE_ASSERT(IsCalleeSavedRegister(THR));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 0fa921a..5731d55 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -96,6 +96,7 @@
     uword /*SmiPtr*/, uword /*SmiPtr*/, uword /*SmiPtr*/)                      \
   V(void, EnterSafepoint)                                                      \
   V(void, ExitSafepoint)                                                       \
+  V(void, ExitSafepointIgnoreUnwindInProgress)                                 \
   V(ApiLocalScope*, EnterHandleScope, Thread*)                                 \
   V(void, ExitHandleScope, Thread*)                                            \
   V(LocalHandle*, AllocateHandle, ApiLocalScope*)                              \
diff --git a/runtime/vm/runtime_entry_riscv.cc b/runtime/vm/runtime_entry_riscv.cc
new file mode 100644
index 0000000..8dfab67
--- /dev/null
+++ b/runtime/vm/runtime_entry_riscv.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/runtime_entry.h"
+
+#include "vm/simulator.h"
+#include "vm/stub_code.h"
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#include "vm/compiler/assembler/assembler.h"
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+namespace dart {
+
+#define __ assembler->
+
+uword RuntimeEntry::GetEntryPoint() const {
+  // Compute the effective address. When running under the simulator,
+  // this is a redirection address that forces the simulator to call
+  // into the runtime system.
+  uword entry = reinterpret_cast<uword>(function());
+#if defined(USING_SIMULATOR)
+  // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
+  // in registers (maximum 2 double arguments for leaf float runtime calls).
+  ASSERT(argument_count() >= 0);
+  ASSERT(!is_leaf() || (!is_float() && (argument_count() <= 4)) ||
+         (argument_count() <= 2));
+  Simulator::CallKind call_kind =
+      is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
+                              : Simulator::kLeafRuntimeCall)
+                : Simulator::kRuntimeCall;
+  entry =
+      Simulator::RedirectExternalReference(entry, call_kind, argument_count());
+#endif
+  return entry;
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+// Generate code to call into the stub which will call the runtime
+// function. Input for the stub is as follows:
+//   SP : points to the arguments and return value array.
+//   T5 : address of the runtime function to call.
+//   T4 : number of arguments to the call.
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                compiler::Assembler* assembler,
+                                intptr_t argument_count) {
+  if (runtime_entry->is_leaf()) {
+    ASSERT(argument_count == runtime_entry->argument_count());
+    // Caller is responsible for either using CallRuntimeScore or manually
+    // saving PP (C volatile register) and SP (altered by alignment).
+    COMPILE_ASSERT(!IsAbiPreservedRegister(PP));
+
+    __ lx(TMP2,
+          compiler::Address(THR, Thread::OffsetFromThread(runtime_entry)));
+    __ sx(TMP2, compiler::Address(THR, Thread::vm_tag_offset()));
+    __ ReserveAlignedFrameSpace(0);
+    __ jalr(TMP2);
+    __ LoadImmediate(TMP2, VMTag::kDartTagId);
+    __ sx(TMP2, compiler::Address(THR, Thread::vm_tag_offset()));
+    // These registers must be preserved by runtime functions, otherwise
+    // we'd need to restore them here.
+    COMPILE_ASSERT(IsCalleeSavedRegister(THR));
+    COMPILE_ASSERT(IsCalleeSavedRegister(NULL_REG));
+    COMPILE_ASSERT(IsCalleeSavedRegister(WRITE_BARRIER_MASK));
+    COMPILE_ASSERT(IsCalleeSavedRegister(DISPATCH_TABLE_REG));
+  } else {
+    // Argument count is not checked here, but in the runtime entry for a more
+    // informative error message.
+    __ lx(T5, compiler::Address(THR, Thread::OffsetFromThread(runtime_entry)));
+    __ li(T4, argument_count);
+    __ JumpAndLinkToRuntime();
+  }
+}
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index 78d3ead..fe759e1 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -38,8 +38,11 @@
     __ CallCFunction(RAX);
     __ movq(compiler::Assembler::VMTagAddress(),
             compiler::Immediate(VMTag::kDartTagId));
-    ASSERT((CallingConventions::kCalleeSaveCpuRegisters & (1 << THR)) != 0);
-    ASSERT((CallingConventions::kCalleeSaveCpuRegisters & (1 << PP)) != 0);
+    // These registers must be preserved by runtime functions, otherwise
+    // we'd need to restore them here.
+    ASSERT(IsCalleeSavedRegister(THR));
+    ASSERT(IsCalleeSavedRegister(PP));
+    ASSERT(IsCalleeSavedRegister(CODE_REG));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 50238aa..553097b 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -72,6 +72,56 @@
             "Print a message when an isolate is paused but there is no "
             "debugger attached.");
 
+DEFINE_FLAG(
+    charp,
+    log_service_response_sizes,
+    nullptr,
+    "Log sizes of service responses and events to a file in CSV format.");
+
+void* Service::service_response_size_log_file_ = nullptr;
+
+void Service::LogResponseSize(const char* method, JSONStream* js) {
+  if (service_response_size_log_file_ == nullptr) {
+    return;
+  }
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  char* entry =
+      OS::SCreate(nullptr, "%s, %" Pd "\n", method, js->buffer()->length());
+  (*file_write)(entry, strlen(entry), service_response_size_log_file_);
+  free(entry);
+}
+
+void Service::Init() {
+  if (FLAG_log_service_response_sizes == nullptr) {
+    return;
+  }
+  Dart_FileOpenCallback file_open = Dart::file_open_callback();
+  Dart_FileWriteCallback file_write = Dart::file_write_callback();
+  Dart_FileCloseCallback file_close = Dart::file_close_callback();
+  if ((file_open == nullptr) || (file_write == nullptr) ||
+      (file_close == nullptr)) {
+    OS::PrintErr("Error: Could not access file callbacks.");
+    UNREACHABLE();
+  }
+  ASSERT(service_response_size_log_file_ == nullptr);
+  service_response_size_log_file_ =
+      (*file_open)(FLAG_log_service_response_sizes, true);
+  if (service_response_size_log_file_ == nullptr) {
+    OS::PrintErr("Warning: Failed to open service response size log file: %s\n",
+                 FLAG_log_service_response_sizes);
+    return;
+  }
+}
+
+void Service::Cleanup() {
+  if (service_response_size_log_file_ == nullptr) {
+    return;
+  }
+  Dart_FileCloseCallback file_close = Dart::file_close_callback();
+  (*file_close)(service_response_size_log_file_);
+  service_response_size_log_file_ = nullptr;
+}
+
 static void PrintInvalidParamError(JSONStream* js, const char* param) {
 #if !defined(PRODUCT)
   js->PrintError(kInvalidParams, "%s: invalid '%s' parameter: %s", js->method(),
@@ -367,7 +417,8 @@
     &Service::timeline_stream, &Service::profiler_stream,
 };
 
-bool Service::ListenStream(const char* stream_id) {
+bool Service::ListenStream(const char* stream_id,
+                           bool include_private_members) {
   if (FLAG_trace_service) {
     OS::PrintErr("vm-service: starting stream '%s'\n", stream_id);
   }
@@ -375,6 +426,7 @@
   for (intptr_t i = 0; i < num_streams; i++) {
     if (strcmp(stream_id, streams_[i]->id()) == 0) {
       streams_[i]->set_enabled(true);
+      streams_[i]->set_include_private_members(include_private_members);
       return true;
     }
   }
@@ -986,6 +1038,7 @@
         return T->StealStickyError();
       }
       method->entry(T, &js);
+      Service::LogResponseSize(c_method_name, &js);
       js.PostReply();
       return T->StealStickyError();
     }
@@ -1164,7 +1217,7 @@
 }
 
 void Service::HandleEvent(ServiceEvent* event, bool enter_safepoint) {
-  if (event->stream_info() != NULL && !event->stream_info()->enabled()) {
+  if (event->stream_info() != nullptr && !event->stream_info()->enabled()) {
     if (FLAG_warn_on_pause_with_no_debugger && event->IsPause()) {
       // If we are about to pause a running program which has no
       // debugger connected, tell the user about it.
@@ -1172,7 +1225,7 @@
     }
     // Ignore events when no one is listening to the event stream.
     return;
-  } else if (event->stream_info() != NULL &&
+  } else if (event->stream_info() != nullptr &&
              FLAG_warn_on_pause_with_no_debugger && event->IsPause()) {
     ReportPauseOnConsole(event);
   }
@@ -1180,8 +1233,12 @@
     return;
   }
   JSONStream js;
+  if (event->stream_info() != nullptr) {
+    js.set_include_private_members(
+        event->stream_info()->include_private_members());
+  }
   const char* stream_id = event->stream_id();
-  ASSERT(stream_id != NULL);
+  ASSERT(stream_id != nullptr);
   {
     JSONObject jsobj(&js);
     jsobj.AddProperty("jsonrpc", "2.0");
@@ -1233,6 +1290,8 @@
     }
   }
 
+  Service::LogResponseSize(kind, event);
+
   // Message is of the format [<stream id>, <json string>].
   //
   // Build the event message in the C heap to avoid dart heap
@@ -1495,6 +1554,31 @@
   }
 }
 
+static const MethodParameter* const
+    set_stream_include_private_members_params[] = {
+        NO_ISOLATE_PARAMETER,
+        new BoolParameter("includePrivateMembers", true),
+        nullptr,
+};
+
+static void SetStreamIncludePrivateMembers(Thread* thread, JSONStream* js) {
+  const char* stream_id = js->LookupParam("streamId");
+  if (stream_id == nullptr) {
+    PrintMissingParamError(js, "streamId");
+    return;
+  }
+  bool include_private_members =
+      BoolParameter::Parse(js->LookupParam("includePrivateMembers"), false);
+  intptr_t num_streams = sizeof(streams_) / sizeof(streams_[0]);
+  for (intptr_t i = 0; i < num_streams; i++) {
+    if (strcmp(stream_id, streams_[i]->id()) == 0) {
+      streams_[i]->set_include_private_members(include_private_members);
+      break;
+    }
+  }
+  PrintSuccess(js);
+}
+
 static void ActOnIsolateGroup(JSONStream* js,
                               std::function<void(IsolateGroup*)> visitor) {
   const String& prefix =
@@ -3380,11 +3464,9 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 static const char* const report_enum_names[] = {
-    SourceReport::kCallSitesStr,
-    SourceReport::kCoverageStr,
-    SourceReport::kPossibleBreakpointsStr,
-    SourceReport::kProfileStr,
-    NULL,
+    SourceReport::kCallSitesStr,           SourceReport::kCoverageStr,
+    SourceReport::kPossibleBreakpointsStr, SourceReport::kProfileStr,
+    SourceReport::kBranchCoverageStr,      NULL,
 };
 #endif
 
@@ -3423,6 +3505,8 @@
       report_set |= SourceReport::kPossibleBreakpoints;
     } else if (strcmp(*riter, SourceReport::kProfileStr) == 0) {
       report_set |= SourceReport::kProfile;
+    } else if (strcmp(*riter, SourceReport::kBranchCoverageStr) == 0) {
+      report_set |= SourceReport::kBranchCoverage;
     }
     riter++;
   }
@@ -4842,7 +4926,7 @@
   virtual ~ServiceIsolateVisitor() {}
 
   void VisitIsolate(Isolate* isolate) {
-    if (!IsSystemIsolate(isolate)) {
+    if (!IsSystemIsolate(isolate) && isolate->is_service_registered()) {
       jsarr_->AddValue(isolate);
     }
   }
@@ -5626,6 +5710,8 @@
     set_library_debuggable_params },
   { "setName", SetName,
     set_name_params },
+  { "_setStreamIncludePrivateMembers", SetStreamIncludePrivateMembers,
+    set_stream_include_private_members_params },
   { "setTraceClassAllocation", SetTraceClassAllocation,
     set_trace_class_allocation_params },
   { "setVMName", SetVMName,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index f625b94..6bf1e40 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 55
+#define SERVICE_PROTOCOL_MINOR_VERSION 56
 
 class Array;
 class EmbedderServiceHandler;
@@ -68,20 +68,30 @@
 
 class StreamInfo {
  public:
-  explicit StreamInfo(const char* id) : id_(id), enabled_(false) {}
+  explicit StreamInfo(const char* id)
+      : id_(id), enabled_(false), include_private_members_(false) {}
 
   const char* id() const { return id_; }
 
   void set_enabled(bool value) { enabled_ = value; }
   bool enabled() const { return enabled_; }
 
+  void set_include_private_members(bool value) {
+    include_private_members_ = value;
+  }
+  bool include_private_members() const { return include_private_members_; }
+
  private:
   const char* id_;
   bool enabled_;
+  bool include_private_members_;
 };
 
 class Service : public AllStatic {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Handles a message which is not directed to an isolate.
   static ErrorPtr HandleRootMessage(const Array& message);
 
@@ -152,6 +162,9 @@
                         const Instance& id,
                         const Error& error);
 
+  // Logs the size of the contents of `js` to FLAG_log_service_response_sizes.
+  static void LogResponseSize(const char* method, JSONStream* js);
+
   // Enable/Disable timeline categories.
   // Returns True if the categories were successfully enabled, False otherwise.
   static bool EnableTimelineStreams(char* categories_list);
@@ -168,7 +181,7 @@
   static StreamInfo timeline_stream;
   static StreamInfo profiler_stream;
 
-  static bool ListenStream(const char* stream_id);
+  static bool ListenStream(const char* stream_id, bool include_privates);
   static void CancelStream(const char* stream_id);
 
   static ObjectPtr RequestAssets();
@@ -243,6 +256,8 @@
   static Dart_GetVMServiceAssetsArchive get_service_assets_callback_;
   static Dart_EmbedderInformationCallback embedder_information_callback_;
 
+  static void* service_response_size_log_file_;
+
   static const uint8_t* dart_library_kernel_;
   static intptr_t dart_library_kernel_len_;
 };
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 2c22e5f..ed6e095 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.55
+# Dart VM Service Protocol 3.56
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.55_ of the Dart VM Service Protocol. This
+This document describes of _version 3.56_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -3878,6 +3878,14 @@
 
   // The last token of the location if this is a range.
   int endTokenPos [optional];
+
+  // The line associated with this location. Only provided for non-synthetic
+  // token positions.
+  int line [optional];
+
+  // The column associated with this location. Only provided for non-synthetic
+  // token positions.
+  int column [optional];
 }
 ```
 
@@ -3934,7 +3942,10 @@
   Coverage,
 
   // Used to request a list of token positions of possible breakpoints.
-  PossibleBreakpoints
+  PossibleBreakpoints,
+
+  // Used to request branch coverage information.
+  BranchCoverage
 }
 ```
 
@@ -3969,6 +3980,11 @@
   // enabled).  Provided only when the when the PossibleBreakpoint report has
   // been requested and the range has been compiled.
   int[] possibleBreakpoints [optional];
+
+  // Branch coverage information for this range.  Provided only when the
+  // BranchCoverage report has been requested and the range has been
+  // compiled.
+  SourceReportCoverage branchCoverage [optional];
 }
 ```
 
@@ -4319,5 +4335,6 @@
 3.53 | Added `setIsolatePauseMode` RPC.
 3.54 | Added `CpuSamplesEvent`, updated `cpuSamples` property on `Event` to have type `CpuSamplesEvent`.
 3.55 | Added `streamCpuSamplesWithUserTag` RPC.
+3.56 | Added optional `line` and `column` properties to `SourceLocation`. Added a new `SourceReportKind`, `BranchCoverage`, which reports branch level coverage information.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 95add31..f2a1286 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -229,9 +229,11 @@
                                               " registered.\n",
                  name.ToCString(), Dart_GetMainPortId());
   }
-  return PortMap::PostMessage(WriteMessage(
+  bool result = PortMap::PostMessage(WriteMessage(
       /* can_send_any_object */ false, /* same_group */ false, list, port_,
       Message::kNormalPriority));
+  isolate->set_is_service_registered(true);
+  return result;
 }
 
 bool ServiceIsolate::SendIsolateShutdownMessage() {
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index 1979da4..a0127e9 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -21,6 +21,10 @@
   pc = static_cast<uintptr_t>(mcontext.arm_pc);
 #elif defined(HOST_ARCH_ARM64)
   pc = static_cast<uintptr_t>(mcontext.pc);
+#elif defined(HOST_ARCH_RISCV32)
+  pc = static_cast<uintptr_t>(mcontext.__gregs[REG_PC]);
+#elif defined(HOST_ARCH_RISCV64)
+  pc = static_cast<uintptr_t>(mcontext.__gregs[REG_PC]);
 #else
 #error Unsupported architecture.
 #endif  // HOST_ARCH_...
@@ -45,6 +49,10 @@
   }
 #elif defined(HOST_ARCH_ARM64)
   fp = static_cast<uintptr_t>(mcontext.regs[29]);
+#elif defined(HOST_ARCH_RISCV32)
+  fp = static_cast<uintptr_t>(mcontext.__gregs[REG_S0]);
+#elif defined(HOST_ARCH_RISCV64)
+  fp = static_cast<uintptr_t>(mcontext.__gregs[REG_S0]);
 #else
 #error Unsupported architecture.
 #endif  // HOST_ARCH_...
@@ -63,6 +71,10 @@
   sp = static_cast<uintptr_t>(mcontext.arm_sp);
 #elif defined(HOST_ARCH_ARM64)
   sp = static_cast<uintptr_t>(mcontext.sp);
+#elif defined(HOST_ARCH_RISCV32)
+  sp = static_cast<uintptr_t>(mcontext.__gregs[REG_SP]);
+#elif defined(HOST_ARCH_RISCV64)
+  sp = static_cast<uintptr_t>(mcontext.__gregs[REG_SP]);
 #else
 #error Unsupported architecture.
 #endif  // HOST_ARCH_...
@@ -88,6 +100,10 @@
   lr = static_cast<uintptr_t>(mcontext.arm_lr);
 #elif defined(HOST_ARCH_ARM64)
   lr = static_cast<uintptr_t>(mcontext.regs[30]);
+#elif defined(HOST_ARCH_RISCV32)
+  lr = static_cast<uintptr_t>(mcontext.__gregs[REG_RA]);
+#elif defined(HOST_ARCH_RISCV64)
+  lr = static_cast<uintptr_t>(mcontext.__gregs[REG_RA]);
 #else
 #error Unsupported architecture.
 #endif  // HOST_ARCH_...
diff --git a/runtime/vm/simulator.h b/runtime/vm/simulator.h
index e08337c..7738d0c 100644
--- a/runtime/vm/simulator.h
+++ b/runtime/vm/simulator.h
@@ -14,6 +14,8 @@
 #include "vm/simulator_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/simulator_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/simulator_riscv.h"
 #else
 #error Unknown architecture.
 #endif  // defined(TARGET_ARCH_...)
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 8074d56..61beaec 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -25,14 +25,12 @@
 class SimulatorSetjmpBuffer;
 class Thread;
 
-#if !defined(SIMD_VALUE_T_)
 typedef struct {
   union {
     uint32_t u;
     float f;
   } data_[4];
 } simd_value_t;
-#endif
 
 class Simulator {
  public:
diff --git a/runtime/vm/simulator_riscv.cc b/runtime/vm/simulator_riscv.cc
new file mode 100644
index 0000000..73cdb72
--- /dev/null
+++ b/runtime/vm/simulator_riscv.cc
@@ -0,0 +1,2617 @@
+// 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.
+
+#include <setjmp.h>  // NOLINT
+#include <stdlib.h>
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+// Only build the simulator if not compiling for real RISCV hardware.
+#if defined(USING_SIMULATOR)
+
+#include "vm/simulator.h"
+
+#include "vm/compiler/assembler/disassembler.h"
+#include "vm/constants.h"
+#include "vm/image_snapshot.h"
+#include "vm/native_arguments.h"
+#include "vm/os_thread.h"
+#include "vm/stack_frame.h"
+
+namespace dart {
+
+DEFINE_FLAG(uint64_t,
+            trace_sim_after,
+            ULLONG_MAX,
+            "Trace simulator execution after instruction count reached.");
+DEFINE_FLAG(uint64_t,
+            stop_sim_at,
+            ULLONG_MAX,
+            "Instruction address or instruction count to stop simulator at.");
+
+// SimulatorSetjmpBuffer are linked together, and the last created one
+// is referenced by the Simulator. When an exception is thrown, the exception
+// runtime looks at where to jump and finds the corresponding
+// SimulatorSetjmpBuffer based on the stack pointer of the exception handler.
+// The runtime then does a Longjmp on that buffer to return to the simulator.
+class SimulatorSetjmpBuffer {
+ public:
+  void Longjmp() {
+    // "This" is now the last setjmp buffer.
+    simulator_->set_last_setjmp_buffer(this);
+    longjmp(buffer_, 1);
+  }
+
+  explicit SimulatorSetjmpBuffer(Simulator* sim) {
+    simulator_ = sim;
+    link_ = sim->last_setjmp_buffer();
+    sim->set_last_setjmp_buffer(this);
+    sp_ = static_cast<uword>(sim->get_register(SP));
+  }
+
+  ~SimulatorSetjmpBuffer() {
+    ASSERT(simulator_->last_setjmp_buffer() == this);
+    simulator_->set_last_setjmp_buffer(link_);
+  }
+
+  SimulatorSetjmpBuffer* link() { return link_; }
+
+  uword sp() { return sp_; }
+
+ private:
+  uword sp_;
+  Simulator* simulator_;
+  SimulatorSetjmpBuffer* link_;
+  jmp_buf buffer_;
+
+  friend class Simulator;
+};
+
+// When the generated code calls an external reference we need to catch that in
+// the simulator.  The external reference will be a function compiled for the
+// host architecture.  We need to call that function instead of trying to
+// execute it with the simulator.  We do that by redirecting the external
+// reference to a svc (supervisor call) instruction that is handled by
+// the simulator.  We write the original destination of the jump just at a known
+// offset from the svc instruction so the simulator knows what to call.
+class Redirection {
+ public:
+  uword address_of_ecall_instruction() {
+    return reinterpret_cast<uword>(&ecall_instruction_);
+  }
+
+  uword external_function() const { return external_function_; }
+
+  Simulator::CallKind call_kind() const { return call_kind_; }
+
+  int argument_count() const { return argument_count_; }
+
+  static Redirection* Get(uword external_function,
+                          Simulator::CallKind call_kind,
+                          int argument_count) {
+    MutexLocker ml(mutex_);
+
+    Redirection* old_head = list_.load(std::memory_order_relaxed);
+    for (Redirection* current = old_head; current != nullptr;
+         current = current->next_) {
+      if (current->external_function_ == external_function) return current;
+    }
+
+    Redirection* redirection =
+        new Redirection(external_function, call_kind, argument_count);
+    redirection->next_ = old_head;
+
+    // Use a memory fence to ensure all pending writes are written at the time
+    // of updating the list head, so the profiling thread always has a valid
+    // list to look at.
+    list_.store(redirection, std::memory_order_release);
+
+    return redirection;
+  }
+
+  static Redirection* FromECallInstruction(uintx_t ecall_instruction) {
+    char* addr_of_ecall = reinterpret_cast<char*>(ecall_instruction);
+    char* addr_of_redirection =
+        addr_of_ecall - OFFSET_OF(Redirection, ecall_instruction_);
+    return reinterpret_cast<Redirection*>(addr_of_redirection);
+  }
+
+  // Please note that this function is called by the signal handler of the
+  // profiling thread.  It can therefore run at any point in time and is not
+  // allowed to hold any locks - which is precisely the reason why the list is
+  // prepend-only and a memory fence is used when writing the list head [list_]!
+  static uword FunctionForRedirect(uword address_of_ecall) {
+    for (Redirection* current = list_.load(std::memory_order_acquire);
+         current != nullptr; current = current->next_) {
+      if (current->address_of_ecall_instruction() == address_of_ecall) {
+        return current->external_function_;
+      }
+    }
+    return 0;
+  }
+
+ private:
+  Redirection(uword external_function,
+              Simulator::CallKind call_kind,
+              int argument_count)
+      : external_function_(external_function),
+        call_kind_(call_kind),
+        argument_count_(argument_count),
+        ecall_instruction_(Instr::kSimulatorRedirectInstruction),
+        next_(NULL) {}
+
+  uword external_function_;
+  Simulator::CallKind call_kind_;
+  int argument_count_;
+  uint32_t ecall_instruction_;
+  Redirection* next_;
+  static std::atomic<Redirection*> list_;
+  static Mutex* mutex_;
+};
+
+std::atomic<Redirection*> Redirection::list_ = {nullptr};
+Mutex* Redirection::mutex_ = new Mutex();
+
+uword Simulator::RedirectExternalReference(uword function,
+                                           CallKind call_kind,
+                                           int argument_count) {
+  Redirection* redirection =
+      Redirection::Get(function, call_kind, argument_count);
+  return redirection->address_of_ecall_instruction();
+}
+
+uword Simulator::FunctionForRedirect(uword redirect) {
+  return Redirection::FunctionForRedirect(redirect);
+}
+
+// Get the active Simulator for the current isolate.
+Simulator* Simulator::Current() {
+  Isolate* isolate = Isolate::Current();
+  Simulator* simulator = isolate->simulator();
+  if (simulator == NULL) {
+    NoSafepointScope no_safepoint;
+    simulator = new Simulator();
+    isolate->set_simulator(simulator);
+  }
+  return simulator;
+}
+
+void Simulator::Init() {}
+
+Simulator::Simulator()
+    : pc_(0),
+      instret_(0),
+      reserved_address_(0),
+      reserved_value_(0),
+      fcsr_(0),
+      random_(),
+      last_setjmp_buffer_(NULL) {
+  // Setup simulator support first. Some of this information is needed to
+  // setup the architecture state.
+  // We allocate the stack here, the size is computed as the sum of
+  // the size specified by the user and the buffer space needed for
+  // handling stack overflow exceptions. To be safe in potential
+  // stack underflows we also add some underflow buffer space.
+  stack_ =
+      new char[(OSThread::GetSpecifiedStackSize() +
+                OSThread::kStackSizeBufferMax + kSimulatorStackUnderflowSize)];
+  // Low address.
+  stack_limit_ = reinterpret_cast<uword>(stack_);
+  // Limit for StackOverflowError.
+  overflow_stack_limit_ = stack_limit_ + OSThread::kStackSizeBufferMax;
+  // High address.
+  stack_base_ = overflow_stack_limit_ + OSThread::GetSpecifiedStackSize();
+
+  // Setup architecture state.
+  xregs_[0] = 0;
+  for (intptr_t i = 1; i < kNumberOfCpuRegisters; i++) {
+    xregs_[i] = random_.NextUInt64();
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    // TODO(riscv): This generates values that are very wide when printed,
+    // making it hard to read register state. Maybe generate random values in
+    // the unit interval instead?
+    // fregs_[i] = bit_cast<double>(random_.NextUInt64());
+    fregs_[i] = bit_cast<double>(kNaNBox);
+  }
+
+  // The sp is initialized to point to the bottom (high address) of the
+  // allocated stack area.
+  set_xreg(SP, stack_base());
+  // The lr and pc are initialized to a known bad value that will cause an
+  // access violation if the simulator ever tries to execute it.
+  set_xreg(RA, kBadLR);
+  pc_ = kBadLR;
+}
+
+Simulator::~Simulator() {
+  delete[] stack_;
+  Isolate* isolate = Isolate::Current();
+  if (isolate != NULL) {
+    isolate->set_simulator(NULL);
+  }
+}
+
+void Simulator::PrepareCall(PreservedRegisters* preserved) {
+#if defined(DEBUG)
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    preserved->xregs[i] = xregs_[i];
+    if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
+      xregs_[i] = random_.NextUInt64();
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    preserved->fregs[i] = fregs_[i];
+    if ((kAbiVolatileFpuRegs & (1 << i)) != 0) {
+      // TODO(riscv): This generates values that are very wide when printed,
+      // making it hard to read register state. Maybe generate random values in
+      // the unit interval instead?
+      // fregs_[i] = bit_cast<double>(random_.NextUInt64());
+      fregs_[i] = bit_cast<double>(kNaNBox);
+    }
+  }
+#endif
+}
+
+void Simulator::ClobberVolatileRegisters() {
+#if defined(DEBUG)
+  reserved_address_ = reserved_value_ = 0;  // Clear atomic reservation.
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
+      xregs_[i] = random_.NextUInt64();
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    if ((kAbiVolatileFpuRegs & (1 << i)) != 0) {
+      // TODO(riscv): This generates values that are very wide when printed,
+      // making it hard to read register state. Maybe generate random values in
+      // the unit interval instead?
+      // fregs_[i] = bit_cast<double>(random_.NextUInt64());
+      fregs_[i] = bit_cast<double>(kNaNBox);
+    }
+  }
+#endif
+}
+
+void Simulator::SavePreservedRegisters(PreservedRegisters* preserved) {
+#if defined(DEBUG)
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    preserved->xregs[i] = xregs_[i];
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    preserved->fregs[i] = fregs_[i];
+  }
+#endif
+}
+
+void Simulator::CheckPreservedRegisters(PreservedRegisters* preserved) {
+#if defined(DEBUG)
+  if (preserved->xregs[SP] != xregs_[SP]) {
+    PrintRegisters();
+    PrintStack();
+    FATAL("Stack unbalanced");
+  }
+  const intptr_t kPreservedAtCall =
+      kAbiPreservedCpuRegs | (1 << TP) | (1 << GP) | (1 << SP) | (1 << FP);
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    if ((kPreservedAtCall & (1 << i)) != 0) {
+      if (preserved->xregs[i] != xregs_[i]) {
+        FATAL("%s was not preserved\n", cpu_reg_names[i]);
+      }
+    }
+  }
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    if ((kAbiVolatileFpuRegs & (1 << i)) == 0) {
+      if (bit_cast<uint64_t>(preserved->fregs[i]) !=
+          bit_cast<uint64_t>(fregs_[i])) {
+        FATAL("%s was not preserved\n", fpu_reg_names[i]);
+      }
+    }
+  }
+#endif
+}
+
+void Simulator::RunCall(intx_t entry, PreservedRegisters* preserved) {
+  pc_ = entry;
+  set_xreg(RA, kEndSimulatingPC);
+  Execute();
+  CheckPreservedRegisters(preserved);
+}
+
+int64_t Simulator::Call(intx_t entry,
+                        intx_t parameter0,
+                        intx_t parameter1,
+                        intx_t parameter2,
+                        intx_t parameter3,
+                        bool fp_return,
+                        bool fp_args) {
+  // Save the SP register before the call so we can restore it.
+  const intptr_t sp_before_call = get_xreg(SP);
+
+  // Setup parameters.
+  if (fp_args) {
+    set_fregd(FA0, parameter0);
+    set_fregd(FA1, parameter1);
+    set_fregd(FA2, parameter2);
+    set_fregd(FA3, parameter3);
+  } else {
+    set_xreg(A0, parameter0);
+    set_xreg(A1, parameter1);
+    set_xreg(A2, parameter2);
+    set_xreg(A3, parameter3);
+  }
+
+  // Make sure the activation frames are properly aligned.
+  intptr_t stack_pointer = sp_before_call;
+  if (OS::ActivationFrameAlignment() > 1) {
+    stack_pointer =
+        Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
+  }
+  set_xreg(SP, stack_pointer);
+
+  // Prepare to execute the code at entry.
+  pc_ = entry;
+  // Put down marker for end of simulation. The simulator will stop simulation
+  // when the PC reaches this value. By saving the "end simulation" value into
+  // the LR the simulation stops when returning to this call point.
+  set_xreg(RA, kEndSimulatingPC);
+
+  // Remember the values of callee-saved registers, and set them up with a
+  // known value so that we are able to check that they are preserved
+  // properly across Dart execution.
+  PreservedRegisters preserved;
+  SavePreservedRegisters(&preserved);
+
+  // Start the simulation.
+  Execute();
+
+  // Check that the callee-saved registers have been preserved,
+  // and restore them with the original value.
+  CheckPreservedRegisters(&preserved);
+
+  // Restore the SP register and return R0.
+  set_xreg(SP, sp_before_call);
+  int64_t return_value;
+  if (fp_return) {
+    return_value = get_fregd(FA0);
+  } else {
+    return_value = get_xreg(A0);
+  }
+  return return_value;
+}
+
+void Simulator::Execute() {
+  while (pc_ != kEndSimulatingPC) {
+    uint16_t parcel = *reinterpret_cast<uint16_t*>(pc_);
+    if (IsCInstruction(parcel)) {
+      CInstr instr(parcel);
+      if (IsTracingExecution()) {
+        Disassembler::Disassemble(pc_, pc_ + instr.length());
+      }
+      Interpret(instr);
+    } else {
+      Instr instr(*reinterpret_cast<uint32_t*>(pc_));
+      if (IsTracingExecution()) {
+        Disassembler::Disassemble(pc_, pc_ + instr.length());
+      }
+      Interpret(instr);
+    }
+    instret_++;
+  }
+}
+
+bool Simulator::IsTracingExecution() const {
+  return instret_ > FLAG_trace_sim_after;
+}
+
+void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
+  // Walk over all setjmp buffers (simulated --> C++ transitions)
+  // and try to find the setjmp associated with the simulated stack pointer.
+  SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
+  while (buf->link() != NULL && buf->link()->sp() <= sp) {
+    buf = buf->link();
+  }
+  ASSERT(buf != NULL);
+
+  // The C++ caller has not cleaned up the stack memory of C++ frames.
+  // Prepare for unwinding frames by destroying all the stack resources
+  // in the previous C++ frames.
+  StackResource::Unwind(thread);
+
+  // Keep the following code in sync with `StubCode::JumpToFrameStub()`.
+
+  // Unwind the C++ stack and continue simulation in the target frame.
+  pc_ = pc;
+  set_xreg(SP, static_cast<uintx_t>(sp));
+  set_xreg(FP, static_cast<uintx_t>(fp));
+  set_xreg(THR, reinterpret_cast<uintx_t>(thread));
+  // Set the tag.
+  thread->set_vm_tag(VMTag::kDartTagId);
+  // Clear top exit frame.
+  thread->set_top_exit_frame_info(0);
+  // Restore pool pointer.
+  uintx_t code =
+      *reinterpret_cast<uintx_t*>(fp + kPcMarkerSlotFromFp * kWordSize);
+  uintx_t pp = FLAG_precompiled_mode
+                   ? static_cast<uintx_t>(thread->global_object_pool())
+                   : *reinterpret_cast<uintx_t*>(
+                         code + Code::object_pool_offset() - kHeapObjectTag);
+  pp -= kHeapObjectTag;  // In the PP register, the pool pointer is untagged.
+  set_xreg(CODE_REG, code);
+  set_xreg(PP, pp);
+  set_xreg(WRITE_BARRIER_MASK, thread->write_barrier_mask());
+  set_xreg(NULL_REG, static_cast<uintx_t>(Object::null()));
+  if (FLAG_precompiled_mode) {
+    set_xreg(DISPATCH_TABLE_REG,
+             reinterpret_cast<uintx_t>(thread->dispatch_table_array()));
+  }
+
+  buf->Longjmp();
+}
+
+void Simulator::PrintRegisters() {
+  ASSERT(static_cast<intptr_t>(kNumberOfCpuRegisters) ==
+         static_cast<intptr_t>(kNumberOfFpuRegisters));
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+#if XLEN == 32
+    OS::Print("%4s: %8x %11d", cpu_reg_names[i], xregs_[i], xregs_[i]);
+#elif XLEN == 64
+    OS::Print("%4s: %16" Px64 " %20" Pd64, cpu_reg_names[i], xregs_[i],
+              xregs_[i]);
+#endif
+    OS::Print("  %4s: %lf\n", fpu_reg_names[i], fregs_[i]);
+  }
+#if XLEN == 32
+  OS::Print("  pc: %8x\n", pc_);
+#elif XLEN == 64
+  OS::Print("  pc: %16" Px64 "\n", pc_);
+#endif
+}
+
+void Simulator::PrintStack() {
+  StackFrameIterator frames(get_register(FP), get_register(SP), get_pc(),
+                            ValidationPolicy::kDontValidateFrames,
+                            Thread::Current(),
+                            StackFrameIterator::kNoCrossThreadIteration);
+  StackFrame* frame = frames.NextFrame();
+  while (frame != nullptr) {
+    OS::PrintErr("%s\n", frame->ToCString());
+    frame = frames.NextFrame();
+  }
+}
+
+void Simulator::Interpret(Instr instr) {
+  switch (instr.opcode()) {
+    case LUI:
+      InterpretLUI(instr);
+      break;
+    case AUIPC:
+      InterpretAUIPC(instr);
+      break;
+    case JAL:
+      InterpretJAL(instr);
+      break;
+    case JALR:
+      InterpretJALR(instr);
+      break;
+    case BRANCH:
+      InterpretBRANCH(instr);
+      break;
+    case LOAD:
+      InterpretLOAD(instr);
+      break;
+    case STORE:
+      InterpretSTORE(instr);
+      break;
+    case OPIMM:
+      InterpretOPIMM(instr);
+      break;
+    case OPIMM32:
+      InterpretOPIMM32(instr);
+      break;
+    case OP:
+      InterpretOP(instr);
+      break;
+    case OP32:
+      InterpretOP32(instr);
+      break;
+    case MISCMEM:
+      InterpretMISCMEM(instr);
+      break;
+    case SYSTEM:
+      InterpretSYSTEM(instr);
+      break;
+    case AMO:
+      InterpretAMO(instr);
+      break;
+    case LOADFP:
+      InterpretLOADFP(instr);
+      break;
+    case STOREFP:
+      InterpretSTOREFP(instr);
+      break;
+    case FMADD:
+      InterpretFMADD(instr);
+      break;
+    case FMSUB:
+      InterpretFMSUB(instr);
+      break;
+    case FNMADD:
+      InterpretFNMADD(instr);
+      break;
+    case FNMSUB:
+      InterpretFNMSUB(instr);
+      break;
+    case OPFP:
+      InterpretOPFP(instr);
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+}
+
+void Simulator::Interpret(CInstr instr) {
+  switch (instr.opcode()) {
+    case C_LWSP: {
+      uintx_t addr = get_xreg(SP) + instr.spload4_imm();
+      set_xreg(instr.rd(), MemoryRead<int32_t>(addr, SP));
+      break;
+    }
+#if XLEN == 32
+    case C_FLWSP: {
+      uintx_t addr = get_xreg(SP) + instr.spload4_imm();
+      set_fregs(instr.frd(), MemoryRead<float>(addr, SP));
+      break;
+    }
+#else
+    case C_LDSP: {
+      uintx_t addr = get_xreg(SP) + instr.spload8_imm();
+      set_xreg(instr.rd(), MemoryRead<int64_t>(addr, SP));
+      break;
+    }
+#endif
+    case C_FLDSP: {
+      uintx_t addr = get_xreg(SP) + instr.spload8_imm();
+      set_fregd(instr.frd(), MemoryRead<double>(addr, SP));
+      break;
+    }
+    case C_SWSP: {
+      uintx_t addr = get_xreg(SP) + instr.spstore4_imm();
+      MemoryWrite<uint32_t>(addr, get_xreg(instr.rs2()), SP);
+      break;
+    }
+#if XLEN == 32
+    case C_FSWSP: {
+      uintx_t addr = get_xreg(SP) + instr.spstore4_imm();
+      MemoryWrite<float>(addr, get_fregs(instr.frs2()), SP);
+      break;
+    }
+#else
+    case C_SDSP: {
+      uintx_t addr = get_xreg(SP) + instr.spstore8_imm();
+      MemoryWrite<uint64_t>(addr, get_xreg(instr.rs2()), SP);
+      break;
+    }
+#endif
+    case C_FSDSP: {
+      uintx_t addr = get_xreg(SP) + instr.spstore8_imm();
+      MemoryWrite<double>(addr, get_fregd(instr.frs2()), SP);
+      break;
+    }
+    case C_LW: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem4_imm();
+      set_xreg(instr.rdp(), MemoryRead<int32_t>(addr, instr.rs1p()));
+      break;
+    }
+#if XLEN == 32
+    case C_FLW: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem4_imm();
+      set_fregs(instr.frdp(), MemoryRead<float>(addr, instr.rs1p()));
+      break;
+    }
+#else
+    case C_LD: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem8_imm();
+      set_xreg(instr.rdp(), MemoryRead<int64_t>(addr, instr.rs1p()));
+      break;
+    }
+#endif
+    case C_FLD: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem8_imm();
+      set_fregd(instr.frdp(), MemoryRead<double>(addr, instr.rs1p()));
+      break;
+    }
+    case C_SW: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem4_imm();
+      MemoryWrite<uint32_t>(addr, get_xreg(instr.rs2p()), instr.rs1p());
+      break;
+    }
+#if XLEN == 32
+    case C_FSW: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem4_imm();
+      MemoryWrite<float>(addr, get_fregs(instr.frs2p()), instr.rs1p());
+      break;
+    }
+#else
+    case C_SD: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem8_imm();
+      MemoryWrite<uint64_t>(addr, get_xreg(instr.rs2p()), instr.rs1p());
+      break;
+    }
+#endif
+    case C_FSD: {
+      uintx_t addr = get_xreg(instr.rs1p()) + instr.mem8_imm();
+      MemoryWrite<double>(addr, get_fregd(instr.frs2p()), instr.rs1p());
+      break;
+    }
+    case C_J: {
+      pc_ += sign_extend((int32_t)instr.j_imm());
+      return;
+    }
+#if XLEN == 32
+    case C_JAL: {
+      set_xreg(RA, pc_ + instr.length());
+      pc_ += sign_extend((int32_t)instr.j_imm());
+      return;
+    }
+#endif
+    case C_JR: {
+      if (instr.encoding() & (C_JALR ^ C_JR)) {
+        if ((instr.rs1() == ZR) && (instr.rs2() == ZR)) {
+          InterpretEBREAK(instr);
+        } else if (instr.rs2() == ZR) {
+          // JALR
+          uintx_t target = get_xreg(instr.rs1());
+          set_xreg(RA, pc_ + instr.length());
+          pc_ = target;
+          return;
+        } else {
+          // ADD
+          set_xreg(instr.rd(), get_xreg(instr.rs1()) + get_xreg(instr.rs2()));
+        }
+      } else {
+        if ((instr.rd() != ZR) && (instr.rs2() != ZR)) {
+          // MV
+          set_xreg(instr.rd(), get_xreg(instr.rs2()));
+        } else if (instr.rs2() != ZR) {
+          IllegalInstruction(instr);
+        } else {
+          // JR
+          pc_ = get_xreg(instr.rs1());
+          return;
+        }
+      }
+      break;
+    }
+    case C_BEQZ:
+      if (get_xreg(instr.rs1p()) == 0) {
+        pc_ += instr.b_imm();
+        return;
+      }
+      break;
+    case C_BNEZ:
+      if (get_xreg(instr.rs1p()) != 0) {
+        pc_ += instr.b_imm();
+        return;
+      }
+      break;
+    case C_LI:
+      if (instr.rd() == ZR) {
+        IllegalInstruction(instr);
+      } else {
+        set_xreg(instr.rd(), sign_extend(instr.i_imm()));
+      }
+      break;
+    case C_LUI:
+      if (instr.rd() == SP) {
+        if (instr.i16_imm() == 0) {
+          IllegalInstruction(instr);
+        } else {
+          set_xreg(instr.rd(),
+                   get_xreg(instr.rs1()) + sign_extend(instr.i16_imm()));
+        }
+      } else if ((instr.rd() == ZR) || (instr.u_imm() == 0)) {
+        IllegalInstruction(instr);
+      } else {
+        set_xreg(instr.rd(), sign_extend(instr.u_imm()));
+      }
+      break;
+    case C_ADDI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) + instr.i_imm());
+      break;
+#if XLEN >= 64
+    case C_ADDIW: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = instr.i_imm();
+      set_xreg(instr.rd(), sign_extend(a + b));
+      break;
+    }
+#endif  // XLEN >= 64
+    case C_ADDI4SPN:
+      if (instr.i4spn_imm() == 0) {
+        IllegalInstruction(instr);
+      } else {
+        set_xreg(instr.rdp(), get_xreg(SP) + instr.i4spn_imm());
+      }
+      break;
+    case C_SLLI:
+      if (instr.i_imm() == 0) {
+        IllegalInstruction(instr);
+      } else {
+        set_xreg(instr.rd(), get_xreg(instr.rs1())
+                                 << (instr.i_imm() & (XLEN - 1)));
+      }
+      break;
+    case C_MISCALU:
+      // Note MISCALU has a different notion of rsd′ than other instructions,
+      // so use rs1′ instead.
+      switch (instr.encoding() & C_MISCALU_MASK) {
+        case C_SRLI:
+          if (instr.i_imm() == 0) {
+            IllegalInstruction(instr);
+          } else {
+            set_xreg(instr.rs1p(),
+                     get_xreg(instr.rs1p()) >> (instr.i_imm() & (XLEN - 1)));
+          }
+          break;
+        case C_SRAI:
+          if (instr.i_imm() == 0) {
+            IllegalInstruction(instr);
+          } else {
+            set_xreg(instr.rs1p(),
+                     static_cast<intx_t>(get_xreg(instr.rs1p())) >>
+                         (instr.i_imm() & (XLEN - 1)));
+          }
+          break;
+        case C_ANDI:
+          set_xreg(instr.rs1p(), get_xreg(instr.rs1p()) & instr.i_imm());
+          break;
+        case C_RR:
+          switch (instr.encoding() & C_RR_MASK) {
+            case C_AND:
+              set_xreg(instr.rs1p(),
+                       get_xreg(instr.rs1p()) & get_xreg(instr.rs2p()));
+              break;
+            case C_OR:
+              set_xreg(instr.rs1p(),
+                       get_xreg(instr.rs1p()) | get_xreg(instr.rs2p()));
+              break;
+            case C_XOR:
+              set_xreg(instr.rs1p(),
+                       get_xreg(instr.rs1p()) ^ get_xreg(instr.rs2p()));
+              break;
+            case C_SUB:
+              set_xreg(instr.rs1p(),
+                       get_xreg(instr.rs1p()) - get_xreg(instr.rs2p()));
+              break;
+            case C_ADDW: {
+              uint32_t a = get_xreg(instr.rs1p());
+              uint32_t b = get_xreg(instr.rs2p());
+              set_xreg(instr.rs1p(), sign_extend(a + b));
+              break;
+            }
+            case C_SUBW: {
+              uint32_t a = get_xreg(instr.rs1p());
+              uint32_t b = get_xreg(instr.rs2p());
+              set_xreg(instr.rs1p(), sign_extend(a - b));
+              break;
+            }
+            default:
+              IllegalInstruction(instr);
+          }
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretLUI(Instr instr) {
+  set_xreg(instr.rd(), sign_extend(instr.utype_imm()));
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretAUIPC(Instr instr) {
+  set_xreg(instr.rd(), pc_ + sign_extend(instr.utype_imm()));
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretJAL(Instr instr) {
+  set_xreg(instr.rd(), pc_ + instr.length());
+  pc_ += sign_extend(instr.jtype_imm());
+}
+
+void Simulator::InterpretJALR(Instr instr) {
+  uintx_t base = get_xreg(instr.rs1());
+  uintx_t offset = static_cast<uintx_t>(instr.itype_imm());
+  set_xreg(instr.rd(), pc_ + instr.length());
+  pc_ = base + offset;
+}
+
+void Simulator::InterpretBRANCH(Instr instr) {
+  switch (instr.funct3()) {
+    case BEQ:
+      if (get_xreg(instr.rs1()) == get_xreg(instr.rs2())) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    case BNE:
+      if (get_xreg(instr.rs1()) != get_xreg(instr.rs2())) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    case BLT:
+      if (static_cast<intx_t>(get_xreg(instr.rs1())) <
+          static_cast<intx_t>(get_xreg(instr.rs2()))) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    case BGE:
+      if (static_cast<intx_t>(get_xreg(instr.rs1())) >=
+          static_cast<intx_t>(get_xreg(instr.rs2()))) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    case BLTU:
+      if (static_cast<uintx_t>(get_xreg(instr.rs1())) <
+          static_cast<uintx_t>(get_xreg(instr.rs2()))) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    case BGEU:
+      if (static_cast<uintx_t>(get_xreg(instr.rs1())) >=
+          static_cast<uintx_t>(get_xreg(instr.rs2()))) {
+        pc_ += instr.btype_imm();
+      } else {
+        pc_ += instr.length();
+      }
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+}
+
+void Simulator::InterpretLOAD(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1()) + instr.itype_imm();
+  switch (instr.funct3()) {
+    case LB:
+      set_xreg(instr.rd(), MemoryRead<int8_t>(addr, instr.rs1()));
+      break;
+    case LH:
+      set_xreg(instr.rd(), MemoryRead<int16_t>(addr, instr.rs1()));
+      break;
+    case LW:
+      set_xreg(instr.rd(), MemoryRead<int32_t>(addr, instr.rs1()));
+      break;
+    case LBU:
+      set_xreg(instr.rd(), MemoryRead<uint8_t>(addr, instr.rs1()));
+      break;
+    case LHU:
+      set_xreg(instr.rd(), MemoryRead<uint16_t>(addr, instr.rs1()));
+      break;
+#if XLEN >= 64
+    case LWU:
+      set_xreg(instr.rd(), MemoryRead<uint32_t>(addr, instr.rs1()));
+      break;
+    case LD:
+      set_xreg(instr.rd(), MemoryRead<int64_t>(addr, instr.rs1()));
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretLOADFP(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1()) + instr.itype_imm();
+  switch (instr.funct3()) {
+    case S:
+      set_fregs(instr.frd(), MemoryRead<float>(addr, instr.rs1()));
+      break;
+    case D:
+      set_fregd(instr.frd(), MemoryRead<double>(addr, instr.rs1()));
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretSTORE(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1()) + instr.stype_imm();
+  switch (instr.funct3()) {
+    case SB:
+      MemoryWrite<uint8_t>(addr, get_xreg(instr.rs2()), instr.rs1());
+      break;
+    case SH:
+      MemoryWrite<uint16_t>(addr, get_xreg(instr.rs2()), instr.rs1());
+      break;
+    case SW:
+      MemoryWrite<uint32_t>(addr, get_xreg(instr.rs2()), instr.rs1());
+      break;
+#if XLEN >= 64
+    case SD:
+      MemoryWrite<uint64_t>(addr, get_xreg(instr.rs2()), instr.rs1());
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretSTOREFP(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1()) + instr.stype_imm();
+  switch (instr.funct3()) {
+    case S:
+      MemoryWrite<float>(addr, get_fregs(instr.frs2()), instr.rs1());
+      break;
+    case D:
+      MemoryWrite<double>(addr, get_fregd(instr.frs2()), instr.rs1());
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOPIMM(Instr instr) {
+  switch (instr.funct3()) {
+    case ADDI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) + instr.itype_imm());
+      break;
+    case SLTI: {
+      set_xreg(instr.rd(), static_cast<intx_t>(get_xreg(instr.rs1())) <
+                                   static_cast<intx_t>(instr.itype_imm())
+                               ? 1
+                               : 0);
+      break;
+    }
+    case SLTIU:
+      set_xreg(instr.rd(), static_cast<uintx_t>(get_xreg(instr.rs1())) <
+                                   static_cast<uintx_t>(instr.itype_imm())
+                               ? 1
+                               : 0);
+      break;
+    case XORI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) ^ instr.itype_imm());
+      break;
+    case ORI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) | instr.itype_imm());
+      break;
+    case ANDI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) & instr.itype_imm());
+
+      break;
+    case SLLI:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) << instr.shamt());
+      break;
+    case SRI:
+      if ((instr.funct7() & 0b1111110) == SRA) {
+        set_xreg(instr.rd(),
+                 static_cast<intx_t>(get_xreg(instr.rs1())) >> instr.shamt());
+      } else {
+        set_xreg(instr.rd(),
+                 static_cast<uintx_t>(get_xreg(instr.rs1())) >> instr.shamt());
+      }
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOPIMM32(Instr instr) {
+  switch (instr.funct3()) {
+    case ADDI: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = instr.itype_imm();
+      set_xreg(instr.rd(), sign_extend(a + b));
+      break;
+    }
+    case SLLI: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = instr.shamt();
+      set_xreg(instr.rd(), sign_extend(a << b));
+      break;
+    }
+    case SRI:
+      if (instr.funct7() == SRA) {
+        int32_t a = get_xreg(instr.rs1());
+        int32_t b = instr.shamt();
+        set_xreg(instr.rd(), sign_extend(a >> b));
+      } else {
+        uint32_t a = get_xreg(instr.rs1());
+        uint32_t b = instr.shamt();
+        set_xreg(instr.rd(), sign_extend(a >> b));
+      }
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOP(Instr instr) {
+  switch (instr.funct7()) {
+    case 0:
+      InterpretOP_0(instr);
+      break;
+    case SUB:
+      InterpretOP_SUB(instr);
+      break;
+    case MULDIV:
+      InterpretOP_MULDIV(instr);
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+}
+
+void Simulator::InterpretOP_0(Instr instr) {
+  switch (instr.funct3()) {
+    case ADD:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) + get_xreg(instr.rs2()));
+      break;
+    case SLL: {
+      uintx_t shamt = get_xreg(instr.rs2()) & (XLEN - 1);
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) << shamt);
+      break;
+    }
+    case SLT:
+      set_xreg(instr.rd(), static_cast<intx_t>(get_xreg(instr.rs1())) <
+                                   static_cast<intx_t>(get_xreg(instr.rs2()))
+                               ? 1
+                               : 0);
+      break;
+    case SLTU:
+      set_xreg(instr.rd(), static_cast<uintx_t>(get_xreg(instr.rs1())) <
+                                   static_cast<uintx_t>(get_xreg(instr.rs2()))
+                               ? 1
+                               : 0);
+      break;
+    case XOR:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) ^ get_xreg(instr.rs2()));
+      break;
+    case SR: {
+      uintx_t shamt = get_xreg(instr.rs2()) & (XLEN - 1);
+      set_xreg(instr.rd(),
+               static_cast<uintx_t>(get_xreg(instr.rs1())) >> shamt);
+      break;
+    }
+    case OR:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) | get_xreg(instr.rs2()));
+      break;
+    case AND:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) & get_xreg(instr.rs2()));
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+static intx_t mul(intx_t a, intx_t b) {
+  return a * b;
+}
+
+static intx_t mulh(intx_t a, intx_t b) {
+  const uintx_t kLoMask = (static_cast<uintx_t>(1) << (XLEN / 2)) - 1;
+  const uintx_t kHiShift = XLEN / 2;
+
+  uintx_t a_lo = a & kLoMask;
+  intx_t a_hi = a >> kHiShift;
+  uintx_t b_lo = b & kLoMask;
+  intx_t b_hi = b >> kHiShift;
+
+  uintx_t x = a_lo * b_lo;
+  intx_t y = a_hi * b_lo;
+  intx_t z = a_lo * b_hi;
+  intx_t w = a_hi * b_hi;
+
+  intx_t r0 = (x >> kHiShift) + y;
+  intx_t r1 = (r0 & kLoMask) + z;
+  return w + (r0 >> kHiShift) + (r1 >> kHiShift);
+}
+
+static uintx_t mulhu(uintx_t a, uintx_t b) {
+  const uintx_t kLoMask = (static_cast<uintx_t>(1) << (XLEN / 2)) - 1;
+  const uintx_t kHiShift = XLEN / 2;
+
+  uintx_t a_lo = a & kLoMask;
+  uintx_t a_hi = a >> kHiShift;
+  uintx_t b_lo = b & kLoMask;
+  uintx_t b_hi = b >> kHiShift;
+
+  uintx_t x = a_lo * b_lo;
+  uintx_t y = a_hi * b_lo;
+  uintx_t z = a_lo * b_hi;
+  uintx_t w = a_hi * b_hi;
+
+  uintx_t r0 = (x >> kHiShift) + y;
+  uintx_t r1 = (r0 & kLoMask) + z;
+  return w + (r0 >> kHiShift) + (r1 >> kHiShift);
+}
+
+static uintx_t mulhsu(intx_t a, uintx_t b) {
+  const uintx_t kLoMask = (static_cast<uintx_t>(1) << (XLEN / 2)) - 1;
+  const uintx_t kHiShift = XLEN / 2;
+
+  uintx_t a_lo = a & kLoMask;
+  intx_t a_hi = a >> kHiShift;
+  uintx_t b_lo = b & kLoMask;
+  uintx_t b_hi = b >> kHiShift;
+
+  uintx_t x = a_lo * b_lo;
+  intx_t y = a_hi * b_lo;
+  uintx_t z = a_lo * b_hi;
+  intx_t w = a_hi * b_hi;
+
+  intx_t r0 = (x >> kHiShift) + y;
+  uintx_t r1 = (r0 & kLoMask) + z;
+  return w + (r0 >> kHiShift) + (r1 >> kHiShift);
+}
+
+static intx_t div(intx_t a, intx_t b) {
+  if (b == 0) {
+    return -1;
+  } else if (b == -1 && a == kMinIntX) {
+    return kMinIntX;
+  } else {
+    return a / b;
+  }
+}
+
+static uintx_t divu(uintx_t a, uintx_t b) {
+  if (b == 0) {
+    return kMaxUIntX;
+  } else {
+    return a / b;
+  }
+}
+
+static intx_t rem(intx_t a, intx_t b) {
+  if (b == 0) {
+    return a;
+  } else if (b == -1 && a == kMinIntX) {
+    return 0;
+  } else {
+    return a % b;
+  }
+}
+
+static uintx_t remu(uintx_t a, uintx_t b) {
+  if (b == 0) {
+    return a;
+  } else {
+    return a % b;
+  }
+}
+
+#if XLEN >= 64
+static int32_t mulw(int32_t a, int32_t b) {
+  return a * b;
+}
+
+static int32_t divw(int32_t a, int32_t b) {
+  if (b == 0) {
+    return -1;
+  } else if (b == -1 && a == kMinInt32) {
+    return kMinInt32;
+  } else {
+    return a / b;
+  }
+}
+
+static uint32_t divuw(uint32_t a, uint32_t b) {
+  if (b == 0) {
+    return kMaxUint32;
+  } else {
+    return a / b;
+  }
+}
+
+static int32_t remw(int32_t a, int32_t b) {
+  if (b == 0) {
+    return a;
+  } else if (b == -1 && a == kMinInt32) {
+    return 0;
+  } else {
+    return a % b;
+  }
+}
+
+static uint32_t remuw(uint32_t a, uint32_t b) {
+  if (b == 0) {
+    return a;
+  } else {
+    return a % b;
+  }
+}
+#endif  // XLEN >= 64
+
+void Simulator::InterpretOP_MULDIV(Instr instr) {
+  switch (instr.funct3()) {
+    case MUL:
+      set_xreg(instr.rd(), mul(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case MULH:
+      set_xreg(instr.rd(), mulh(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case MULHSU:
+      set_xreg(instr.rd(),
+               mulhsu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case MULHU:
+      set_xreg(instr.rd(), mulhu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case DIV:
+      set_xreg(instr.rd(), div(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case DIVU:
+      set_xreg(instr.rd(), divu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case REM:
+      set_xreg(instr.rd(), rem(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    case REMU:
+      set_xreg(instr.rd(), remu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOP_SUB(Instr instr) {
+  switch (instr.funct3()) {
+    case ADD:
+      set_xreg(instr.rd(), get_xreg(instr.rs1()) - get_xreg(instr.rs2()));
+      break;
+    case SR: {
+      uintx_t shamt = get_xreg(instr.rs2()) & (XLEN - 1);
+      set_xreg(instr.rd(), static_cast<intx_t>(get_xreg(instr.rs1())) >> shamt);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOP32(Instr instr) {
+  switch (instr.funct7()) {
+#if XLEN >= 64
+    case 0:
+      InterpretOP32_0(instr);
+      break;
+    case SUB:
+      InterpretOP32_SUB(instr);
+      break;
+    case MULDIV:
+      InterpretOP32_MULDIV(instr);
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+}
+
+void Simulator::InterpretOP32_0(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case ADD: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = get_xreg(instr.rs2());
+      set_xreg(instr.rd(), sign_extend(a + b));
+      break;
+    }
+    case SLL: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = get_xreg(instr.rs2()) & (32 - 1);
+      set_xreg(instr.rd(), sign_extend(a << b));
+      break;
+    }
+    case SR: {
+      uint32_t b = get_xreg(instr.rs2()) & (32 - 1);
+      uint32_t a = get_xreg(instr.rs1());
+      set_xreg(instr.rd(), sign_extend(a >> b));
+      break;
+    }
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOP32_SUB(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case ADD: {
+      uint32_t a = get_xreg(instr.rs1());
+      uint32_t b = get_xreg(instr.rs2());
+      set_xreg(instr.rd(), sign_extend(a - b));
+      break;
+    }
+    case SR: {
+      uint32_t b = get_xreg(instr.rs2()) & (32 - 1);
+      int32_t a = get_xreg(instr.rs1());
+      set_xreg(instr.rd(), sign_extend(a >> b));
+      break;
+    }
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretOP32_MULDIV(Instr instr) {
+  switch (instr.funct3()) {
+#if XLEN >= 64
+    case MULW:
+      set_xreg(instr.rd(),
+               sign_extend(mulw(get_xreg(instr.rs1()), get_xreg(instr.rs2()))));
+      break;
+    case DIVW:
+      set_xreg(instr.rd(),
+               sign_extend(divw(get_xreg(instr.rs1()), get_xreg(instr.rs2()))));
+      break;
+    case DIVUW:
+      set_xreg(instr.rd(), sign_extend(divuw(get_xreg(instr.rs1()),
+                                             get_xreg(instr.rs2()))));
+      break;
+    case REMW:
+      set_xreg(instr.rd(),
+               sign_extend(remw(get_xreg(instr.rs1()), get_xreg(instr.rs2()))));
+      break;
+    case REMUW:
+      set_xreg(instr.rd(), sign_extend(remuw(get_xreg(instr.rs1()),
+                                             get_xreg(instr.rs2()))));
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretMISCMEM(Instr instr) {
+  switch (instr.funct3()) {
+    case FENCE:
+      std::atomic_thread_fence(std::memory_order_acq_rel);
+      break;
+    case FENCEI:
+      // Nothing to do: simulated instructions are data on the host.
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretSYSTEM(Instr instr) {
+  switch (instr.funct3()) {
+    case 0:
+      switch (instr.funct12()) {
+        case ECALL:
+          InterpretECALL(instr);
+          return;
+        case EBREAK:
+          InterpretEBREAK(instr);
+          return;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case CSRRW: {
+      if (instr.rd() == ZR) {
+        // No read effect.
+        CSRWrite(instr.csr(), get_xreg(instr.rs1()));
+      } else {
+        intx_t result = CSRRead(instr.csr());
+        CSRWrite(instr.csr(), get_xreg(instr.rs1()));
+        set_xreg(instr.rd(), result);
+      }
+      break;
+    }
+    case CSRRS: {
+      intx_t result = CSRRead(instr.csr());
+      if (instr.rs1() == ZR) {
+        // No write effect.
+      } else {
+        CSRSet(instr.csr(), get_xreg(instr.rs1()));
+      }
+      set_xreg(instr.rd(), result);
+      break;
+    }
+    case CSRRC: {
+      intx_t result = CSRRead(instr.csr());
+      if (instr.rs1() == ZR) {
+        // No write effect.
+      } else {
+        CSRClear(instr.csr(), get_xreg(instr.rs1()));
+      }
+      set_xreg(instr.rd(), result);
+      break;
+    }
+    case CSRRWI: {
+      if (instr.rd() == ZR) {
+        // No read effect.
+        CSRWrite(instr.csr(), instr.zimm());
+      } else {
+        intx_t result = CSRRead(instr.csr());
+        CSRWrite(instr.csr(), instr.zimm());
+        set_xreg(instr.rd(), result);
+      }
+      break;
+    }
+    case CSRRSI: {
+      intx_t result = CSRRead(instr.csr());
+      if (instr.zimm() == 0) {
+        // No write effect.
+      } else {
+        CSRSet(instr.csr(), instr.zimm());
+      }
+      set_xreg(instr.rd(), result);
+      break;
+    }
+    case CSRRCI: {
+      intx_t result = CSRRead(instr.csr());
+      if (instr.zimm() == 0) {
+        // No write effect.
+      } else {
+        CSRClear(instr.csr(), instr.zimm());
+      }
+      set_xreg(instr.rd(), result);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+// Calls into the Dart runtime are based on this interface.
+typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
+
+// Calls to leaf Dart runtime functions are based on this interface.
+typedef intx_t (*SimulatorLeafRuntimeCall)(intx_t r0,
+                                           intx_t r1,
+                                           intx_t r2,
+                                           intx_t r3,
+                                           intx_t r4,
+                                           intx_t r5,
+                                           intx_t r6,
+                                           intx_t r7);
+
+// [target] has several different signatures that differ from
+// SimulatorLeafRuntimeCall. We can call them all from here only because in
+// X64's calling conventions a function can be called with extra arguments
+// and the callee will see the first arguments and won't unbalance the stack.
+NO_SANITIZE_UNDEFINED("function")
+static intx_t InvokeLeafRuntime(SimulatorLeafRuntimeCall target,
+                                intx_t r0,
+                                intx_t r1,
+                                intx_t r2,
+                                intx_t r3,
+                                intx_t r4,
+                                intx_t r5,
+                                intx_t r6,
+                                intx_t r7) {
+  return target(r0, r1, r2, r3, r4, r5, r6, r7);
+}
+
+// Calls to leaf float Dart runtime functions are based on this interface.
+typedef double (*SimulatorLeafFloatRuntimeCall)(double d0,
+                                                double d1,
+                                                double d2,
+                                                double d3,
+                                                double d4,
+                                                double d5,
+                                                double d6,
+                                                double d7);
+
+// [target] has several different signatures that differ from
+// SimulatorFloatLeafRuntimeCall. We can call them all from here only because in
+// X64's calling conventions a function can be called with extra arguments
+// and the callee will see the first arguments and won't unbalance the stack.
+NO_SANITIZE_UNDEFINED("function")
+static double InvokeFloatLeafRuntime(SimulatorLeafFloatRuntimeCall target,
+                                     double d0,
+                                     double d1,
+                                     double d2,
+                                     double d3,
+                                     double d4,
+                                     double d5,
+                                     double d6,
+                                     double d7) {
+  return target(d0, d1, d2, d3, d4, d5, d6, d7);
+}
+
+// Calls to native Dart functions are based on this interface.
+typedef void (*SimulatorNativeCallWrapper)(Dart_NativeArguments arguments,
+                                           Dart_NativeFunction target);
+
+void Simulator::InterpretECALL(Instr instr) {
+  if (instr.rs1() != ZR) {
+    // Fake instruction generated by Assembler::SimulatorPrintObject.
+    if (true || IsTracingExecution()) {
+      uintx_t raw = get_xreg(instr.rs1());
+      Object& obj = Object::Handle(static_cast<ObjectPtr>(raw));
+      THR_Print("%" Px ": %s = %s\n", pc_, cpu_reg_names[instr.rs1()],
+                obj.ToCString());
+      FLAG_trace_sim_after = 1;
+    }
+    pc_ += instr.length();
+    return;
+  }
+
+  // The C ABI stack alignment is 16 for both 32 and 64 bit.
+  if (!Utils::IsAligned(get_xreg(SP), 16)) {
+    PrintRegisters();
+    PrintStack();
+    FATAL("Stack misaligned at call to C function");
+  }
+
+  SimulatorSetjmpBuffer buffer(this);
+  if (!setjmp(buffer.buffer_)) {
+    uintx_t saved_ra = get_xreg(RA);
+    Redirection* redirection = Redirection::FromECallInstruction(pc_);
+    uword external = redirection->external_function();
+    if (IsTracingExecution()) {
+      THR_Print("Call to host function at 0x%" Pd "\n", external);
+    }
+
+    if (redirection->call_kind() == kRuntimeCall) {
+      NativeArguments* arguments =
+          reinterpret_cast<NativeArguments*>(get_register(A0));
+      SimulatorRuntimeCall target =
+          reinterpret_cast<SimulatorRuntimeCall>(external);
+      target(*arguments);
+      ClobberVolatileRegisters();
+    } else if (redirection->call_kind() == kLeafRuntimeCall) {
+      ASSERT((0 <= redirection->argument_count()) &&
+             (redirection->argument_count() <= 8));
+      SimulatorLeafRuntimeCall target =
+          reinterpret_cast<SimulatorLeafRuntimeCall>(external);
+      const intx_t r0 = get_register(A0);
+      const intx_t r1 = get_register(A1);
+      const intx_t r2 = get_register(A2);
+      const intx_t r3 = get_register(A3);
+      const intx_t r4 = get_register(A4);
+      const intx_t r5 = get_register(A5);
+      const intx_t r6 = get_register(A6);
+      const intx_t r7 = get_register(A7);
+      const intx_t res =
+          InvokeLeafRuntime(target, r0, r1, r2, r3, r4, r5, r6, r7);
+      ClobberVolatileRegisters();
+      set_xreg(A0, res);  // Set returned result from function.
+    } else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
+      ASSERT((0 <= redirection->argument_count()) &&
+             (redirection->argument_count() <= 8));
+      SimulatorLeafFloatRuntimeCall target =
+          reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external);
+      const double d0 = get_fregd(FA0);
+      const double d1 = get_fregd(FA1);
+      const double d2 = get_fregd(FA2);
+      const double d3 = get_fregd(FA3);
+      const double d4 = get_fregd(FA4);
+      const double d5 = get_fregd(FA5);
+      const double d6 = get_fregd(FA6);
+      const double d7 = get_fregd(FA7);
+      const double res =
+          InvokeFloatLeafRuntime(target, d0, d1, d2, d3, d4, d5, d6, d7);
+      ClobberVolatileRegisters();
+      set_fregd(FA0, res);
+    } else if (redirection->call_kind() == kNativeCallWrapper) {
+      SimulatorNativeCallWrapper wrapper =
+          reinterpret_cast<SimulatorNativeCallWrapper>(external);
+      Dart_NativeArguments arguments =
+          reinterpret_cast<Dart_NativeArguments>(get_register(A0));
+      Dart_NativeFunction target =
+          reinterpret_cast<Dart_NativeFunction>(get_register(A1));
+      wrapper(arguments, target);
+      ClobberVolatileRegisters();
+    } else {
+      UNREACHABLE();
+    }
+
+    // Return.
+    pc_ = saved_ra;
+  } else {
+    // Coming via long jump from a throw. Continue to exception handler.
+  }
+}
+
+void Simulator::InterpretAMO(Instr instr) {
+  switch (instr.funct3()) {
+    case WIDTH32:
+      InterpretAMO32(instr);
+      break;
+    case WIDTH64:
+      InterpretAMO64(instr);
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+}
+
+// Note: This implementation does not give full LR/SC semantics because it
+// suffers from the ABA problem.
+
+template <typename type>
+void Simulator::InterpretLR(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  reserved_address_ = addr;
+  reserved_value_ = atomic->load(instr.memory_order());
+  set_xreg(instr.rd(), reserved_value_);
+}
+
+template <typename type>
+void Simulator::InterpretSC(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  if (addr != reserved_address_) {
+    set_xreg(instr.rd(), 1);
+    return;
+  }
+  type expected = reserved_value_;
+  type desired = get_xreg(instr.rs2());
+  bool success =
+      atomic->compare_exchange_strong(expected, desired, instr.memory_order());
+  set_xreg(instr.rd(), success ? 0 : 1);
+}
+
+template <typename type>
+void Simulator::InterpretAMOSWAP(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type desired = get_xreg(instr.rs2());
+  type result = atomic->exchange(desired, instr.memory_order());
+  set_xreg(instr.rd(), sign_extend(result));
+}
+
+template <typename type>
+void Simulator::InterpretAMOADD(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type arg = get_xreg(instr.rs2());
+  type result = atomic->fetch_add(arg, instr.memory_order());
+  set_xreg(instr.rd(), sign_extend(result));
+}
+
+template <typename type>
+void Simulator::InterpretAMOXOR(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type arg = get_xreg(instr.rs2());
+  type result = atomic->fetch_xor(arg, instr.memory_order());
+  set_xreg(instr.rd(), sign_extend(result));
+}
+
+template <typename type>
+void Simulator::InterpretAMOAND(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type arg = get_xreg(instr.rs2());
+  type result = atomic->fetch_and(arg, instr.memory_order());
+  set_xreg(instr.rd(), sign_extend(result));
+}
+
+template <typename type>
+void Simulator::InterpretAMOOR(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type arg = get_xreg(instr.rs2());
+  type result = atomic->fetch_or(arg, instr.memory_order());
+  set_xreg(instr.rd(), sign_extend(result));
+}
+
+template <typename type>
+void Simulator::InterpretAMOMIN(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type expected = atomic->load(std::memory_order_relaxed);
+  type compare = get_xreg(instr.rs2());
+  type desired;
+  do {
+    desired = expected < compare ? expected : compare;
+  } while (
+      !atomic->compare_exchange_weak(expected, desired, instr.memory_order()));
+  set_xreg(instr.rd(), sign_extend(expected));
+}
+
+template <typename type>
+void Simulator::InterpretAMOMAX(Instr instr) {
+  uintx_t addr = get_xreg(instr.rs1());
+  if ((addr & (sizeof(type) - 1)) != 0) {
+    FATAL("Misaligned atomic memory operation");
+  }
+  std::atomic<type>* atomic = reinterpret_cast<std::atomic<type>*>(addr);
+  type expected = atomic->load(std::memory_order_relaxed);
+  type compare = get_xreg(instr.rs2());
+  type desired;
+  do {
+    desired = expected > compare ? expected : compare;
+  } while (
+      !atomic->compare_exchange_weak(expected, desired, instr.memory_order()));
+  set_xreg(instr.rd(), sign_extend(expected));
+}
+
+void Simulator::InterpretAMO32(Instr instr) {
+  switch (instr.funct5()) {
+    case LR:
+      InterpretLR<int32_t>(instr);
+      break;
+    case SC:
+      InterpretSC<int32_t>(instr);
+      break;
+    case AMOSWAP:
+      InterpretAMOSWAP<int32_t>(instr);
+      break;
+    case AMOADD:
+      InterpretAMOADD<int32_t>(instr);
+      break;
+    case AMOXOR:
+      InterpretAMOXOR<int32_t>(instr);
+      break;
+    case AMOAND:
+      InterpretAMOAND<int32_t>(instr);
+      break;
+    case AMOOR:
+      InterpretAMOOR<int32_t>(instr);
+      break;
+    case AMOMIN:
+      InterpretAMOMIN<int32_t>(instr);
+      break;
+    case AMOMAX:
+      InterpretAMOMAX<int32_t>(instr);
+      break;
+    case AMOMINU:
+      InterpretAMOMIN<uint32_t>(instr);
+      break;
+    case AMOMAXU:
+      InterpretAMOMAX<uint32_t>(instr);
+      break;
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretAMO64(Instr instr) {
+  switch (instr.funct5()) {
+#if XLEN >= 64
+    case LR:
+      InterpretLR<int64_t>(instr);
+      break;
+    case SC:
+      InterpretSC<int64_t>(instr);
+      break;
+    case AMOSWAP:
+      InterpretAMOSWAP<int64_t>(instr);
+      break;
+    case AMOADD:
+      InterpretAMOADD<int64_t>(instr);
+      break;
+    case AMOXOR:
+      InterpretAMOXOR<int64_t>(instr);
+      break;
+    case AMOAND:
+      InterpretAMOAND<int64_t>(instr);
+      break;
+    case AMOOR:
+      InterpretAMOOR<int64_t>(instr);
+      break;
+    case AMOMIN:
+      InterpretAMOMIN<int64_t>(instr);
+      break;
+    case AMOMAX:
+      InterpretAMOMAX<int64_t>(instr);
+      break;
+    case AMOMINU:
+      InterpretAMOMIN<uint64_t>(instr);
+      break;
+    case AMOMAXU:
+      InterpretAMOMAX<uint64_t>(instr);
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretFMADD(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      float rs3 = get_fregs(instr.frs3());
+      set_fregs(instr.frd(), (rs1 * rs2) + rs3);
+      break;
+    }
+    case F2_D: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      double rs3 = get_fregd(instr.frs3());
+      set_fregd(instr.frd(), (rs1 * rs2) + rs3);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretFMSUB(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      float rs3 = get_fregs(instr.frs3());
+      set_fregs(instr.frd(), (rs1 * rs2) - rs3);
+      break;
+    }
+    case F2_D: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      double rs3 = get_fregd(instr.frs3());
+      set_fregd(instr.frd(), (rs1 * rs2) - rs3);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretFNMSUB(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      float rs3 = get_fregs(instr.frs3());
+      set_fregs(instr.frd(), -(rs1 * rs2) + rs3);
+      break;
+    }
+    case F2_D: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      double rs3 = get_fregd(instr.frs3());
+      set_fregd(instr.frd(), -(rs1 * rs2) + rs3);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretFNMADD(Instr instr) {
+  switch (instr.funct2()) {
+    case F2_S: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      float rs3 = get_fregs(instr.frs3());
+      set_fregs(instr.frd(), -(rs1 * rs2) - rs3);
+      break;
+    }
+    case F2_D: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      double rs3 = get_fregd(instr.frs3());
+      set_fregd(instr.frd(), -(rs1 * rs2) - rs3);
+      break;
+    }
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+static bool is_quiet(float x) {
+  // Warning: This is true on Intel/ARM, but not everywhere.
+  return (bit_cast<uint32_t>(x) & (static_cast<uint32_t>(1) << 22)) != 0;
+}
+
+static uintx_t fclass(float x) {
+  ASSERT(!is_quiet(std::numeric_limits<float>::signaling_NaN()));
+  ASSERT(is_quiet(std::numeric_limits<float>::quiet_NaN()));
+
+  switch (fpclassify(x)) {
+    case FP_INFINITE:
+      return signbit(x) ? kFClassNegInfinity : kFClassPosInfinity;
+    case FP_NAN:
+      return is_quiet(x) ? kFClassQuietNan : kFClassSignallingNan;
+    case FP_ZERO:
+      return signbit(x) ? kFClassNegZero : kFClassPosZero;
+    case FP_SUBNORMAL:
+      return signbit(x) ? kFClassNegSubnormal : kFClassPosSubnormal;
+    case FP_NORMAL:
+      return signbit(x) ? kFClassNegNormal : kFClassPosNormal;
+    default:
+      UNREACHABLE();
+      return 0;
+  }
+}
+
+static bool is_quiet(double x) {
+  // Warning: This is true on Intel/ARM, but not everywhere.
+  return (bit_cast<uint64_t>(x) & (static_cast<uint64_t>(1) << 51)) != 0;
+}
+
+static uintx_t fclass(double x) {
+  ASSERT(!is_quiet(std::numeric_limits<double>::signaling_NaN()));
+  ASSERT(is_quiet(std::numeric_limits<double>::quiet_NaN()));
+
+  switch (fpclassify(x)) {
+    case FP_INFINITE:
+      return signbit(x) ? kFClassNegInfinity : kFClassPosInfinity;
+    case FP_NAN:
+      return is_quiet(x) ? kFClassQuietNan : kFClassSignallingNan;
+    case FP_ZERO:
+      return signbit(x) ? kFClassNegZero : kFClassPosZero;
+    case FP_SUBNORMAL:
+      return signbit(x) ? kFClassNegSubnormal : kFClassPosSubnormal;
+    case FP_NORMAL:
+      return signbit(x) ? kFClassNegNormal : kFClassPosNormal;
+    default:
+      UNREACHABLE();
+      return 0;
+  }
+}
+
+static float roundevenf(float x) {
+  float rounded = roundf(x);
+  if (fabsf(x - rounded) == 0.5f) {  // Tie
+    if (fmodf(rounded, 2) != 0) {    // Not even
+      if (rounded > 0.0f) {
+        rounded -= 1.0f;
+      } else {
+        rounded += 1.0f;
+      }
+      ASSERT(fmodf(rounded, 2) == 0);
+    }
+  }
+  return rounded;
+}
+
+static double roundeven(double x) {
+  double rounded = round(x);
+  if (fabs(x - rounded) == 0.5f) {  // Tie
+    if (fmod(rounded, 2) != 0) {    // Not even
+      if (rounded > 0.0f) {
+        rounded -= 1.0f;
+      } else {
+        rounded += 1.0f;
+      }
+      ASSERT(fmod(rounded, 2) == 0);
+    }
+  }
+  return rounded;
+}
+
+static float Round(float x, RoundingMode rounding) {
+  switch (rounding) {
+    case RNE:  // Round to Nearest, ties to Even
+      return roundevenf(x);
+    case RTZ:  // Round towards Zero
+      return truncf(x);
+    case RDN:  // Round Down (toward negative infinity)
+      return floorf(x);
+    case RUP:  // Round Up (toward positive infinity)
+      return ceilf(x);
+    case RMM:  // Round to nearest, ties to Max Magnitude
+      return roundf(x);
+    case DYN:  // Dynamic rounding mode
+      UNIMPLEMENTED();
+    default:
+      FATAL("Invalid rounding mode");
+  }
+}
+
+static double Round(double x, RoundingMode rounding) {
+  switch (rounding) {
+    case RNE:  // Round to Nearest, ties to Even
+      return roundeven(x);
+    case RTZ:  // Round towards Zero
+      return trunc(x);
+    case RDN:  // Round Down (toward negative infinity)
+      return floor(x);
+    case RUP:  // Round Up (toward positive infinity)
+      return ceil(x);
+    case RMM:  // Round to nearest, ties to Max Magnitude
+      return round(x);
+    case DYN:  // Dynamic rounding mode
+      UNIMPLEMENTED();
+    default:
+      FATAL("Invalid rounding mode");
+  }
+}
+
+static int32_t fcvtws(float x, RoundingMode rounding) {
+  if (x < static_cast<float>(kMinInt32)) {
+    return kMinInt32;  // Negative infinity.
+  }
+  if (x < static_cast<float>(kMaxInt32)) {
+    return static_cast<int32_t>(Round(x, rounding));
+  }
+  return kMaxInt32;  // Positive infinity, NaN.
+}
+
+static uint32_t fcvtwus(float x, RoundingMode rounding) {
+  if (x < static_cast<float>(0)) {
+    return 0;  // Negative infinity.
+  }
+  if (x < static_cast<float>(kMaxUint32)) {
+    return static_cast<uint32_t>(Round(x, rounding));
+  }
+  return kMaxUint32;  // Positive infinity, NaN.
+}
+
+#if XLEN >= 64
+static int64_t fcvtls(float x, RoundingMode rounding) {
+  if (x < static_cast<float>(kMinInt64)) {
+    return kMinInt64;  // Negative infinity.
+  }
+  if (x < static_cast<float>(kMaxInt64)) {
+    return static_cast<int64_t>(Round(x, rounding));
+  }
+  return kMaxInt64;  // Positive infinity, NaN.
+}
+
+static uint64_t fcvtlus(float x, RoundingMode rounding) {
+  if (x < static_cast<float>(0.0)) {
+    return 0;  // Negative infinity.
+  }
+  if (x < static_cast<float>(kMaxUint64)) {
+    return static_cast<uint64_t>(Round(x, rounding));
+  }
+  return kMaxUint64;  // Positive infinity, NaN.
+}
+#endif  // XLEN >= 64
+
+static int32_t fcvtwd(double x, RoundingMode rounding) {
+  if (x < static_cast<double>(kMinInt32)) {
+    return kMinInt32;  // Negative infinity.
+  }
+  if (x < static_cast<double>(kMaxInt32)) {
+    return static_cast<int32_t>(Round(x, rounding));
+  }
+  return kMaxInt32;  // Positive infinity, NaN.
+}
+
+static uint32_t fcvtwud(double x, RoundingMode rounding) {
+  if (x < static_cast<double>(0)) {
+    return 0;  // Negative infinity.
+  }
+  if (x < static_cast<double>(kMaxUint32)) {
+    return static_cast<uint32_t>(Round(x, rounding));
+  }
+  return kMaxUint32;  // Positive infinity, NaN.
+}
+
+#if XLEN >= 64
+static int64_t fcvtld(double x, RoundingMode rounding) {
+  if (x < static_cast<double>(kMinInt64)) {
+    return kMinInt64;  // Negative infinity.
+  }
+  if (x < static_cast<double>(kMaxInt64)) {
+    return static_cast<int64_t>(Round(x, rounding));
+  }
+  return kMaxInt64;  // Positive infinity, NaN.
+}
+
+static uint64_t fcvtlud(double x, RoundingMode rounding) {
+  if (x < static_cast<double>(0.0)) {
+    return 0;  // Negative infinity.
+  }
+  if (x < static_cast<double>(kMaxUint64)) {
+    return static_cast<uint64_t>(Round(x, rounding));
+  }
+  return kMaxUint64;  // Positive infinity, NaN.
+}
+#endif  // XLEN >= 64
+
+void Simulator::InterpretOPFP(Instr instr) {
+  switch (instr.funct7()) {
+    case FADDS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      set_fregs(instr.frd(), rs1 + rs2);
+      break;
+    }
+    case FSUBS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      set_fregs(instr.frd(), rs1 - rs2);
+      break;
+    }
+    case FMULS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      set_fregs(instr.frd(), rs1 * rs2);
+      break;
+    }
+    case FDIVS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      set_fregs(instr.frd(), rs1 / rs2);
+      break;
+    }
+    case FSQRTS: {
+      float rs1 = get_fregs(instr.frs1());
+      set_fregs(instr.frd(), sqrtf(rs1));
+      break;
+    }
+    case FSGNJS: {
+      const uint32_t kSignMask = static_cast<uint32_t>(1) << 31;
+      uint32_t rs1 = bit_cast<uint32_t>(get_fregs(instr.frs1()));
+      uint32_t rs2 = bit_cast<uint32_t>(get_fregs(instr.frs2()));
+      uint32_t result;
+      switch (instr.funct3()) {
+        case J:
+          result = (rs1 & ~kSignMask) | (rs2 & kSignMask);
+          break;
+        case JN:
+          result = (rs1 & ~kSignMask) | (~rs2 & kSignMask);
+          break;
+        case JX:
+          result = (rs1 & ~kSignMask) | ((rs1 ^ rs2) & kSignMask);
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      set_fregs(instr.frd(), bit_cast<float>(result));
+      break;
+    }
+    case FMINMAXS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      switch (instr.funct3()) {
+        case MIN:
+          set_fregs(instr.frd(), fminf(rs1, rs2));
+          break;
+        case MAX:
+          set_fregs(instr.frd(), fmaxf(rs1, rs2));
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+    case FCMPS: {
+      float rs1 = get_fregs(instr.frs1());
+      float rs2 = get_fregs(instr.frs2());
+      switch (instr.funct3()) {
+        case FEQ:
+          set_xreg(instr.rd(), rs1 == rs2 ? 1 : 0);
+          break;
+        case FLT:
+          set_xreg(instr.rd(), rs1 < rs2 ? 1 : 0);
+          break;
+        case FLE:
+          set_xreg(instr.rd(), rs1 <= rs2 ? 1 : 0);
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+    case FCLASSS:  // = FMVXW
+      switch (instr.funct3()) {
+        case 1:
+          // fclass.s
+          set_xreg(instr.rd(), fclass(get_fregs(instr.frs1())));
+          break;
+        case 0:
+          // fmv.x.s
+          set_xreg(instr.rd(),
+                   sign_extend(bit_cast<int32_t>(get_fregs(instr.frs1()))));
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case FCVTintS:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          set_xreg(instr.rd(), sign_extend(fcvtws(get_fregs(instr.frs1()),
+                                                  instr.rounding())));
+          break;
+        case WU:
+          set_xreg(instr.rd(), sign_extend(fcvtwus(get_fregs(instr.frs1()),
+                                                   instr.rounding())));
+          break;
+#if XLEN >= 64
+        case L:
+          set_xreg(instr.rd(), sign_extend(fcvtls(get_fregs(instr.frs1()),
+                                                  instr.rounding())));
+          break;
+        case LU:
+          set_xreg(instr.rd(), sign_extend(fcvtlus(get_fregs(instr.frs1()),
+                                                   instr.rounding())));
+          break;
+#endif  // XLEN >= 64
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case FCVTSint:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          set_fregs(
+              instr.frd(),
+              static_cast<float>(static_cast<int32_t>(get_xreg(instr.rs1()))));
+          break;
+        case WU:
+          set_fregs(
+              instr.frd(),
+              static_cast<float>(static_cast<uint32_t>(get_xreg(instr.rs1()))));
+          break;
+#if XLEN >= 64
+        case L:
+          set_fregs(
+              instr.frd(),
+              static_cast<float>(static_cast<int64_t>(get_xreg(instr.rs1()))));
+          break;
+        case LU:
+          set_fregs(
+              instr.frd(),
+              static_cast<float>(static_cast<uint64_t>(get_xreg(instr.rs1()))));
+          break;
+#endif  // XLEN >= 64
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case FMVWX:
+      set_fregs(instr.frd(),
+                bit_cast<float>(static_cast<int32_t>(get_xreg(instr.rs1()))));
+      break;
+    case FADDD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      set_fregd(instr.frd(), rs1 + rs2);
+      break;
+    }
+    case FSUBD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      set_fregd(instr.frd(), rs1 - rs2);
+      break;
+    }
+    case FMULD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      set_fregd(instr.frd(), rs1 * rs2);
+      break;
+    }
+    case FDIVD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      set_fregd(instr.frd(), rs1 / rs2);
+      break;
+    }
+    case FSQRTD: {
+      double rs1 = get_fregd(instr.frs1());
+      set_fregd(instr.frd(), sqrt(rs1));
+      break;
+    }
+    case FSGNJD: {
+      const uint64_t kSignMask = static_cast<uint64_t>(1) << 63;
+      uint64_t rs1 = bit_cast<uint64_t>(get_fregd(instr.frs1()));
+      uint64_t rs2 = bit_cast<uint64_t>(get_fregd(instr.frs2()));
+      uint64_t result;
+      switch (instr.funct3()) {
+        case J:
+          result = (rs1 & ~kSignMask) | (rs2 & kSignMask);
+          break;
+        case JN:
+          result = (rs1 & ~kSignMask) | (~rs2 & kSignMask);
+          break;
+        case JX:
+          result = (rs1 & ~kSignMask) | ((rs1 ^ rs2) & kSignMask);
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      set_fregd(instr.frd(), bit_cast<double>(result));
+      break;
+    }
+    case FMINMAXD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      switch (instr.funct3()) {
+        case MIN:
+          set_fregd(instr.frd(), fmin(rs1, rs2));
+          break;
+        case MAX:
+          set_fregd(instr.frd(), fmax(rs1, rs2));
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+    case FCVTS: {
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case 1:
+          set_fregs(instr.frd(), static_cast<float>(get_fregd(instr.frs1())));
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+    case FCVTD: {
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case 0:
+          set_fregd(instr.frd(), static_cast<double>(get_fregs(instr.frs1())));
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+
+    case FCMPD: {
+      double rs1 = get_fregd(instr.frs1());
+      double rs2 = get_fregd(instr.frs2());
+      switch (instr.funct3()) {
+        case FEQ:
+          set_xreg(instr.rd(), rs1 == rs2 ? 1 : 0);
+          break;
+        case FLT:
+          set_xreg(instr.rd(), rs1 < rs2 ? 1 : 0);
+          break;
+        case FLE:
+          set_xreg(instr.rd(), rs1 <= rs2 ? 1 : 0);
+          break;
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    }
+    case FCLASSD:  // = FMVXD
+      switch (instr.funct3()) {
+        case 1:
+          // fclass.d
+          set_xreg(instr.rd(), fclass(get_fregd(instr.frs1())));
+          break;
+#if XLEN >= 64
+        case 0:
+          // fmv.x.d
+          set_xreg(instr.rd(), bit_cast<int64_t>(get_fregd(instr.frs1())));
+          break;
+#endif  // XLEN >= 64
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case FCVTintD:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          set_xreg(instr.rd(), sign_extend(fcvtwd(get_fregd(instr.frs1()),
+                                                  instr.rounding())));
+          break;
+        case WU:
+          set_xreg(instr.rd(), sign_extend(fcvtwud(get_fregd(instr.frs1()),
+                                                   instr.rounding())));
+          break;
+#if XLEN >= 64
+        case L:
+          set_xreg(instr.rd(), sign_extend(fcvtld(get_fregd(instr.frs1()),
+                                                  instr.rounding())));
+          break;
+        case LU:
+          set_xreg(instr.rd(), sign_extend(fcvtlud(get_fregd(instr.frs1()),
+                                                   instr.rounding())));
+          break;
+#endif  // XLEN >= 64
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+    case FCVTDint:
+      switch (static_cast<FcvtRs2>(instr.rs2())) {
+        case W:
+          set_fregd(
+              instr.frd(),
+              static_cast<double>(static_cast<int32_t>(get_xreg(instr.rs1()))));
+          break;
+        case WU:
+          set_fregd(instr.frd(), static_cast<double>(static_cast<uint32_t>(
+                                     get_xreg(instr.rs1()))));
+          break;
+#if XLEN >= 64
+        case L:
+          set_fregd(
+              instr.frd(),
+              static_cast<double>(static_cast<int64_t>(get_xreg(instr.rs1()))));
+          break;
+        case LU:
+          set_fregd(instr.frd(), static_cast<double>(static_cast<uint64_t>(
+                                     get_xreg(instr.rs1()))));
+          break;
+#endif  // XLEN >= 64
+        default:
+          IllegalInstruction(instr);
+      }
+      break;
+#if XLEN >= 64
+    case FMVDX:
+      set_fregd(instr.frd(), bit_cast<double>(get_xreg(instr.rs1())));
+      break;
+#endif  // XLEN >= 64
+    default:
+      IllegalInstruction(instr);
+  }
+  pc_ += instr.length();
+}
+
+void Simulator::InterpretEBREAK(Instr instr) {
+  PrintRegisters();
+  PrintStack();
+  FATAL("Encounted EBREAK");
+}
+
+void Simulator::InterpretEBREAK(CInstr instr) {
+  PrintRegisters();
+  PrintStack();
+  FATAL("Encounted EBREAK");
+}
+
+void Simulator::IllegalInstruction(Instr instr) {
+  PrintRegisters();
+  PrintStack();
+  FATAL("Illegal instruction: 0x%08x", instr.encoding());
+}
+
+void Simulator::IllegalInstruction(CInstr instr) {
+  PrintRegisters();
+  PrintStack();
+  FATAL("Illegal instruction: 0x%04x", instr.encoding());
+}
+
+template <typename type>
+type Simulator::MemoryRead(uintx_t addr, Register base) {
+#if defined(DEBUG)
+  if ((base == SP) || (base == FP)) {
+    if ((addr + sizeof(type) > stack_base()) || (addr < get_xreg(SP))) {
+      PrintRegisters();
+      PrintStack();
+      FATAL("Out-of-bounds stack access");
+    }
+  } else {
+    const uintx_t kPageSize = 16 * KB;
+    if ((addr < kPageSize) || (addr + sizeof(type) >= ~kPageSize)) {
+      PrintRegisters();
+      PrintStack();
+      FATAL("Bad memory access");
+    }
+  }
+#endif
+  return *reinterpret_cast<type*>(addr);
+}
+
+template <typename type>
+void Simulator::MemoryWrite(uintx_t addr, type value, Register base) {
+#if defined(DEBUG)
+  if ((base == SP) || (base == FP)) {
+    if ((addr + sizeof(type) > stack_base()) || (addr < get_xreg(SP))) {
+      PrintRegisters();
+      PrintStack();
+      FATAL("Out-of-bounds stack access");
+    }
+  } else {
+    const uintx_t kPageSize = 16 * KB;
+    if ((addr < kPageSize) || (addr + sizeof(type) >= ~kPageSize)) {
+      PrintRegisters();
+      PrintStack();
+      FATAL("Bad memory access");
+    }
+  }
+#endif
+  *reinterpret_cast<type*>(addr) = value;
+}
+
+enum ControlStatusRegister {
+  fflags = 0x001,
+  frm = 0x002,
+  fcsr = 0x003,
+  cycle = 0xC00,
+  time = 0xC01,
+  instret = 0xC02,
+#if XLEN == 32
+  cycleh = 0xC80,
+  timeh = 0xC81,
+  instreth = 0xC82,
+#endif
+};
+
+intx_t Simulator::CSRRead(uint16_t csr) {
+  switch (csr) {
+    case fcsr:
+      return fcsr_;
+    case cycle:
+      return instret_ / 2;
+    case time:
+      return 0;
+    case instret:
+      return instret_;
+#if XLEN == 32
+    case cycleh:
+      return (instret_ / 2) >> 32;
+    case timeh:
+      return 0;
+    case instreth:
+      return instret_ >> 32;
+#endif
+    default:
+      FATAL("Unknown CSR: %d", csr);
+  }
+}
+
+void Simulator::CSRWrite(uint16_t csr, intx_t value) {
+  UNIMPLEMENTED();
+}
+
+void Simulator::CSRSet(uint16_t csr, intx_t mask) {
+  UNIMPLEMENTED();
+}
+
+void Simulator::CSRClear(uint16_t csr, intx_t mask) {
+  UNIMPLEMENTED();
+}
+
+}  // namespace dart
+
+#endif  // !defined(USING_SIMULATOR)
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/simulator_riscv.h b/runtime/vm/simulator_riscv.h
new file mode 100644
index 0000000..b63ed39
--- /dev/null
+++ b/runtime/vm/simulator_riscv.h
@@ -0,0 +1,343 @@
+// 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.
+
+#ifndef RUNTIME_VM_SIMULATOR_RISCV_H_
+#define RUNTIME_VM_SIMULATOR_RISCV_H_
+
+#ifndef RUNTIME_VM_SIMULATOR_H_
+#error Do not include simulator_riscv.h directly; use simulator.h.
+#endif
+
+#include "vm/constants.h"
+#include "vm/random.h"
+
+namespace dart {
+
+class Isolate;
+class Mutex;
+class SimulatorSetjmpBuffer;
+class Thread;
+
+// TODO(riscv): Introduce random LR/SC failures.
+// TODO(riscv): Dynamic rounding mode and other FSCR state.
+class Simulator {
+ public:
+  static const uword kSimulatorStackUnderflowSize = 64;
+
+  Simulator();
+  ~Simulator();
+
+  static Simulator* Current();
+
+  intx_t CallX(intx_t function,
+               intx_t arg0 = 0,
+               intx_t arg1 = 0,
+               intx_t arg2 = 0,
+               intx_t arg3 = 0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_xreg(A0, arg0);
+    set_xreg(A1, arg1);
+    set_xreg(A2, arg2);
+    set_xreg(A3, arg3);
+    RunCall(function, &preserved);
+    return get_xreg(A0);
+  }
+
+  intx_t CallI(intx_t function, double arg0, double arg1 = 0.0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregd(FA0, arg0);
+    set_fregd(FA1, arg1);
+    RunCall(function, &preserved);
+    return get_xreg(A0);
+  }
+  intx_t CallI(intx_t function, float arg0, float arg1 = 0.0f) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregs(FA0, arg0);
+    set_fregs(FA1, arg1);
+    RunCall(function, &preserved);
+    return get_xreg(A0);
+  }
+
+  double CallD(intx_t function, intx_t arg0, intx_t arg1 = 0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_xreg(A0, arg0);
+    set_xreg(A1, arg1);
+    RunCall(function, &preserved);
+    return get_fregd(FA0);
+  }
+  double CallD(intx_t function,
+               double arg0,
+               double arg1 = 0.0,
+               double arg2 = 0.0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregd(FA0, arg0);
+    set_fregd(FA1, arg1);
+    set_fregd(FA2, arg2);
+    RunCall(function, &preserved);
+    return get_fregd(FA0);
+  }
+  double CallD(intx_t function, intx_t arg0, double arg1) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_xreg(A0, arg0);
+    set_fregd(FA0, arg1);
+    RunCall(function, &preserved);
+    return get_fregd(FA0);
+  }
+  double CallD(intx_t function, float arg0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregs(FA0, arg0);
+    RunCall(function, &preserved);
+    return get_fregd(FA0);
+  }
+
+  float CallF(intx_t function, intx_t arg0, intx_t arg1 = 0) {
+    PreservedRegisters preserved;
+    SavePreservedRegisters(&preserved);
+    set_xreg(A0, arg0);
+    set_xreg(A1, arg1);
+    RunCall(function, &preserved);
+    return get_fregs(FA0);
+  }
+  float CallF(intx_t function,
+              float arg0,
+              float arg1 = 0.0f,
+              float arg2 = 0.0f) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregs(FA0, arg0);
+    set_fregs(FA1, arg1);
+    set_fregs(FA2, arg2);
+    RunCall(function, &preserved);
+    return get_fregs(FA0);
+  }
+  float CallF(intx_t function, intx_t arg0, float arg1) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_xreg(A0, arg0);
+    set_fregs(FA0, arg1);
+    RunCall(function, &preserved);
+    return get_fregs(FA0);
+  }
+  float CallF(intx_t function, double arg0) {
+    PreservedRegisters preserved;
+    PrepareCall(&preserved);
+    set_fregd(FA0, arg0);
+    RunCall(function, &preserved);
+    return get_fregs(FA0);
+  }
+
+  // Dart generally calls into generated code with 4 parameters. This is a
+  // convenience function, which sets up the simulator state and grabs the
+  // result on return. The return value is A0. The parameters are placed in
+  // A0-3.
+  int64_t Call(intx_t entry,
+               intx_t parameter0,
+               intx_t parameter1,
+               intx_t parameter2,
+               intx_t parameter3,
+               bool fp_return = false,
+               bool fp_args = false);
+
+  // Runtime and native call support.
+  enum CallKind {
+    kRuntimeCall,
+    kLeafRuntimeCall,
+    kLeafFloatRuntimeCall,
+    kNativeCallWrapper
+  };
+  static uword RedirectExternalReference(uword function,
+                                         CallKind call_kind,
+                                         int argument_count);
+
+  static uword FunctionForRedirect(uword redirect);
+
+  void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
+
+  uintx_t get_register(Register rs) const { return get_xreg(rs); }
+  uintx_t get_pc() const { return pc_; }
+  uintx_t get_sp() const { return get_xreg(SP); }
+  uintx_t get_fp() const { return get_xreg(FP); }
+  void PrintRegisters();
+  void PrintStack();
+
+  // High address.
+  uword stack_base() const { return stack_base_; }
+  // Limit for StackOverflowError.
+  uword overflow_stack_limit() const { return overflow_stack_limit_; }
+  // Low address.
+  uword stack_limit() const { return stack_limit_; }
+
+  // Accessor to the instruction counter.
+  uint64_t get_icount() const { return instret_; }
+
+  // Call on program start.
+  static void Init();
+
+ private:
+  struct PreservedRegisters {
+    uintx_t xregs[kNumberOfCpuRegisters];
+    double fregs[kNumberOfFpuRegisters];
+  };
+  void PrepareCall(PreservedRegisters* preserved);
+  void ClobberVolatileRegisters();
+  void SavePreservedRegisters(PreservedRegisters* preserved);
+  void CheckPreservedRegisters(PreservedRegisters* preserved);
+  void RunCall(intx_t function, PreservedRegisters* preserved);
+
+  void Interpret(Instr instr);
+  void Interpret(CInstr instr);
+  void InterpretLUI(Instr instr);
+  void InterpretAUIPC(Instr instr);
+  void InterpretJAL(Instr instr);
+  void InterpretJALR(Instr instr);
+  void InterpretBRANCH(Instr instr);
+  void InterpretLOAD(Instr instr);
+  void InterpretSTORE(Instr instr);
+  void InterpretOPIMM(Instr instr);
+  void InterpretOPIMM32(Instr instr);
+  void InterpretOP(Instr instr);
+  void InterpretOP_0(Instr instr);
+  void InterpretOP_SUB(Instr instr);
+  void InterpretOP_MULDIV(Instr instr);
+  void InterpretOP32(Instr instr);
+  void InterpretOP32_0(Instr instr);
+  void InterpretOP32_SUB(Instr instr);
+  void InterpretOP32_MULDIV(Instr instr);
+  void InterpretMISCMEM(Instr instr);
+  void InterpretSYSTEM(Instr instr);
+  void InterpretECALL(Instr instr);
+  void InterpretEBREAK(Instr instr);
+  void InterpretEBREAK(CInstr instr);
+  void InterpretAMO(Instr instr);
+  void InterpretAMO32(Instr instr);
+  void InterpretAMO64(Instr instr);
+  template <typename type>
+  void InterpretLR(Instr instr);
+  template <typename type>
+  void InterpretSC(Instr instr);
+  template <typename type>
+  void InterpretAMOSWAP(Instr instr);
+  template <typename type>
+  void InterpretAMOADD(Instr instr);
+  template <typename type>
+  void InterpretAMOXOR(Instr instr);
+  template <typename type>
+  void InterpretAMOAND(Instr instr);
+  template <typename type>
+  void InterpretAMOOR(Instr instr);
+  template <typename type>
+  void InterpretAMOMIN(Instr instr);
+  template <typename type>
+  void InterpretAMOMAX(Instr instr);
+  template <typename type>
+  void InterpretAMOMINU(Instr instr);
+  template <typename type>
+  void InterpretAMOMAXU(Instr instr);
+  void InterpretLOADFP(Instr instr);
+  void InterpretSTOREFP(Instr instr);
+  void InterpretFMADD(Instr instr);
+  void InterpretFMSUB(Instr instr);
+  void InterpretFNMADD(Instr instr);
+  void InterpretFNMSUB(Instr instr);
+  void InterpretOPFP(Instr instr);
+  DART_NORETURN void IllegalInstruction(Instr instr);
+  DART_NORETURN void IllegalInstruction(CInstr instr);
+
+  template <typename type>
+  type MemoryRead(uintx_t address, Register base);
+  template <typename type>
+  void MemoryWrite(uintx_t address, type value, Register base);
+
+  intx_t CSRRead(uint16_t csr);
+  void CSRWrite(uint16_t csr, intx_t value);
+  void CSRSet(uint16_t csr, intx_t mask);
+  void CSRClear(uint16_t csr, intx_t mask);
+
+  uintx_t get_xreg(Register rs) const { return xregs_[rs]; }
+  void set_xreg(Register rd, uintx_t value) {
+    if (rd != ZR) {
+      xregs_[rd] = value;
+    }
+  }
+
+  double get_fregd(FRegister rs) const { return fregs_[rs]; }
+  void set_fregd(FRegister rd, double value) { fregs_[rd] = value; }
+
+  static constexpr uint64_t kNaNBox = 0xFFFFFFFF00000000;
+
+  float get_fregs(FRegister rs) const {
+    uint64_t bits64 = bit_cast<uint64_t>(fregs_[rs]);
+    if ((bits64 & kNaNBox) != kNaNBox) {
+      // When the register value isn't a valid NaN, the canonical NaN is used
+      // instead.
+      return bit_cast<float>(0x7fc00000);
+    }
+    uint32_t bits32 = static_cast<uint32_t>(bits64);
+    return bit_cast<float>(bits32);
+  }
+  void set_fregs(FRegister rd, float value) {
+    uint32_t bits32 = bit_cast<uint32_t>(value);
+    uint64_t bits64 = static_cast<uint64_t>(bits32);
+    bits64 |= kNaNBox;
+    fregs_[rd] = bit_cast<double>(bits64);
+  }
+
+  // Known bad pc value to ensure that the simulator does not execute
+  // without being properly setup.
+  static constexpr uword kBadLR = -1;
+  // A pc value used to signal the simulator to stop execution.  Generally
+  // the lr is set to this value on transition from native C code to
+  // simulated execution, so that the simulator can "return" to the native
+  // C code.
+  static constexpr uword kEndSimulatingPC = -2;
+
+  // I state.
+  uintx_t pc_;
+  uintx_t xregs_[kNumberOfCpuRegisters];
+  uint64_t instret_;  // "Instructions retired" - mandatory counter.
+
+  // A state.
+  uintx_t reserved_address_;
+  uintx_t reserved_value_;
+
+  // F/D state.
+  double fregs_[kNumberOfFpuRegisters];
+  uint32_t fcsr_;
+
+  // Simulator support.
+  char* stack_;
+  uword stack_limit_;
+  uword overflow_stack_limit_;
+  uword stack_base_;
+  Random random_;
+  SimulatorSetjmpBuffer* last_setjmp_buffer_;
+
+  static bool IsIllegalAddress(uword addr) { return addr < 64 * 1024; }
+
+  // Executes RISC-V instructions until the PC reaches kEndSimulatingPC.
+  void Execute();
+
+  // Returns true if tracing of executed instructions is enabled.
+  bool IsTracingExecution() const;
+
+  // Longjmp support for exceptions.
+  SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
+  void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
+    last_setjmp_buffer_ = buffer;
+  }
+
+  friend class SimulatorSetjmpBuffer;
+  DISALLOW_COPY_AND_ASSIGN(Simulator);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_SIMULATOR_RISCV_H_
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index b826aa9..ca98fb9 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -21,6 +21,7 @@
 const char* SourceReport::kCoverageStr = "Coverage";
 const char* SourceReport::kPossibleBreakpointsStr = "PossibleBreakpoints";
 const char* SourceReport::kProfileStr = "_Profile";
+const char* SourceReport::kBranchCoverageStr = "BranchCoverage";
 
 SourceReport::SourceReport(intptr_t report_set,
                            CompileMode compile_mode,
@@ -285,7 +286,8 @@
 
 void SourceReport::PrintCoverageData(JSONObject* jsobj,
                                      const Function& function,
-                                     const Code& code) {
+                                     const Code& code,
+                                     bool report_branch_coverage) {
   ASSERT(!code.IsNull());
   const TokenPosition& begin_pos = function.token_pos();
   const TokenPosition& end_pos = function.end_token_pos();
@@ -329,16 +331,18 @@
     }
   };
 
-  PcDescriptors::Iterator iter(
-      descriptors,
-      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall);
-  while (iter.MoveNext()) {
-    HANDLESCOPE(thread());
-    ASSERT(iter.DeoptId() < ic_data_array->length());
-    const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
-    if (!ShouldCoverageSkipCallSite(ic_data)) {
-      const TokenPosition& token_pos = iter.TokenPos();
-      update_coverage(token_pos, ic_data->AggregateCount() > 0);
+  if (!report_branch_coverage) {
+    PcDescriptors::Iterator iter(descriptors,
+                                 UntaggedPcDescriptors::kIcCall |
+                                     UntaggedPcDescriptors::kUnoptStaticCall);
+    while (iter.MoveNext()) {
+      HANDLESCOPE(thread());
+      ASSERT(iter.DeoptId() < ic_data_array->length());
+      const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
+      if (!ShouldCoverageSkipCallSite(ic_data)) {
+        const TokenPosition& token_pos = iter.TokenPos();
+        update_coverage(token_pos, ic_data->AggregateCount() > 0);
+      }
     }
   }
 
@@ -349,7 +353,7 @@
       bool is_branch_coverage;
       const TokenPosition token_pos = TokenPosition::DecodeCoveragePosition(
           Smi::Value(Smi::RawCast(coverage_array.At(i))), &is_branch_coverage);
-      if (!is_branch_coverage) {
+      if (is_branch_coverage == report_branch_coverage) {
         const bool was_executed =
             Smi::Value(Smi::RawCast(coverage_array.At(i + 1))) != 0;
         update_coverage(token_pos, was_executed);
@@ -357,7 +361,7 @@
     }
   }
 
-  JSONObject cov(jsobj, "coverage");
+  JSONObject cov(jsobj, report_branch_coverage ? "branchCoverage" : "coverage");
   {
     JSONArray hits(&cov, "hits");
     TokenPosition pos = begin_pos;
@@ -532,7 +536,10 @@
       PrintCallSitesData(&range, func, code);
     }
     if (IsReportRequested(kCoverage)) {
-      PrintCoverageData(&range, func, code);
+      PrintCoverageData(&range, func, code, /* report_branch_coverage */ false);
+    }
+    if (IsReportRequested(kBranchCoverage)) {
+      PrintCoverageData(&range, func, code, /* report_branch_coverage */ true);
     }
     if (IsReportRequested(kPossibleBreakpoints)) {
       PrintPossibleBreakpointsData(&range, func, code);
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 874f682..729008e 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -27,12 +27,14 @@
     kCoverage = 0x2,
     kPossibleBreakpoints = 0x4,
     kProfile = 0x8,
+    kBranchCoverage = 0x10,
   };
 
   static const char* kCallSitesStr;
   static const char* kCoverageStr;
   static const char* kPossibleBreakpointsStr;
   static const char* kProfileStr;
+  static const char* kBranchCoverageStr;
 
   enum CompileMode { kNoCompile, kForceCompile };
 
@@ -77,7 +79,8 @@
                           const Code& code);
   void PrintCoverageData(JSONObject* jsobj,
                          const Function& func,
-                         const Code& code);
+                         const Code& code,
+                         bool report_branch_coverage);
   void PrintPossibleBreakpointsData(JSONObject* jsobj,
                                     const Function& func,
                                     const Code& code);
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index 2670ac6..f749b28 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -541,7 +541,8 @@
       "\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
-      "\"tokenPos\":0,\"endTokenPos\":11}},\"count\":1}]}]}],"
+      "\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"
+      "]}]}],"
 
       // One script in the script table.
       "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
@@ -602,7 +603,8 @@
       "\"script\":{\"type\":\"@Script\","
       "\"fixedId\":true,\"id\":\"\","
       "\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27,\"line\":1,"
+      "\"column\":1},"
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}},"
 
@@ -614,7 +616,8 @@
       "\"script\":{\"type\":\"@Script\","
       "\"fixedId\":true,\"id\":\"\","
       "\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27,\"line\":1,"
+      "\"column\":1},"
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
@@ -624,7 +627,8 @@
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":17,\"endTokenPos\":25}},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":17,\"endTokenPos\":25,\"line\":2,"
+      "\"column\":3}},"
 
       "\"count\":2},"
 
@@ -635,7 +639,8 @@
       "\"script\":{\"type\":\"@Script\","
       "\"fixedId\":true,\"id\":\"\","
       "\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58,\"line\":4,"
+      "\"column\":1},"
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}},"
 
@@ -647,7 +652,8 @@
       "\"script\":{\"type\":\"@Script\","
       "\"fixedId\":true,\"id\":\"\","
       "\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58,\"line\":4,"
+      "\"column\":1},"
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
@@ -657,7 +663,8 @@
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
-      "\"_kind\":\"kernel\"},\"tokenPos\":48,\"endTokenPos\":56}},"
+      "\"_kind\":\"kernel\"},\"tokenPos\":48,\"endTokenPos\":56,\"line\":5,"
+      "\"column\":3}},"
 
       "\"count\":1}]}]}],"
 
@@ -713,7 +720,8 @@
       "intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
-      "\"tokenPos\":0,\"endTokenPos\":11}},\"count\":1}]}],\"coverage\":{"
+      "\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"
+      "]}],\"coverage\":{"
       "\"hits\":[26,37],\"misses\":[]}}],"
 
       // One script in the script table.
@@ -1119,6 +1127,251 @@
       buffer);
 }
 
+ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_if) {
+  // WARNING: This MUST be big enough for the serialised JSON string.
+  const int kBufferSize = 1024;
+  char buffer[kBufferSize];
+  const char* kScript = R"(
+int ifTest(int x) {
+  if (x > 0) {
+    if (x > 10) {
+      return 10;
+    } else {
+      return 1;
+    }
+  } else {
+    return 0;
+  }
+}
+
+main() {
+  ifTest(1);
+}
+)";
+
+  Library& lib = Library::Handle();
+  const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
+  IsolateGroup::Current()->set_branch_coverage(true);
+  lib ^= ExecuteScript(kScript);
+  IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
+  ASSERT(!lib.IsNull());
+  const Script& script =
+      Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kBranchCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  const char* json_str = js.ToCString();
+  ASSERT(strlen(json_str) < kBufferSize);
+  ElideJSONSubstring("classes", json_str, buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // In ifTest, the outer true case is hit, the inner true case is missed,
+      // the inner false case is hit, and the outer false case is missed.
+      "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":135,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[1,34,82],\"misses\":[52,115]}},"
+
+      // Main is hit.
+      "{\"scriptIndex\":0,\"startPos\":138,\"endPos\":160,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[138],\"misses\":[]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+      buffer);
+}
+
+ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_loops) {
+  // WARNING: This MUST be big enough for the serialised JSON string.
+  const int kBufferSize = 1024;
+  char buffer[kBufferSize];
+  const char* kScript = R"(
+int loopTest() {
+  var x = 0;
+
+  while (x < 10) {
+    ++x;
+  }
+
+  do {
+    ++x;
+  } while (false);
+
+  for (int i = 0; i < 10; ++i) {
+    ++x;
+  }
+
+  for (final i in [1, 2, 3]) {
+    ++x;
+  }
+
+  return x;
+}
+
+main() {
+  loopTest();
+}
+)";
+
+  Library& lib = Library::Handle();
+  const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
+  IsolateGroup::Current()->set_branch_coverage(true);
+  lib ^= ExecuteScript(kScript);
+  IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
+  ASSERT(!lib.IsNull());
+  const Script& script =
+      Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kBranchCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  const char* json_str = js.ToCString();
+  ASSERT(strlen(json_str) < kBufferSize);
+  ElideJSONSubstring("classes", json_str, buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // In loopTest, the while loop, do-while loop, for loop, and for-in loop
+      // are all hit.
+      "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":205,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[1,49,70,132,177],\"misses\":[]}},"
+
+      // Main is hit.
+      "{\"scriptIndex\":0,\"startPos\":208,\"endPos\":231,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[208],\"misses\":[]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+      buffer);
+}
+
+ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_switch) {
+  // WARNING: This MUST be big enough for the serialised JSON string.
+  const int kBufferSize = 1024;
+  char buffer[kBufferSize];
+  const char* kScript = R"(
+int switchTest(int x) {
+  switch (x) {
+    case 0:
+      return 10;
+    case 1:
+      return 20;
+    default:
+      return 30;
+  }
+}
+
+main() {
+  switchTest(1);
+}
+)";
+
+  Library& lib = Library::Handle();
+  const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
+  IsolateGroup::Current()->set_branch_coverage(true);
+  lib ^= ExecuteScript(kScript);
+  IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
+  ASSERT(!lib.IsNull());
+  const Script& script =
+      Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kBranchCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  const char* json_str = js.ToCString();
+  ASSERT(strlen(json_str) < kBufferSize);
+  ElideJSONSubstring("classes", json_str, buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // In switchTest, the 1 case is hit and the others are missed.
+      "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":132,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[1,73],\"misses\":[44,102]}},"
+
+      // Main is hit.
+      "{\"scriptIndex\":0,\"startPos\":135,\"endPos\":161,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[135],\"misses\":[]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+      buffer);
+}
+
+ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_try) {
+  // WARNING: This MUST be big enough for the serialised JSON string.
+  const int kBufferSize = 1024;
+  char buffer[kBufferSize];
+  const char* kScript = R"(
+void tryTestInner() {
+  try {
+    throw "abc";
+  } catch (e) {
+  } finally {
+  }
+
+  try {
+    throw "def";
+  } finally {
+  }
+}
+
+void tryTestOuter() {
+  try {
+    tryTestInner();
+  } catch (e) {
+  }
+}
+
+main() {
+  tryTestOuter();
+}
+)";
+
+  Library& lib = Library::Handle();
+  const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
+  IsolateGroup::Current()->set_branch_coverage(true);
+  lib ^= ExecuteScript(kScript);
+  IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
+  ASSERT(!lib.IsNull());
+  const Script& script =
+      Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kBranchCoverage);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  const char* json_str = js.ToCString();
+  ASSERT(strlen(json_str) < kBufferSize);
+  ElideJSONSubstring("classes", json_str, buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // In tryTestInner, the try/catch/finally and the try/finally are all hit,
+      // and the try/finally rethrows its exception.
+      "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":126,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[1,29,62,76,89,120],\"misses\":[]}},"
+
+      // In tryTestOuter, the exception thrown by tryTestInner causes both the
+      // try and the catch to be hit.
+      "{\"scriptIndex\":0,\"startPos\":129,\"endPos\":199,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[129,157,193],\"misses\":[]}},"
+
+      // Main is hit.
+      "{\"scriptIndex\":0,\"startPos\":202,\"endPos\":229,\"compiled\":true,"
+      "\"branchCoverage\":{\"hits\":[202],\"misses\":[]}}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+      buffer);
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index e23d93b..3574ec3 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -18,6 +18,8 @@
 #include "vm/stack_frame_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/stack_frame_arm64.h"
+#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#include "vm/stack_frame_riscv.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/stack_frame_riscv.h b/runtime/vm/stack_frame_riscv.h
new file mode 100644
index 0000000..4bf58ab
--- /dev/null
+++ b/runtime/vm/stack_frame_riscv.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_STACK_FRAME_RISCV_H_
+#define RUNTIME_VM_STACK_FRAME_RISCV_H_
+
+#if !defined(RUNTIME_VM_STACK_FRAME_H_)
+#error Do not include stack_frame_riscv.h directly; use stack_frame.h instead.
+#endif
+
+namespace dart {
+
+/* RISC-V Dart Frame Layout
+               |                    | <- TOS
+Callee frame   | ...                |
+               | saved PP           |
+               | code object        |
+               | saved FP           |    (FP of current frame)
+               | saved PC           |    (PC of current frame)
+               +--------------------+
+Current frame  | ...               T| <- SP of current frame
+               | first local       T|
+               | caller's PP       T|
+               | code object       T|    (current frame's code object)
+               | caller's FP        | <- FP of current frame
+               | caller's RA        |    (PC of caller frame)
+               +--------------------+
+Caller frame   | last parameter     | <- SP of caller frame
+               |  ...               |
+
+               T against a slot indicates it needs to be traversed during GC.
+*/
+
+static const int kDartFrameFixedSize = 4;  // PP, FP, RA, PC marker.
+static const int kSavedPcSlotFromSp = -1;
+
+static const int kFirstObjectSlotFromFp = -1;  // Used by GC to traverse stack.
+static const int kLastFixedObjectSlotFromFp = -2;
+
+static const int kFirstLocalSlotFromFp = -3;
+static const int kSavedCallerPpSlotFromFp = -2;
+static const int kPcMarkerSlotFromFp = -1;
+static const int kSavedCallerFpSlotFromFp = 0;
+static const int kSavedCallerPcSlotFromFp = 1;
+
+static const int kParamEndSlotFromFp = 1;  // One slot past last parameter.
+static const int kCallerSpSlotFromFp = 2;
+static const int kLastParamSlotFromEntrySp = 0;
+
+// Entry and exit frame layout.
+#if defined(TARGET_ARCH_RISCV64)
+static const int kExitLinkSlotFromEntryFp = -28;
+#elif defined(TARGET_ARCH_RISCV32)
+static const int kExitLinkSlotFromEntryFp = -40;
+#endif
+COMPILE_ASSERT(kAbiPreservedCpuRegCount == 11);
+COMPILE_ASSERT(kAbiPreservedFpuRegCount == 12);
+
+// For FFI native -> Dart callbacks, this is the number of stack slots between
+// arguments passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+//
+// If NativeCallbackTrampolines::Enabled(), then
+// kNativeCallbackTrampolineStackDelta must be added as well.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
+// For FFI calls passing in TypedData, we save it on the stack before entering
+// a Dart frame. This denotes how to get to the backed up typed data.
+static const int kFfiCallerTypedDataSlotFromFp = kCallerSpSlotFromFp;
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_STACK_FRAME_RISCV_H_
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 1f29e90..583e055 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -395,6 +395,10 @@
   if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
     // Next, look up caller's closure on the stack and walk backwards
     // through the yields.
+    //
+    // Due the async/async* closures having optional parameters, the
+    // caller-frame's pushed arguments includes the closure and should never be
+    // modified (even in the event of deopts).
     ObjectPtr* last_caller_obj =
         reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
     closure = FindClosureInFrame(last_caller_obj, function);
@@ -432,6 +436,12 @@
     Object& receiver =
         Object::Handle(*(reinterpret_cast<ObjectPtr*>(frame->GetCallerSp()) +
                          kNumArgsFutureListenerHandleValue));
+    if (receiver.ptr() == Symbols::OptimizedOut().ptr()) {
+      // In the very rare case that _FutureListener.handleValue has deoptimized
+      // it may override the receiver slot in the caller frame with "<optimized
+      // out>" due to the `this` no longer being needed.
+      return Closure::null();
+    }
 
     return caller_closure_finder->GetCallerInFutureListener(receiver);
   }
@@ -579,6 +589,9 @@
         function.parent_function() != Function::null()) {
       if (async_function.ptr() == function.parent_function()) {
         if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+          // Due the async/async* closures having optional parameters, the
+          // caller-frame's pushed arguments includes the closure and should
+          // never be modified (even in the event of deopts).
           ObjectPtr* last_caller_obj =
               reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
           closure = FindClosureInFrame(last_caller_obj, function);
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index fa7b06b..778e08c 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -125,6 +125,7 @@
   V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)                         \
   V(EnterSafepoint)                                                            \
   V(ExitSafepoint)                                                             \
+  V(ExitSafepointIgnoreUnwindInProgress)                                       \
   V(CallNativeThroughSafepoint)                                                \
   V(InitStaticField)                                                           \
   V(InitLateStaticField)                                                       \
diff --git a/runtime/vm/stub_code_riscv_test.cc b/runtime/vm/stub_code_riscv_test.cc
new file mode 100644
index 0000000..df605de
--- /dev/null
+++ b/runtime/vm/stub_code_riscv_test.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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_RISCV32) || defined(TARGET_ARCH_RISCV64)
+
+#include "vm/dart_entry.h"
+#include "vm/isolate.h"
+#include "vm/native_entry.h"
+#include "vm/native_entry_test.h"
+#include "vm/object.h"
+#include "vm/runtime_entry.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+#include "vm/unit_test.h"
+
+#define __ assembler->
+
+namespace dart {
+
+static Function* CreateFunction(const char* name) {
+  const String& class_name =
+      String::Handle(Symbols::New(Thread::Current(), "ownerClass"));
+  const Script& script = Script::Handle();
+  const Library& lib = Library::Handle(Library::New(class_name));
+  const Class& owner_class = Class::Handle(
+      Class::New(lib, class_name, script, TokenPosition::kNoSource));
+  const String& function_name =
+      String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  Function& function = Function::ZoneHandle(Function::New(
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
+  return &function;
+}
+
+// Test calls to stub code which calls into the runtime.
+static void GenerateCallToCallRuntimeStub(compiler::Assembler* assembler,
+                                          int length) {
+  const int argc = 2;
+  const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
+  __ EnterDartFrame(0);
+  __ PushObject(Object::null_object());  // Push Null obj for return value.
+  __ PushObject(smi_length);             // Push argument 1: length.
+  __ PushObject(Object::null_object());  // Push argument 2: type arguments.
+  ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+  __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
+  __ addi(SP, SP, argc * kWordSize);
+  __ PopRegister(A0);  // Pop return value from return slot.
+  __ LeaveDartFrame();
+  __ ret();
+}
+
+ISOLATE_UNIT_TEST_CASE(CallRuntimeStubCode) {
+  extern const Function& RegisterFakeFunction(const char* name,
+                                              const Code& code);
+  const int length = 10;
+  const char* kName = "Test_CallRuntimeStubCode";
+  compiler::ObjectPoolBuilder object_pool_builder;
+  compiler::Assembler assembler(&object_pool_builder);
+  GenerateCallToCallRuntimeStub(&assembler, length);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
+      *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
+  const Function& function = RegisterFakeFunction(kName, code);
+  Array& result = Array::Handle();
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
+  EXPECT_EQ(length, result.Length());
+}
+
+// Test calls to stub code which calls into a leaf runtime entry.
+static void GenerateCallToCallLeafRuntimeStub(compiler::Assembler* assembler,
+                                              const char* str_value,
+                                              intptr_t lhs_index_value,
+                                              intptr_t rhs_index_value,
+                                              intptr_t length_value) {
+  const String& str = String::ZoneHandle(String::New(str_value, Heap::kOld));
+  const Smi& lhs_index = Smi::ZoneHandle(Smi::New(lhs_index_value));
+  const Smi& rhs_index = Smi::ZoneHandle(Smi::New(rhs_index_value));
+  const Smi& length = Smi::ZoneHandle(Smi::New(length_value));
+  __ EnterDartFrame(0);
+  __ ReserveAlignedFrameSpace(0);
+  __ LoadObject(A0, str);
+  __ LoadObject(A1, lhs_index);
+  __ LoadObject(A2, rhs_index);
+  __ LoadObject(A3, length);
+  __ CallRuntime(kCaseInsensitiveCompareUCS2RuntimeEntry, 4);
+  __ LeaveDartFrame();
+  __ ret();  // Return value is in A0.
+}
+
+ISOLATE_UNIT_TEST_CASE(CallLeafRuntimeStubCode) {
+  extern const Function& RegisterFakeFunction(const char* name,
+                                              const Code& code);
+  const char* str_value = "abAB";
+  intptr_t lhs_index_value = 0;
+  intptr_t rhs_index_value = 2;
+  intptr_t length_value = 2;
+  const char* kName = "Test_CallLeafRuntimeStubCode";
+  compiler::ObjectPoolBuilder object_pool_builder;
+  compiler::Assembler assembler(&object_pool_builder);
+  GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
+                                    rhs_index_value, length_value);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
+      *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
+      Code::PoolAttachment::kAttachPool));
+  const Function& function = RegisterFakeFunction(kName, code);
+  Instance& result = Instance::Handle();
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
+  EXPECT_EQ(Bool::True().ptr(), result.ptr());
+}
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_RISCV
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 75bb968..5c8db08 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -293,6 +293,7 @@
   V(_DeletedEnumPrefix, "Deleted enum value from ")                            \
   V(_DeletedEnumSentinel, "_deleted_enum_sentinel")                            \
   V(_Double, "_Double")                                                        \
+  V(_Enum, "_Enum")                                                            \
   V(_ExternalFloat32Array, "_ExternalFloat32Array")                            \
   V(_ExternalFloat32x4Array, "_ExternalFloat32x4Array")                        \
   V(_ExternalFloat64Array, "_ExternalFloat64Array")                            \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 6efc403..584cb9c 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -118,8 +118,7 @@
   CACHED_CONSTANTS_LIST(DEFAULT_INIT)
 #undef DEFAULT_INIT
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
+#if !defined(TARGET_ARCH_IA32)
   for (intptr_t i = 0; i < kNumberOfDartAvailableCpuRegs; ++i) {
     write_barrier_wrappers_entry_points_[i] = 0;
   }
@@ -194,8 +193,7 @@
   CACHED_CONSTANTS_LIST(INIT_VALUE)
 #undef INIT_VALUE
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
+#if !defined(TARGET_ARCH_IA32)
   for (intptr_t i = 0; i < kNumberOfDartAvailableCpuRegs; ++i) {
     write_barrier_wrappers_entry_points_[i] =
         StubCode::WriteBarrierWrappers().EntryPoint() +
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index ed9e9b7..8c352db 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -151,6 +151,8 @@
     StubCode::LazySpecializeTypeTest().ptr(), nullptr)                         \
   V(CodePtr, enter_safepoint_stub_, StubCode::EnterSafepoint().ptr(), nullptr) \
   V(CodePtr, exit_safepoint_stub_, StubCode::ExitSafepoint().ptr(), nullptr)   \
+  V(CodePtr, exit_safepoint_ignore_unwind_in_progress_stub_,                   \
+    StubCode::ExitSafepointIgnoreUnwindInProgress().ptr(), nullptr)            \
   V(CodePtr, call_native_through_safepoint_stub_,                              \
     StubCode::CallNativeThroughSafepoint().ptr(), nullptr)
 
@@ -565,7 +567,10 @@
 
   bool is_unwind_in_progress() const { return is_unwind_in_progress_; }
 
-  void StartUnwindError() { is_unwind_in_progress_ = true; }
+  void StartUnwindError() {
+    is_unwind_in_progress_ = true;
+    SetUnwindErrorInProgress(true);
+  }
 
 #if defined(DEBUG)
   void EnterCompiler() {
@@ -654,8 +659,7 @@
   CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
 #undef DEFINE_OFFSET_METHOD
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
+#if !defined(TARGET_ARCH_IA32)
   static intptr_t write_barrier_wrappers_thread_offset(Register reg) {
     ASSERT((kDartAvailableCpuRegs & (1 << reg)) != 0);
     intptr_t index = 0;
@@ -813,6 +817,9 @@
    * - Bit 4 of the safepoint_state_ field is used to indicate that the thread
    *   is blocked at a (deopt)safepoint and has to be woken up once the
    *   (deopt)safepoint operation is complete.
+   * - Bit 6 of the safepoint_state_ field is used to indicate that the isolate
+   *   running on this thread has triggered unwind error, which requires
+   *   enforced exit on a transition from native back to generated.
    *
    * The safepoint execution state (described above) for a thread is stored in
    * in the execution_state_ field.
@@ -903,6 +910,19 @@
   static uword SetBypassSafepoints(bool value, uword state) {
     return BypassSafepointsField::update(value, state);
   }
+  bool UnwindErrorInProgress() const {
+    return UnwindErrorInProgressField::decode(safepoint_state_);
+  }
+  void SetUnwindErrorInProgress(bool value) {
+    const uword mask = UnwindErrorInProgressField::mask_in_place();
+    if (value) {
+      safepoint_state_.fetch_or(mask);
+    } else {
+      safepoint_state_.fetch_and(~mask);
+    }
+  }
+
+  uword safepoint_state() { return safepoint_state_; }
 
   enum ExecutionState {
     kThreadInVM = 0,
@@ -1120,8 +1140,7 @@
   LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
 #undef DECLARE_MEMBERS
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
-    defined(TARGET_ARCH_X64)
+#if !defined(TARGET_ARCH_IA32)
   uword write_barrier_wrappers_entry_points_[kNumberOfDartAvailableCpuRegs];
 #endif
 
@@ -1210,6 +1229,8 @@
                         1> {};
   class BypassSafepointsField
       : public BitField<uword, bool, BlockedForSafepointField::kNextBit, 1> {};
+  class UnwindErrorInProgressField
+      : public BitField<uword, bool, BypassSafepointsField::kNextBit, 1> {};
 
   static uword AtSafepointBits(SafepointLevel level) {
     switch (level) {
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index f450555..ac6adfc 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -317,6 +317,13 @@
 }
 
 void ThreadPool::Worker::Main(uword args) {
+  // Call the thread start hook here to notify the embedder that the
+  // thread pool thread has started.
+  Dart_ThreadStartCallback start_cb = Dart::thread_start_callback();
+  if (start_cb != nullptr) {
+    start_cb();
+  }
+
   OSThread* os_thread = OSThread::Current();
   ASSERT(os_thread != nullptr);
 
@@ -343,8 +350,9 @@
 
   // Call the thread exit hook here to notify the embedder that the
   // thread pool thread is exiting.
-  if (Dart::thread_exit_callback() != NULL) {
-    (*Dart::thread_exit_callback())();
+  Dart_ThreadExitCallback exit_cb = Dart::thread_exit_callback();
+  if (exit_cb != nullptr) {
+    exit_cb();
   }
 }
 
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 785e536..c4dc3d3 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -206,28 +206,22 @@
 #if !defined(TARGET_ARCH_IA32)
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
-#define ONLY_ON_ARM(...) __VA_ARGS__
-#else
-#define ONLY_ON_ARM(...)
-#endif
-
 static CodePtr RetryCompilationWithFarBranches(
     Thread* thread,
     std::function<CodePtr(compiler::Assembler&)> fun) {
-  volatile bool use_far_branches = false;
+  volatile intptr_t far_branch_level = 0;
   while (true) {
     LongJumpScope jump;
     if (setjmp(*jump.Set()) == 0) {
       // To use the already-defined __ Macro !
-      compiler::Assembler assembler(nullptr ONLY_ON_ARM(, use_far_branches));
+      compiler::Assembler assembler(nullptr, far_branch_level);
       return fun(assembler);
     } else {
       // We bailed out or we encountered an error.
       const Error& error = Error::Handle(thread->StealStickyError());
       if (error.ptr() == Object::branch_offset_error().ptr()) {
-        ASSERT(!use_far_branches);
-        use_far_branches = true;
+        ASSERT(far_branch_level < 2);
+        far_branch_level++;
       } else if (error.ptr() == Object::out_of_memory_error().ptr()) {
         thread->set_sticky_error(error);
         return Code::null();
@@ -238,8 +232,6 @@
   }
 }
 
-#undef ONLY_ON_ARM
-
 CodePtr TypeTestingStubGenerator::BuildCodeForType(const Type& type) {
   auto thread = Thread::Current();
   auto zone = thread->zone();
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 7f04842..3c68eb8 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -15,8 +15,7 @@
 #include "vm/type_testing_stubs.h"
 #include "vm/unit_test.h"
 
-#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) ||                  \
-    defined(TARGET_ARCH_X64)
+#if !defined(TARGET_ARCH_IA32)
 
 namespace dart {
 
@@ -2267,5 +2266,4 @@
 
 }  // namespace dart
 
-#endif  // defined(TARGET_ARCH_ARM64) ||  defined(TARGET_ARCH_ARM) ||          \
-        // defined(TARGET_ARCH_X64)
+#endif  // !defined(TARGET_ARCH_IA32)
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index a2478ad..5242592 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -667,7 +667,7 @@
   return Api::NewHandle(thread, val.ptr());
 }
 
-#if !defined(PRODUCT) && defined(TARGET_ARCH_IA32)
+#if !defined(PRODUCT) && (defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64))
 static bool IsHex(int c) {
   return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f');
 }
@@ -705,9 +705,11 @@
   }
   Disassembler::Disassemble(start, start + assembler_->CodeSize(), disassembly_,
                             DISASSEMBLY_SIZE);
-#if defined(TARGET_ARCH_IA32)
-  // Blank out absolute addressing constants, since they are not stable from run
-  // to run.
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+  // Blank out absolute addressing constants on ia32, since they are not stable
+  // from run to run.
+  // Blank out thread-relative offsets on x64 since they change when new fields
+  // are added to thread object.
   bool in_hex_constant = false;
   for (char* p = disassembly_; *p != '\0'; p++) {
     if (in_hex_constant) {
@@ -717,14 +719,24 @@
         in_hex_constant = false;
       }
     } else {
+#if defined(TARGET_ARCH_IA32)
       if (*p == '[' && *(p + 1) == '0' && *(p + 2) == 'x' && IsHex(*(p + 3)) &&
           IsHex(*(p + 4))) {
         p += 2;
         in_hex_constant = true;
       }
+#endif  // defined(TARGET_ARCH_IA32)
+#if defined(TARGET_ARCH_X64)
+      if (*p == '[' && *(p + 1) == 't' && *(p + 2) == 'h' && *(p + 3) == 'r' &&
+          *(p + 4) == '+' && *(p + 5) == '0' && *(p + 6) == 'x' &&
+          IsHex(*(p + 7)) && IsHex(*(p + 8))) {
+        p += 6;
+        in_hex_constant = true;
+      }
+#endif  // defined(TARGET_ARCH_X64)
     }
   }
-#endif  // TARGET_ARCH_IA32
+#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
 #endif  // !PRODUCT
 }
 
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index bc86b9e..42102af 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -101,40 +101,37 @@
 #define ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, expectation)           \
   static void AssemblerTestRun##name(AssemblerTest* test);                     \
   ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) {                 \
-    {                                                                          \
-      bool use_far_branches = false;                                           \
+    volatile intptr_t far_branch_level = 0;                                    \
+    while (true) {                                                             \
       LongJumpScope jump;                                                      \
       if (setjmp(*jump.Set()) == 0) {                                          \
         compiler::ObjectPoolBuilder object_pool_builder;                       \
-        compiler::Assembler assembler(&object_pool_builder, use_far_branches); \
+        compiler::Assembler assembler(&object_pool_builder, far_branch_level); \
         AssemblerTest test("" #name, &assembler);                              \
         AssemblerTestGenerate##name(test.assembler());                         \
         test.Assemble();                                                       \
         AssemblerTestRun##name(&test);                                         \
         return;                                                                \
+      } else {                                                                 \
+        const Error& error = Error::Handle(Thread::Current()->sticky_error()); \
+        if (error.ptr() == Object::branch_offset_error().ptr()) {              \
+          ASSERT(far_branch_level < 2);                                        \
+          far_branch_level++;                                                  \
+        } else {                                                               \
+          FATAL1("Unexpected error: %s\n", error.ToErrorCString());            \
+        }                                                                      \
       }                                                                        \
     }                                                                          \
-                                                                               \
-    const Error& error = Error::Handle(Thread::Current()->sticky_error());     \
-    if (error.ptr() == Object::branch_offset_error().ptr()) {                  \
-      bool use_far_branches = true;                                            \
-      compiler::ObjectPoolBuilder object_pool_builder;                         \
-      compiler::Assembler assembler(&object_pool_builder, use_far_branches);   \
-      AssemblerTest test("" #name, &assembler);                                \
-      AssemblerTestGenerate##name(test.assembler());                           \
-      test.Assemble();                                                         \
-      AssemblerTestRun##name(&test);                                           \
-    } else {                                                                   \
-      FATAL1("Unexpected error: %s\n", error.ToErrorCString());                \
-    }                                                                          \
   }                                                                            \
   static void AssemblerTestRun##name(AssemblerTest* test)
 
 #define ASSEMBLER_TEST_RUN(name, test)                                         \
   ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, "Pass")
 
-#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
-#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
+    defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) ||                      \
+    defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
 // Running on actual ARM hardware, execute code natively.
 #define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
 #define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)()
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index 8596e4a..ef8274c 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -57,6 +57,10 @@
     "arm"
 #elif defined(TARGET_ARCH_ARM64)
     "arm64"
+#elif defined(TARGET_ARCH_RISCV32)
+    "riscv32"
+#elif defined(TARGET_ARCH_RISCV64)
+    "riscv64"
 #else
 #error Unknown arch
 #endif
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index f17cc64..059703c 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -44,6 +44,7 @@
   "code_patcher_arm.cc",
   "code_patcher_arm64.cc",
   "code_patcher_ia32.cc",
+  "code_patcher_riscv.cc",
   "code_patcher_x64.cc",
   "constants_arm.cc",
   "constants_arm.h",
@@ -52,12 +53,15 @@
   "constants_base.h",
   "constants_ia32.cc",
   "constants_ia32.h",
+  "constants_riscv.cc",
+  "constants_riscv.h",
   "constants_x64.cc",
   "constants_x64.h",
   "cpu.h",
   "cpu_arm.cc",
   "cpu_arm64.cc",
   "cpu_ia32.cc",
+  "cpu_riscv.cc",
   "cpu_x64.cc",
   "cpuid.cc",
   "cpuid.h",
@@ -82,6 +86,7 @@
   "debugger_arm.cc",
   "debugger_arm64.cc",
   "debugger_ia32.cc",
+  "debugger_riscv.cc",
   "debugger_x64.cc",
   "deferred_objects.cc",
   "deferred_objects.h",
@@ -128,6 +133,8 @@
   "instructions_arm64.h",
   "instructions_ia32.cc",
   "instructions_ia32.h",
+  "instructions_riscv.cc",
+  "instructions_riscv.h",
   "instructions_x64.cc",
   "instructions_x64.h",
   "intrusive_dlist.h",
@@ -266,6 +273,7 @@
   "runtime_entry_arm64.cc",
   "runtime_entry_ia32.cc",
   "runtime_entry_list.h",
+  "runtime_entry_riscv.cc",
   "runtime_entry_x64.cc",
   "scope_timer.h",
   "scopes.cc",
@@ -287,6 +295,8 @@
   "simulator_arm.h",
   "simulator_arm64.cc",
   "simulator_arm64.h",
+  "simulator_riscv.cc",
+  "simulator_riscv.h",
   "snapshot.cc",
   "snapshot.h",
   "source_report.cc",
@@ -381,6 +391,7 @@
   "code_patcher_arm64_test.cc",
   "code_patcher_arm_test.cc",
   "code_patcher_ia32_test.cc",
+  "code_patcher_riscv_test.cc",
   "code_patcher_x64_test.cc",
   "compiler_test.cc",
   "cpu_test.cc",
@@ -400,6 +411,7 @@
   "instructions_arm64_test.cc",
   "instructions_arm_test.cc",
   "instructions_ia32_test.cc",
+  "instructions_riscv_test.cc",
   "instructions_x64_test.cc",
   "intrusive_dlist_test.cc",
   "isolate_reload_test.cc",
@@ -420,6 +432,7 @@
   "object_graph_test.cc",
   "object_ia32_test.cc",
   "object_id_ring_test.cc",
+  "object_riscv_test.cc",
   "object_store_test.cc",
   "object_test.cc",
   "object_x64_test.cc",
@@ -433,11 +446,12 @@
   "snapshot_test.cc",
   "source_report_test.cc",
   "stack_frame_test.cc",
-  "stub_code_test.cc",
   "stub_code_arm64_test.cc",
   "stub_code_arm_test.cc",
   "stub_code_ia32_test.cc",
+  "stub_code_test.cc",
   "stub_code_x64_test.cc",
+  "stub_code_riscv_test.cc",
   "thread_barrier_test.cc",
   "thread_pool_test.cc",
   "thread_test.cc",
@@ -460,6 +474,8 @@
   "constants_base.h",
   "constants_ia32.cc",
   "constants_ia32.h",
+  "constants_riscv.cc",
+  "constants_riscv.h",
   "constants_x64.cc",
   "constants_x64.h",
 ]
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 2b4fa76..867dd32 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -35,7 +35,6 @@
 # ......dart or dart.exe (executable)
 # ......dart.lib (import library for VM native extensions on Windows)
 # ......dartaotruntime or dartaotruntime.exe (executable)
-# ......dartdoc
 # ......dart2js
 # ......dartanalyzer
 # ......dartdevc
@@ -48,7 +47,6 @@
 # ........dartdev.dart.snapshot
 # ........dartdev.dill
 # ........dartdevc.dart.snapshot
-# ........dartdoc.dart.snapshot
 # ........dds.dart.snapshot
 # ........frontend_server.dart.snapshot
 # ........gen_kernel.dart.snapshot (if not on ia32)
@@ -102,9 +100,6 @@
   "pub",
 ]
 
-# Scripts not ending in _sdk that go under bin/
-_scripts = [ "dartdoc" ]
-
 # Snapshots that go under bin/snapshots
 _platform_sdk_snapshots = [
   [
@@ -120,10 +115,6 @@
     "../utils/dartdev:dartdev",
   ],
   [
-    "dartdoc",
-    "../utils/dartdoc",
-  ],
-  [
     "dds",
     "../utils/dds:dds",
   ],
@@ -381,21 +372,6 @@
   }
 }
 
-foreach(script, _scripts) {
-  copy("copy_${script}_script") {
-    visibility = [
-      ":copy_full_sdk_scripts",
-      ":copy_platform_sdk_scripts",
-    ]
-    ext = ""
-    if (is_win) {
-      ext = ".bat"
-    }
-    sources = [ "bin/$script$ext" ]
-    outputs = [ "$root_out_dir/$dart_sdk_output/bin/{{source_file_part}}" ]
-  }
-}
-
 # This is the main target for copying scripts in _platform_sdk_scripts to bin/
 group("copy_platform_sdk_scripts") {
   visibility = [ ":_create_platform_sdk" ]
@@ -403,9 +379,6 @@
   foreach(sdk_script, _platform_sdk_scripts) {
     public_deps += [ ":copy_${sdk_script}_script" ]
   }
-  foreach(script, _scripts) {
-    public_deps += [ ":copy_${script}_script" ]
-  }
 }
 
 # This is the main target for copying scripts in _full_sdk_scripts to bin/
@@ -415,9 +388,6 @@
   foreach(sdk_script, _full_sdk_scripts) {
     public_deps += [ ":copy_${sdk_script}_script" ]
   }
-  foreach(script, _scripts) {
-    public_deps += [ ":copy_${script}_script" ]
-  }
 }
 
 # This loop generates "copy" targets that put snapshots into bin/snapshots
@@ -461,10 +431,6 @@
   }
 }
 
-# This rule writes the .packages file for dartdoc resources.
-write_file("$root_out_dir/$dart_sdk_output/bin/resources/dartdoc/.packages",
-           "dartdoc:.")
-
 # This is the main rule for copying the files that dartdoc needs.
 group("copy_dartdoc_files") {
   visibility = [ ":create_common_sdk" ]
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index cfc91b1..750f20d 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -25,6 +25,7 @@
 unset EXTRA_OPTIONS
 declare -a EXTRA_OPTIONS
 
+EXTRA_OPTIONS+=('--invoker=development_script')
 if test -t 1; then
   # Stdout is a terminal.
   if test 8 -le `tput colors`; then
diff --git a/sdk/bin/dartanalyzer_developer b/sdk/bin/dartanalyzer_developer
deleted file mode 100755
index 373dc67..0000000
--- a/sdk/bin/dartanalyzer_developer
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-. ${BASH_SOURCE%_developer}
diff --git a/sdk/bin/dartanalyzer_developer.bat b/sdk/bin/dartanalyzer_developer.bat
deleted file mode 100644
index b560fe8..0000000
--- a/sdk/bin/dartanalyzer_developer.bat
+++ /dev/null
@@ -1,10 +0,0 @@
-@echo off
-REM Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-REM for details. All rights reserved. Use of this source code is governed by a
-REM BSD-style license that can be found in the LICENSE file.
-
-setlocal
-set DARTANALYZER_DEVELOPER_MODE=1
-call "%~dp0dartanalyzer.bat" %*
-endlocal
-exit /b %errorlevel%
diff --git a/sdk/bin/dartdevc b/sdk/bin/dartdevc
deleted file mode 100755
index c2c25d9..0000000
--- a/sdk/bin/dartdevc
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# Run dev compiler on the Dart VM. This script assumes the Dart repo's
-# directory structure.
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    # On Mac OS, readlink -f doesn't work.
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
-
-SDK_ARG="--dart-sdk=$SDK_DIR"
-
-DART="$BIN_DIR/dart"
-
-unset EXTRA_VM_OPTIONS
-declare -a EXTRA_VM_OPTIONS
-
-case $0 in
-  *_developer)
-    EXTRA_VM_OPTIONS+=('--checked')
-    ;;
-esac
-
-# We allow extra vm options to be passed in through an environment variable.
-if [[ $DART_VM_OPTIONS ]]; then
-  read -a OPTIONS <<< "$DART_VM_OPTIONS"
-  EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
-fi
-
-DART_ROOT="$(cd "${SDK_DIR}/.." ; pwd -P)"
-
-DEV_COMPILER="$DART_ROOT/pkg/dev_compiler/bin/dartdevc.dart"
-
-exec "$DART" "--packages=$DART_ROOT/.packages" --enable_experiment=non-nullable "${EXTRA_VM_OPTIONS[@]}" "$DEV_COMPILER" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc.bat b/sdk/bin/dartdevc.bat
deleted file mode 100644
index 6091a3a..0000000
--- a/sdk/bin/dartdevc.bat
+++ /dev/null
@@ -1,66 +0,0 @@
-@echo off
-REM Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-REM for details. All rights reserved. Use of this source code is governed by a
-REM BSD-style license that can be found in the LICENSE file.
-
-setlocal
-rem Handle the case where dart-sdk/bin has been symlinked to.
-set DIR_NAME_WITH_SLASH=%~dp0
-set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
-call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
-rem Get rid of surrounding quotes.
-for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
-
-set DART=%BIN_DIR%\dart
-
-rem Get absolute full name for SDK_DIR.
-for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
-
-rem Remove trailing backslash if there is one
-if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
-
-set SDK_ARG=--dart-sdk=%SDK_DIR%
-
-set EXTRA_VM_OPTIONS=
-
-rem We allow extra vm options to be passed in through an environment variable.
-if not "_%DART_VM_OPTIONS%_" == "__" (
-  set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
-)
-
-rem Get absolute full name for DART_ROOT.
-for %%i in ("%SDK_DIR%\..\") do set DART_ROOT=%%~fi
-
-rem Remove trailing backslash if there is one
-if %DART_ROOT:~-1%==\ set DART_ROOT=%DART_ROOT:~0,-1%
-
-set DEV_COMPILER=%DART_ROOT%\third_party\pkg\dev_compiler\bin\dartdevc.dart
-
-"%DART%" "--packages=%DART_ROOT%\.packages" %EXTRA_VM_OPTIONS% "DEV_COMPILER%" "%SDK_ARG%" %*
-
-endlocal
-
-exit /b %errorlevel%
-
-rem Follow the symbolic links (junctions points) using `dir to determine the
-rem canonical path. Output with a link looks something like this
-rem
-rem 01/03/2013  10:11 PM    <JUNCTION>     abc def
-rem [c:\dart_bleeding\dart-repo.9\dart\out\ReleaseIA32\dart-sdk]
-rem
-rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
-rem surrounded by right angle bracket and left square bracket. Once we get
-rem the filename, which is name of the link, we recursively follow that.
-:follow_links
-setlocal
-for %%i in (%1) do set result=%%~fi
-set current=
-for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
-  set current=%%i
-)
-if not "%current%"=="" call :follow_links "%current%", result
-endlocal & set %~2=%result%
-goto :eof
-
-:end
diff --git a/sdk/bin/dartdevc_sdk b/sdk/bin/dartdevc_sdk
index c687bdd..ba71205 100755
--- a/sdk/bin/dartdevc_sdk
+++ b/sdk/bin/dartdevc_sdk
@@ -6,6 +6,9 @@
 # Run dev compiler on the Dart VM. This script assumes the Dart SDK's
 # directory structure.
 
+echo "Warning: this 'dartdevc' script is deprecated and will be removed. " 1>&2
+echo "More details at https://github.com/dart-lang/sdk/issues/46100." 1>&2
+
 function follow_links() {
   file="$1"
   while [ -h "$file" ]; do
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
index 74b4c18..931e410 100644
--- a/sdk/bin/dartdevc_sdk.bat
+++ b/sdk/bin/dartdevc_sdk.bat
@@ -3,6 +3,9 @@
 REM for details. All rights reserved. Use of this source code is governed by a
 REM BSD-style license that can be found in the LICENSE file.
 
+echo Warning: this 'dartdevc' script is deprecated and will be removed.  1>&2
+echo More details at https://github.com/dart-lang/sdk/issues/46100.      1>&2
+
 setlocal
 rem Handle the case where dart-sdk/bin has been symlinked to.
 set DIR_NAME_WITH_SLASH=%~dp0
diff --git a/sdk/bin/dartdoc b/sdk/bin/dartdoc
deleted file mode 100755
index b7817c8..0000000
--- a/sdk/bin/dartdoc
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-echo "Warning: 'dartdoc' is deprecated. Please use 'dart doc'." 1>&2
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    # On Mac OS, readlink -f doesn't work.
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
-
-SNAPSHOT="$BIN_DIR/snapshots/dartdoc.dart.snapshot"
-
-# We are running the snapshot in the built SDK.
-DART="$BIN_DIR/dart"
-exec "$DART" "--packages=$BIN_DIR/resources/dartdoc/.packages" "$SNAPSHOT" "--resources-dir=$BIN_DIR/resources/dartdoc/resources/" "$@"
diff --git a/sdk/bin/dartdoc.bat b/sdk/bin/dartdoc.bat
deleted file mode 100644
index ea32a87..0000000
--- a/sdk/bin/dartdoc.bat
+++ /dev/null
@@ -1,46 +0,0 @@
-@echo off
-REM Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-REM for details. All rights reserved. Use of this source code is governed by a
-REM BSD-style license that can be found in the LICENSE file.
-
-echo Warning: 'dartdoc' is deprecated. Please use 'dart doc'. 1>&2
-
-setlocal
-rem Handle the case where dart-sdk/bin has been symlinked to.
-set DIR_NAME_WITH_SLASH=%~dp0
-set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
-call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
-rem Get rid of surrounding quotes.
-for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
-
-set DART=%BIN_DIR%\dart
-set SNAPSHOT=%BIN_DIR%\snapshots\dartdoc.dart.snapshot
-
-"%DART%" "--packages=%BIN_DIR%/resources/dartdoc/.packages" "%SNAPSHOT%" %*
-
-endlocal
-
-exit /b %errorlevel%
-
-rem Follow the symbolic links (junctions points) using `dir to determine the
-rem canonical path. Output with a link looks something like this
-rem
-rem 01/03/2013  10:11 PM    <JUNCTION>     abc def
-rem [c:\dart_bleeding\dart-repo.9\dart\out\ReleaseIA32\dart-sdk]
-rem
-rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
-rem surrounded by right angle bracket and left square bracket. Once we get
-rem the filename, which is name of the link, we recursively follow that.
-:follow_links
-setlocal
-for %%i in (%1) do set result=%%~fi
-set current=
-for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 [" 2^>nul`) do (
-  set current=%%i
-)
-if not "%current%"=="" call :follow_links "%current%", result
-endlocal & set %~2=%result%
-goto :eof
-
-:end
diff --git a/sdk/lib/PRESUBMIT.py b/sdk/lib/PRESUBMIT.py
new file mode 100644
index 0000000..21b779b
--- /dev/null
+++ b/sdk/lib/PRESUBMIT.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+"""sdk/lib specific presubmit script.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+import imp
+import os.path
+import subprocess
+
+USE_PYTHON3 = True
+
+
+def runSmokeTest(input_api, output_api):
+    hasChangedFiles = False
+    for git_file in input_api.AffectedTextFiles():
+        filename = git_file.AbsoluteLocalPath()
+        if filename.endswith('libraries.yaml') or filename.endswith(
+                'libraries.json'):
+            hasChangedFiles = True
+            break
+
+    if hasChangedFiles:
+        local_root = input_api.change.RepositoryRoot()
+        utils = imp.load_source('utils',
+                                os.path.join(local_root, 'tools', 'utils.py'))
+        dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
+        yaml2json = os.path.join(local_root, 'tools', 'yaml2json.dart')
+        libYaml = os.path.join(local_root, 'sdk', 'lib', 'libraries.yaml')
+        libJson = os.path.join(local_root, 'sdk', 'lib', 'libraries.json')
+
+        windows = utils.GuessOS() == 'win32'
+        if windows:
+            dart += '.exe'
+
+        if not os.path.isfile(dart):
+            print('WARNING: dart not found: %s' % dart)
+            return []
+
+        if not os.path.isfile(yaml2json):
+            print('WARNING: yaml2json not found: %s' % yaml2json)
+            return []
+
+        args = [
+            dart, yaml2json, libYaml, libJson, '--check',
+            '--relative=' + local_root + '/'
+        ]
+        process = subprocess.Popen(args,
+                                   stdout=subprocess.PIPE,
+                                   stdin=subprocess.PIPE)
+        outs, _ = process.communicate()
+
+        if process.returncode != 0:
+            return [
+                output_api.PresubmitError('lib/sdk smoketest failure(s)',
+                                          long_text=outs)
+            ]
+
+    return []
+
+
+def CheckChangeOnCommit(input_api, output_api):
+    return runSmokeTest(input_api, output_api)
+
+
+def CheckChangeOnUpload(input_api, output_api):
+    return runSmokeTest(input_api, output_api)
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 6b133cb..95b46d6 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -166,6 +166,22 @@
 }
 
 @patch
+class WeakReference<T extends Object> {
+  @patch
+  factory WeakReference(T object) {
+    throw UnimplementedError("WeakReference");
+  }
+}
+
+@patch
+class Finalizer<T> {
+  @patch
+  factory Finalizer(void Function(T) object) {
+    throw UnimplementedError("Finalizer");
+  }
+}
+
+@patch
 class int {
   @patch
   static int parse(String source,
diff --git a/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
index 7a0de57..474042a 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
@@ -169,8 +169,15 @@
     var re = regExpGetGlobalNative(pattern);
     return stringReplaceJS(receiver, re, replacement);
   } else {
-    // TODO(floitsch): implement generic String.replace (with patterns).
-    throw "String.replaceAll(Pattern) UNIMPLEMENTED";
+    int startIndex = 0;
+    StringBuffer result = StringBuffer();
+    for (Match match in pattern.allMatches(receiver)) {
+      result.write(substring2Unchecked(receiver, startIndex, match.start));
+      result.write(replacement);
+      startIndex = match.end;
+    }
+    result.write(substring1Unchecked(receiver, startIndex));
+    return result.toString();
   }
 }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index b01ebb6..8db9d2a 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -17,8 +17,6 @@
 
 import 'dart:_internal' hide Symbol;
 
-const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
-
 const int _mask30 = 0x3fffffff; // Low 30 bits.
 
 @patch
@@ -509,13 +507,13 @@
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
-          return new JsLinkedHashMap<K, V>.es6();
+          return new JsLinkedHashMap<K, V>();
         }
         hashCode = _defaultHashCode;
       } else {
         if (identical(identityHashCode, hashCode) &&
             identical(identical, equals)) {
-          return new _LinkedIdentityHashMap<K, V>.es6();
+          return new _LinkedIdentityHashMap<K, V>();
         }
         if (equals == null) {
           equals = _defaultEquals;
@@ -533,12 +531,12 @@
   }
 
   @patch
-  factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>.es6;
+  factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>;
 
   // Private factory constructor called by generated code for map literals.
   @pragma('dart2js:noInline')
   factory LinkedHashMap._literal(List keyValuePairs) {
-    return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>.es6());
+    return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>());
   }
 
   // Private factory constructor called by generated code for map literals.
@@ -546,7 +544,7 @@
   @pragma('dart2js:noInline')
   @pragma('dart2js:noSideEffects')
   factory LinkedHashMap._empty() {
-    return new JsLinkedHashMap<K, V>.es6();
+    return new JsLinkedHashMap<K, V>();
   }
 
   // Private factory static function called by generated code for map literals.
@@ -564,17 +562,6 @@
 }
 
 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
-  static bool get _supportsEs6Maps {
-    return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
-        'typeof Map != "undefined"');
-  }
-
-  factory _LinkedIdentityHashMap.es6() {
-    return (_USE_ES6_MAPS && _LinkedIdentityHashMap._supportsEs6Maps)
-        ? new _Es6LinkedIdentityHashMap<K, V>()
-        : new _LinkedIdentityHashMap<K, V>();
-  }
-
   _LinkedIdentityHashMap();
 
   int internalComputeHashCode(var key) {
@@ -595,161 +582,6 @@
   }
 }
 
-class _Es6LinkedIdentityHashMap<K, V> extends _LinkedIdentityHashMap<K, V>
-    implements InternalMap {
-  final _map;
-  int _modifications = 0;
-
-  _Es6LinkedIdentityHashMap() : _map = JS('var', 'new Map()');
-
-  int get length => JS('int', '#.size', _map);
-  bool get isEmpty => length == 0;
-  bool get isNotEmpty => !isEmpty;
-
-  Iterable<K> get keys => new _Es6MapIterable<K>(this, true);
-
-  Iterable<V> get values => new _Es6MapIterable<V>(this, false);
-
-  bool containsKey(Object? key) {
-    return JS('bool', '#.has(#)', _map, key);
-  }
-
-  bool containsValue(Object? value) {
-    return values.any((each) => each == value);
-  }
-
-  void addAll(Map<K, V> other) {
-    other.forEach((K key, V value) {
-      this[key] = value;
-    });
-  }
-
-  V? operator [](Object? key) {
-    return JS('var', '#.get(#)', _map, key);
-  }
-
-  void operator []=(K key, V value) {
-    JS('var', '#.set(#, #)', _map, key, value);
-    _modified();
-  }
-
-  V putIfAbsent(K key, V ifAbsent()) {
-    if (containsKey(key)) return this[key] as V;
-    V value = ifAbsent();
-    this[key] = value;
-    return value;
-  }
-
-  V? remove(Object? key) {
-    V? value = this[key];
-    JS('bool', '#.delete(#)', _map, key);
-    _modified();
-    return value;
-  }
-
-  void clear() {
-    JS('void', '#.clear()', _map);
-    _modified();
-  }
-
-  void forEach(void action(K key, V value)) {
-    var jsEntries = JS('var', '#.entries()', _map);
-    int modifications = _modifications;
-    while (true) {
-      var next = JS('var', '#.next()', jsEntries);
-      bool done = JS('bool', '#.done', next);
-      if (done) break;
-      var entry = JS('var', '#.value', next);
-      var key = JS('var', '#[0]', entry);
-      var value = JS('var', '#[1]', entry);
-      action(key, value);
-      if (modifications != _modifications) {
-        throw new ConcurrentModificationError(this);
-      }
-    }
-  }
-
-  void _modified() {
-    // Value cycles after 2^30 modifications so that modification counts are
-    // always unboxed (Smi) values. Modification detection will be missed if you
-    // make exactly some multiple of 2^30 modifications between advances of an
-    // iterator.
-    _modifications = _mask30 & (_modifications + 1);
-  }
-}
-
-class _Es6MapIterable<E> extends EfficientLengthIterable<E> {
-  final _Es6LinkedIdentityHashMap _map;
-  final bool _isKeys;
-
-  _Es6MapIterable(this._map, this._isKeys);
-
-  int get length => _map.length;
-  bool get isEmpty => _map.isEmpty;
-
-  Iterator<E> get iterator =>
-      new _Es6MapIterator<E>(_map, _map._modifications, _isKeys);
-
-  bool contains(Object? element) => _map.containsKey(element);
-
-  void forEach(void f(E element)) {
-    var jsIterator;
-    if (_isKeys) {
-      jsIterator = JS('var', '#.keys()', _map._map);
-    } else {
-      jsIterator = JS('var', '#.values()', _map._map);
-    }
-    int modifications = _map._modifications;
-    while (true) {
-      var next = JS('var', '#.next()', jsIterator);
-      bool done = JS('bool', '#.done', next);
-      if (done) break;
-      var value = JS('var', '#.value', next);
-      f(value);
-      if (modifications != _map._modifications) {
-        throw new ConcurrentModificationError(_map);
-      }
-    }
-  }
-}
-
-class _Es6MapIterator<E> implements Iterator<E> {
-  final _Es6LinkedIdentityHashMap _map;
-  final int _modifications;
-  final bool _isKeys;
-  var _jsIterator;
-  var _next;
-  E? _current;
-  bool _done = false;
-
-  _Es6MapIterator(this._map, this._modifications, this._isKeys) {
-    if (_isKeys) {
-      _jsIterator = JS('var', '#.keys()', _map._map);
-    } else {
-      _jsIterator = JS('var', '#.values()', _map._map);
-    }
-  }
-
-  E get current => _current as E;
-
-  bool moveNext() {
-    if (_modifications != _map._modifications) {
-      throw new ConcurrentModificationError(_map);
-    }
-    if (_done) return false;
-    _next = JS('var', '#.next()', _jsIterator);
-    bool done = JS('bool', '#.done', _next);
-    if (done) {
-      _current = null;
-      _done = true;
-      return false;
-    } else {
-      _current = JS('var', '#.value', _next);
-      return true;
-    }
-  }
-}
-
 // TODO(floitsch): use ES6 maps when available.
 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> {
   final _Equality<K> _equals;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 6d4d129..529682d 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -118,6 +118,22 @@
 }
 
 @patch
+class WeakReference<T extends Object> {
+  @patch
+  factory WeakReference(T object) {
+    throw UnimplementedError("WeakReference");
+  }
+}
+
+@patch
+class Finalizer<T> {
+  @patch
+  factory Finalizer(void Function(T) object) {
+    throw UnimplementedError("Finalizer");
+  }
+}
+
+@patch
 class int {
   @patch
   static int parse(String source,
@@ -478,7 +494,7 @@
   factory Map.unmodifiable(Map other) = ConstantMap<K, V>.from;
 
   @patch
-  factory Map() = JsLinkedHashMap<K, V>.es6;
+  factory Map() = JsLinkedHashMap<K, V>;
 }
 
 @patch
diff --git a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
index fdf9d23..bd8533a 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -7,8 +7,6 @@
 
 part of _js_helper;
 
-const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
-
 class JsLinkedHashMap<K, V> extends MapBase<K, V>
     implements LinkedHashMap<K, V>, InternalMap {
   int _length = 0;
@@ -35,21 +33,8 @@
   // iterated over.
   int _modifications = 0;
 
-  static bool get _supportsEs6Maps {
-    return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
-        'typeof Map != "undefined"');
-  }
-
   JsLinkedHashMap();
 
-  /// If ES6 Maps are available returns a linked hash-map backed by an ES6 Map.
-  @pragma('dart2js:tryInline')
-  factory JsLinkedHashMap.es6() {
-    return (_USE_ES6_MAPS && JsLinkedHashMap._supportsEs6Maps)
-        ? new Es6LinkedHashMap<K, V>()
-        : new JsLinkedHashMap<K, V>();
-  }
-
   int get length => _length;
   bool get isEmpty => _length == 0;
   bool get isNotEmpty => !isEmpty;
@@ -342,38 +327,6 @@
   }
 }
 
-class Es6LinkedHashMap<K, V> extends JsLinkedHashMap<K, V> {
-  @override
-  LinkedHashMapCell? _getTableCell(var table, var key) {
-    return JS('var', '#.get(#)', table, key);
-  }
-
-  @override
-  List<LinkedHashMapCell>? _getTableBucket(var table, var key) {
-    return JS('var', '#.get(#)', table, key);
-  }
-
-  @override
-  void _setTableEntry(var table, var key, var value) {
-    JS('void', '#.set(#, #)', table, key, value);
-  }
-
-  @override
-  void _deleteTableEntry(var table, var key) {
-    JS('void', '#.delete(#)', table, key);
-  }
-
-  @override
-  bool _containsTableEntry(var table, var key) {
-    return JS('bool', '#.has(#)', table, key);
-  }
-
-  @override
-  _newHashTable() {
-    return JS('var', 'new Map()');
-  }
-}
-
 class LinkedHashMapCell {
   final dynamic hashMapCellKey;
   dynamic hashMapCellValue;
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 5e6c50d..9305f55 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -173,9 +173,21 @@
     return stringReplaceJS(receiver, re, replacement);
   }
 
+  return stringReplaceAllGeneral(receiver, pattern, replacement);
+}
+
+String stringReplaceAllGeneral(
+    String receiver, Pattern pattern, String replacement) {
   checkNull(pattern);
-  // TODO(floitsch): implement generic String.replace (with patterns).
-  throw "String.replaceAll(Pattern) UNIMPLEMENTED";
+  int startIndex = 0;
+  StringBuffer result = StringBuffer();
+  for (Match match in pattern.allMatches(receiver)) {
+    result.write(substring2Unchecked(receiver, startIndex, match.start));
+    result.write(replacement);
+    startIndex = match.end;
+  }
+  result.write(substring1Unchecked(receiver, startIndex));
+  return result.toString();
 }
 
 /// Replaces all non-overlapping occurences of [pattern] in [receiver] with
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index f9b905b..f2b6fc0 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -185,6 +185,27 @@
       !identical(_data, oldData) || (_checkSum != oldCheckSum);
 
   int get length;
+
+  // If this collection has never had an insertion, and [other] is the same
+  // representation and has had no deletions, then adding the entries of [other]
+  // will end up building the same [_data] and [_index]. We can do this more
+  // efficiently by copying the Lists directly.
+  //
+  // Precondition: [this] and [other] must use the same hashcode and equality.
+  bool _quickCopy(_HashBase other) {
+    if (!identical(_index, _uninitializedIndex)) return false;
+    if (other._usedData == 0) return true; // [other] is empty, nothing to copy.
+    if (other._deletedKeys != 0) return false;
+
+    assert(!identical(other._index, _uninitializedIndex));
+    assert(!identical(other._data, _uninitializedData));
+    _index = Uint32List.fromList(other._index);
+    _hashMask = other._hashMask;
+    _data = List.of(other._data, growable: false);
+    _usedData = other._usedData;
+    _deletedKeys = other._deletedKeys;
+    return true;
+  }
 }
 
 class _OperatorEqualsAndHashCode {
@@ -233,6 +254,16 @@
     _usedData = 0;
     _deletedKeys = 0;
   }
+
+  void addAll(Map<K, V> other) {
+    if (other is _InternalLinkedHashMap) {
+      final otherBase = other as _InternalLinkedHashMap; // manual promotion.
+      // If this map is empty we might be able to block-copy from [other].
+      if (isEmpty && _quickCopy(otherBase)) return;
+      // TODO(48143): Pre-grow capacity if it will reduce rehashing.
+    }
+    super.addAll(other);
+  }
 }
 
 // This is essentially the same class as _InternalLinkedHashMap, but it does
@@ -531,12 +562,19 @@
     return false;
   }
 
-  void forEach(void f(K key, V value)) {
-    var ki = keys.iterator;
-    var vi = values.iterator;
-    while (ki.moveNext()) {
-      vi.moveNext();
-      f(ki.current, vi.current);
+  void forEach(void action(K key, V value)) {
+    final data = _data;
+    final checkSum = _checkSum;
+    final len = _usedData;
+    for (int offset = 0; offset < len; offset += 2) {
+      final current = data[offset];
+      if (_HashBase._isDeleted(data, current)) continue;
+      final key = internal.unsafeCast<K>(current);
+      final value = internal.unsafeCast<V>(data[offset + 1]);
+      action(key, value);
+      if (_isModifiedSince(data, checkSum)) {
+        throw ConcurrentModificationError(this);
+      }
     }
   }
 
@@ -554,6 +592,16 @@
         _IdenticalAndIdentityHashCode
     implements LinkedHashMap<K, V> {
   _CompactLinkedIdentityHashMap() : super(_HashBase._INITIAL_INDEX_SIZE);
+
+  void addAll(Map<K, V> other) {
+    if (other is _CompactLinkedIdentityHashMap) {
+      final otherBase = other as _CompactLinkedIdentityHashMap;
+      // If this map is empty we might be able to block-copy from [other].
+      if (isEmpty && _quickCopy(otherBase)) return;
+      // TODO(48143): Pre-grow capacity if it will reduce rehashing.
+    }
+    super.addAll(other);
+  }
 }
 
 class _CompactLinkedCustomHashMap<K, V> extends _HashFieldBase
@@ -825,6 +873,16 @@
   // is not required by the spec. (For instance, always using an identity set
   // would be technically correct, albeit surprising.)
   Set<E> toSet() => new _CompactLinkedHashSet<E>()..addAll(this);
+
+  void addAll(Iterable<E> other) {
+    if (other is _CompactLinkedHashSet) {
+      final otherBase = other as _CompactLinkedHashSet;
+      // If this set is empty we might be able to block-copy from [other].
+      if (isEmpty && _quickCopy(otherBase)) return;
+      // TODO(48143): Pre-grow capacity if it will reduce rehashing.
+    }
+    super.addAll(other);
+  }
 }
 
 @pragma("vm:entry-point")
@@ -917,6 +975,16 @@
   static Set<R> _newEmpty<R>() => new _CompactLinkedIdentityHashSet<R>();
 
   Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+
+  void addAll(Iterable<E> other) {
+    if (other is _CompactLinkedIdentityHashSet) {
+      final otherBase = other as _CompactLinkedIdentityHashSet;
+      // If this set is empty we might be able to block-copy from [other].
+      if (isEmpty && _quickCopy(otherBase)) return;
+      // TODO(48143): Pre-grow capacity if it will reduce rehashing.
+    }
+    super.addAll(other);
+  }
 }
 
 class _CompactLinkedCustomHashSet<E> extends _HashFieldBase
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index f707102..882231f 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.dart
@@ -166,3 +166,27 @@
   List<_WeakProperty?> _data;
   int _used; // Number of used (active and deleted) slots.
 }
+
+@patch
+class WeakReference<T extends Object> {
+  @patch
+  factory WeakReference(T object) = _WeakReferenceImpl<T>;
+}
+
+class _WeakReferenceImpl<T extends Object> implements WeakReference<T> {
+  // TODO(http://dartbug.com/48162): Implement _WeakReference in the VM
+  // instead of reusing WeakProperty.
+  final _WeakProperty _weakProperty;
+
+  _WeakReferenceImpl(T object) : _weakProperty = _WeakProperty()..key = object;
+
+  T? get target => unsafeCast<T?>(_weakProperty.key);
+}
+
+@patch
+class Finalizer<T> {
+  @patch
+  factory Finalizer(void Function(T) object) {
+    throw UnimplementedError("Finalizer");
+  }
+}
diff --git a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
index 92e23c1..ca47a83 100644
--- a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
@@ -55,11 +55,6 @@
 @pragma("vm:entry-point")
 class Uint64 extends _NativeInteger {}
 
-// TODO(http://dartbug.com/47938): Implement as AbiSpecificInteger.
-@patch
-@pragma("vm:entry-point")
-class IntPtr extends _NativeInteger {}
-
 @patch
 @pragma("vm:entry-point")
 class Float extends _NativeDouble {}
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 73d08b7..bbf8499 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -37,6 +37,8 @@
       8, // linuxArm64,
       4, // linuxIA32,
       8, // linuxX64,
+      4, // linuxRiscv32,
+      8, // linuxRiscv64,
       8, // macosArm64,
       8, // macosX64,
       8, // windowsArm64,
@@ -224,8 +226,6 @@
 /// calculations. See pkg/vm/lib/transformations/ffi.dart.
 @pragma("vm:recognized", "other")
 @pragma('vm:prefer-inline')
-@pragma("vm:external-name",
-    "Recognized method: IR graph is built in the flow graph builder.")
 external int _abi();
 
 @patch
@@ -334,10 +334,6 @@
 external int _loadUint64(Object typedDataBase, int offsetInBytes);
 
 @pragma("vm:recognized", "other")
-@pragma("vm:external-name", "Ffi_loadIntPtr")
-external int _loadIntPtr(Object typedDataBase, int offsetInBytes);
-
-@pragma("vm:recognized", "other")
 external int _loadAbiSpecificInt<T extends AbiSpecificInteger>(
     Object typedDataBase, int offsetInBytes);
 
@@ -407,10 +403,6 @@
 external void _storeUint64(Object typedDataBase, int offsetInBytes, int value);
 
 @pragma("vm:recognized", "other")
-@pragma("vm:external-name", "Ffi_storeIntPtr")
-external void _storeIntPtr(Object typedDataBase, int offsetInBytes, int value);
-
-@pragma("vm:recognized", "other")
 external int _storeAbiSpecificInt<T extends AbiSpecificInteger>(
     Object typedDataBase, int offsetInBytes, int value);
 
@@ -476,9 +468,6 @@
 Pointer<Uint64> _elementAtUint64(Pointer<Uint64> pointer, int index) =>
     Pointer.fromAddress(pointer.address + 8 * index);
 
-Pointer<IntPtr> _elementAtIntPtr(Pointer<IntPtr> pointer, int index) =>
-    Pointer.fromAddress(pointer.address + _intPtrSize * index);
-
 Pointer<Float> _elementAtFloat(Pointer<Float> pointer, int index) =>
     Pointer.fromAddress(pointer.address + 4 * index);
 
@@ -696,21 +685,6 @@
   }
 }
 
-extension IntPtrPointer on Pointer<IntPtr> {
-  @patch
-  int get value => _loadIntPtr(this, 0);
-
-  @patch
-  set value(int value) => _storeIntPtr(this, 0, value);
-
-  @patch
-  int operator [](int index) => _loadIntPtr(this, _intPtrSize * index);
-
-  @patch
-  operator []=(int index, int value) =>
-      _storeIntPtr(this, _intPtrSize * index, value);
-}
-
 extension FloatPointer on Pointer<Float> {
   @patch
   double get value => _loadFloat(this, 0);
@@ -883,20 +857,6 @@
   }
 }
 
-extension IntPtrArray on Array<IntPtr> {
-  @patch
-  int operator [](int index) {
-    _checkIndex(index);
-    return _loadIntPtr(_typedDataBase, _intPtrSize * index);
-  }
-
-  @patch
-  operator []=(int index, int value) {
-    _checkIndex(index);
-    return _storeIntPtr(_typedDataBase, _intPtrSize * index, value);
-  }
-}
-
 extension FloatArray on Array<Float> {
   @patch
   double operator [](int index) {
@@ -964,8 +924,16 @@
       throw "UNREACHABLE: This case should have been rewritten in the CFE.";
 
   @patch
+  set ref(T value) =>
+      throw "UNREACHABLE: This case should have been rewritten in the CFE";
+
+  @patch
   T operator [](int index) =>
       throw "UNREACHABLE: This case should have been rewritten in the CFE.";
+
+  @patch
+  void operator []=(int index, T value) =>
+      throw "UNREACHABLE: This case should have been rewritten in the CFE.";
 }
 
 extension UnionPointer<T extends Union> on Pointer<T> {
@@ -974,8 +942,16 @@
       throw "UNREACHABLE: This case should have been rewritten in the CFE.";
 
   @patch
+  set ref(T value) =>
+      throw "UNREACHABLE: This case should have been rewritten in the CFE";
+
+  @patch
   T operator [](int index) =>
       throw "UNREACHABLE: This case should have been rewritten in the CFE.";
+
+  @patch
+  void operator []=(int index, T value) =>
+      throw "UNREACHABLE: This case should have been rewritten in the CFE.";
 }
 
 extension AbiSpecificIntegerPointer<T extends AbiSpecificInteger>
diff --git a/sdk/lib/_internal/vm/lib/hash_factories.dart b/sdk/lib/_internal/vm/lib/hash_factories.dart
new file mode 100644
index 0000000..9e45e8d
--- /dev/null
+++ b/sdk/lib/_internal/vm/lib/hash_factories.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 is a placeholder file which will shortly contain the LinkedhashMap and
+// LinkedHashSet patches from collection_patch.dart. The change is done in two
+// steps to ease rolling it into Flutter.
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 569b91c..b8141d6 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -104,7 +104,6 @@
 
 @pragma("vm:recognized", "other")
 @pragma('vm:prefer-inline')
-@pragma("vm:external-name", "Internal_has63BitSmis")
 external bool get has63BitSmis;
 
 @pragma("vm:recognized", "other")
@@ -168,8 +167,7 @@
 // This function can be used to keep an object alive till that point.
 @pragma("vm:recognized", "other")
 @pragma('vm:prefer-inline')
-@pragma("vm:external-name", "Internal_reachabilityFence")
-external void reachabilityFence(Object object);
+external void reachabilityFence(Object? object);
 
 // This function can be used to encode native side effects.
 //
diff --git a/sdk/lib/_internal/vm/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart
index 37fb390..6e3aabf 100644
--- a/sdk/lib/_internal/vm/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/vm/lib/isolate_patch.dart
@@ -312,7 +312,7 @@
   static Isolate get current => _currentIsolate;
 
   @patch
-  String get debugName => _getDebugName(controlPort);
+  String? get debugName => _getDebugName(controlPort);
 
   @patch
   static Future<Uri?> get packageRoot {
diff --git a/sdk/lib/_internal/vm/lib/math_patch.dart b/sdk/lib/_internal/vm/lib/math_patch.dart
index 270bbbc..ae7872c 100644
--- a/sdk/lib/_internal/vm/lib/math_patch.dart
+++ b/sdk/lib/_internal/vm/lib/math_patch.dart
@@ -164,43 +164,33 @@
 
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_atan2")
 external double _atan2(double a, double b);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_sin")
 external double _sin(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_cos")
 external double _cos(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_tan")
 external double _tan(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_acos")
 external double _acos(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_asin")
 external double _asin(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_atan")
 external double _atan(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_sqrt")
 external double _sqrt(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_exp")
 external double _exp(double x);
 @pragma("vm:recognized", "other")
 @pragma("vm:prefer-inline")
-@pragma("vm:external-name", "Math_log")
 external double _log(double x);
 
 // TODO(iposva): Handle patch methods within a patch class correctly.
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index c3dc65b..4d13cc8 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -80,7 +80,6 @@
   static const int stateWhenComplete = maskWhenComplete;
   static const int maskType =
       maskValue | maskError | maskTestError | maskWhenComplete;
-  static const int stateIsAwait = 16;
 
   // Listeners on the same future are linked through this link.
   _FutureListener? _nextListener;
@@ -110,8 +109,7 @@
       this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
-        state = ((errorCallback == null) ? stateThen : stateThenOnerror) |
-            stateIsAwait;
+        state = stateThenOnerror;
 
   _FutureListener.catchError(this.result, this.errorCallback, this.callback)
       : state = (callback == null) ? stateCatchError : stateCatchErrorTest;
@@ -126,7 +124,6 @@
   bool get handlesError => (state & maskError != 0);
   bool get hasErrorTest => (state & maskType == stateCatchErrorTest);
   bool get handlesComplete => (state & maskType == stateWhenComplete);
-  bool get isAwait => (state & stateIsAwait != 0);
 
   FutureOr<T> Function(S) get _onValue {
     assert(handlesValue);
@@ -304,27 +301,6 @@
   bool get _hasError => (_state & _stateError) != 0;
   bool get _ignoreError => (_state & _stateIgnoreError) != 0;
 
-  static List<Function>? _continuationFunctions(_Future<Object> future) {
-    List<Function>? result = null;
-    while (true) {
-      if (future._mayAddListener) return result;
-      assert(!future._isComplete);
-      assert(!future._isChained);
-      // So _resultOrListeners contains listeners.
-      _FutureListener<Object, Object>? listener = future._resultOrListeners;
-      if (listener != null &&
-          listener._nextListener == null &&
-          listener.isAwait) {
-        (result ??= <Function>[]).add(listener.handleValue);
-        future = listener.result;
-        assert(!future._isComplete);
-      } else {
-        break;
-      }
-    }
-    return result;
-  }
-
   void _setChained(_Future source) {
     assert(_mayAddListener);
     _state = _stateChained | (_state & _stateIgnoreError);
@@ -360,9 +336,7 @@
   /// Registers a system created result and error continuation.
   ///
   /// Used by the implementation of `await` to listen to a future.
-  /// The system created listeners are not registered in the zone,
-  /// and the listener is marked as being from an `await`.
-  /// This marker is used in [_continuationFunctions].
+  /// The system created listeners are not registered in the zone.
   Future<E> _thenAwait<E>(FutureOr<E> f(T value), Function onError) {
     _Future<E> result = new _Future<E>();
     _addListener(new _FutureListener<T, E>.thenAwait(result, f, onError));
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 679c4ef..509faf2 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -15,14 +15,14 @@
 /// A Stream provides a way to receive a sequence of events.
 /// Each event is either a data event, also called an *element* of the stream,
 /// or an error event, which is a notification that something has failed.
-/// When a stream has emitted all its event,
-/// a single "done" event will notify the listener that the end has been reached.
+/// When a stream has emitted all its events,
+/// a single "done" event notifies the listener that the end has been reached.
 ///
 /// You produce a stream by calling an `async*` function, which then returns
 /// a stream. Consuming that stream will lead the function to emit events
 /// until it ends, and the stream closes.
 /// You consume a stream either using an `await for` loop, which is available
-/// inside an `async` or `async*` function, or forwards its events directly
+/// inside an `async` or `async*` function, or by forwarding its events directly
 /// using `yield*` inside an `async*` function.
 /// Example:
 /// ```dart
@@ -55,7 +55,7 @@
 /// then the `optionalMap` function body completes,
 /// which closes the returned stream.
 /// On an error event from the `source` stream,
-/// the `await for` that error is (re-)thrown which breaks the loop.
+/// the `await for` re-throws that error, which breaks the loop.
 /// The error then reaches the end of the `optionalMap` function body,
 /// since it's not caught.
 /// That makes the error be emitted on the returned stream, which then closes.
@@ -71,7 +71,7 @@
 ///
 /// The more low-level [listen] method is what every other method is based on.
 /// You call `listen` on a stream to tell it that you want to receive
-/// events, and to registers the callbacks which will receive those events.
+/// events, and to register the callbacks which will receive those events.
 /// When you call `listen`, you receive a [StreamSubscription] object
 /// which is the active object providing the events,
 /// and which can be used to stop listening again,
@@ -114,7 +114,7 @@
 /// Listening on a broadcast stream can be treated as listening on a new stream
 /// containing only the events that have not yet been emitted when the [listen]
 /// call occurs.
-/// For example, the [first] getter listens to the stream, then returns the first
+/// For example the [first] getter listens to the stream, then returns the first
 /// event that listener receives.
 /// This is not necessarily the first even emitted by the stream, but the first
 /// of the *remaining* events of the broadcast stream.
@@ -126,7 +126,7 @@
 /// as possible.
 ///
 /// Stream subscriptions always respect "pause" requests. If necessary they need
-/// to buffer their input, but often, and preferably, they can simply request
+/// to buffer their input, but often, and preferably they can simply request
 /// their input to pause too.
 ///
 /// The default implementation of [isBroadcast] returns false.
@@ -147,6 +147,19 @@
   ///
   /// This is a stream which does nothing except sending a done event
   /// when it's listened to.
+  ///
+  /// Example:
+  /// ```dart
+  /// const stream = Stream.empty();
+  /// stream.listen(
+  ///   (value) {
+  ///     throw "Unreachable";
+  ///   },
+  ///   onDone: () {
+  ///     print('Done');
+  ///   },
+  /// );
+  /// ```
   const factory Stream.empty() = _EmptyStream<T>;
 
   /// Creates a stream which emits a single data event before closing.
@@ -161,7 +174,7 @@
   ///     print(x);
   ///   }
   /// }
-  /// printThings(Stream<String>.value("ok")); // prints "ok".
+  /// printThings(Stream<String>.value('ok')); // prints "ok".
   /// ```
   ///
   /// The returned stream is effectively equivalent to one created by
@@ -183,13 +196,13 @@
   /// Future<void> tryThings(Stream<int> data) async {
   ///   try {
   ///     await for (var x in data) {
-  ///       print("Data: $x");
+  ///       print('Data: $x');
   ///     }
   ///   } catch (e) {
   ///     print(e);
   ///   }
   /// }
-  /// tryThings(Stream<int>.error("Error")); // prints "Error".
+  /// tryThings(Stream<int>.error('Error')); // prints "Error".
   /// ```
   /// The returned stream is effectively equivalent to one created by
   /// `Future<T>.error(error, stackTrace).asStream()`, by or
@@ -209,6 +222,22 @@
   ///
   /// When the future completes, the stream will fire one event, either
   /// data or error, and then close with a done-event.
+  ///
+  /// Example:
+  /// ```dart
+  /// Future<String> futureTask() async {
+  ///   await Future.delayed(const Duration(seconds: 5));
+  ///   return 'Future complete';
+  /// }
+  ///
+  /// final stream = Stream<String>.fromFuture(futureTask());
+  /// stream.listen(print,
+  ///     onDone: () => print('Done'), onError: print);
+  ///
+  /// // Outputs:
+  /// // "Future complete" after 'futureTask' finished.
+  /// // "Done" when stream completed.
+  /// ```
   factory Stream.fromFuture(Future<T> future) {
     // Use the controller's buffering to fill in the value even before
     // the stream has a listener. For a single value, it's not worth it
@@ -238,6 +267,27 @@
   /// When all futures have completed, the stream is closed.
   ///
   /// If [futures] is empty, the stream closes as soon as possible.
+  ///
+  /// Example:
+  /// ```dart
+  /// Future<int> waitTask() async {
+  ///   await Future.delayed(const Duration(seconds: 2));
+  ///   return 10;
+  /// }
+  ///
+  /// Future<String> doneTask() async {
+  ///   await Future.delayed(const Duration(seconds: 5));
+  ///   return 'Future complete';
+  /// }
+  ///
+  /// final stream = Stream<Object>.fromFutures([doneTask(), waitTask()]);
+  /// stream.listen(print, onDone: () => print('Done'), onError: print);
+  ///
+  /// // Outputs:
+  /// // 10 after 'waitTask' finished.
+  /// // "Future complete" after 'doneTask' finished.
+  /// // "Done" when stream completed.
+  /// ```
   factory Stream.fromFutures(Iterable<Future<T>> futures) {
     _StreamController<T> controller =
         new _SyncStreamController<T>(null, null, null, null);
@@ -282,6 +332,12 @@
   /// the stream emits that error and then it closes.
   /// If reading [Iterator.current] on `elements.iterator` throws,
   /// the stream emits that error, but keeps iterating.
+  ///
+  /// Example:
+  /// ```dart
+  /// final numbers = [1, 2, 3, 5, 6, 7];
+  /// final stream = Stream.fromIterable(numbers);
+  /// ```
   factory Stream.fromIterable(Iterable<T> elements) {
     return new _GeneratedStreamImpl<T>(
         () => new _IterablePendingEvents<T>(elements));
@@ -290,7 +346,7 @@
   /// Creates a multi-subscription stream.
   ///
   /// Each time the created stream is listened to,
-  /// the [onListen] callback is invoked with a new [MultiStreamController]
+  /// the [onListen] callback is invoked with a new [MultiStreamController],
   /// which forwards events to the [StreamSubscription]
   /// returned by that [listen] call.
   ///
@@ -362,12 +418,21 @@
   /// this callback is an integer that starts with 0 and is incremented for
   /// every event.
   ///
-  /// The [period] must a non-negative [Duration].
+  /// The [period] must be a non-negative [Duration].
   ///
-  /// If [computation] is omitted the event values will all be `null`.
+  /// If [computation] is omitted, the event values will all be `null`.
   ///
   /// The [computation] must not be omitted if the event type [T] does not
   /// allow `null` as a value.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(
+  ///         seconds: 1), (count) => count * count).take(5);
+  ///
+  /// stream.forEach(print); // Outputs event values 0,1,4,9,16.
+  /// ```
   factory Stream.periodic(Duration period,
       [T computation(int computationCount)?]) {
     if (computation == null && !typeAcceptsNull<T>()) {
@@ -485,7 +550,7 @@
   /// using [StreamSubscription.asFuture].
   ///
   /// If [onCancel] is provided, it is called in a similar way to [onListen]
-  /// when the returned stream stops having listener. If it later gets
+  /// when the returned stream stops having listeners. If it later gets
   /// a new listener, the [onListen] function is called again.
   ///
   /// Use the callbacks, for example, for pausing the underlying subscription
@@ -496,6 +561,51 @@
   /// If the subscription passed to `onListen` or `onCancel` is cancelled,
   /// then no further events are ever emitted by current subscriptions on
   /// the returned broadcast stream, not even a done event.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(seconds: 1), (count) => count)
+  ///         .take(10);
+  ///
+  /// final broadcastStream = stream.asBroadcastStream(
+  ///   onCancel: (controller) {
+  ///     print('Stream paused');
+  ///     controller.pause();
+  ///   },
+  ///   onListen: (controller) async {
+  ///     if (controller.isPaused) {
+  ///       print('Stream resumed');
+  ///       controller.resume();
+  ///     }
+  ///   },
+  /// );
+  ///
+  /// final oddNumberStream = broadcastStream.where((event) => event.isOdd);
+  /// final oddNumberListener = oddNumberStream.listen(
+  ///       (event) {
+  ///     print('Odd: $event');
+  ///   },
+  ///   onDone: () => print('Done'),
+  /// );
+  ///
+  /// final evenNumberStream = broadcastStream.where((event) => event.isEven);
+  /// final evenNumberListener = evenNumberStream.listen((event) {
+  ///   print('Even: $event');
+  /// }, onDone: () => print('Done'));
+  ///
+  /// await Future.delayed(const Duration(milliseconds: 3500)); // 3.5 second
+  /// // Outputs:
+  /// // Even: 0
+  /// // Odd: 1
+  /// // Even: 2
+  /// oddNumberListener.cancel(); // Nothing printed.
+  /// evenNumberListener.cancel(); // "Stream paused"
+  /// await Future.delayed(const Duration(seconds: 2));
+  /// print(await broadcastStream.first); // "Stream resumed"
+  /// // Outputs:
+  /// // 3
+  /// ```
   Stream<T> asBroadcastStream(
       {void onListen(StreamSubscription<T> subscription)?,
       void onCancel(StreamSubscription<T> subscription)?}) {
@@ -551,6 +661,16 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// If a broadcast stream is listened to more than once, each subscription
   /// will individually perform the `test`.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(seconds: 1), (count) => count)
+  ///         .take(10);
+  ///
+  /// final customStream = stream.where((event) => event > 3 && event <= 6);
+  /// customStream.listen(print); // Outputs event values: 4,5,6.
+  /// ```
   Stream<T> where(bool test(T event)) {
     return new _WhereStream<T>(this, test);
   }
@@ -579,6 +699,22 @@
   /// if a surrogate pair, or a multibyte UTF-8 encoding, is split into
   /// separate events, and those events are attempted encoded or decoded
   /// independently.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(seconds: 1), (count) => count)
+  ///         .take(5);
+  ///
+  /// final calculationStream =
+  ///     stream.map<String>((event) => 'Square: ${event * event}');
+  /// calculationStream.forEach(print);
+  /// // Square: 0
+  /// // Square: 1
+  /// // Square: 4
+  /// // Square: 9
+  /// // Square: 16
+  /// ```
   Stream<S> map<S>(S convert(T event)) {
     return new _MapStream<T, S>(this, convert);
   }
@@ -699,8 +835,8 @@
   /// an error without a stack trace.
   ///
   /// An asynchronous error `error` is matched by a test function if
-  ///`test(error)` returns true. If [test] is omitted, every error is considered
-  /// matching.
+  /// `test(error)` returns true. If [test] is omitted, every error is
+  /// considered matching.
   ///
   /// If the error is intercepted, the [onError] function can decide what to do
   /// with it. It can throw if it wants to raise a new (or the same) error,
@@ -716,6 +852,23 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// If a broadcast stream is listened to more than once, each subscription
   /// will individually perform the `test` and handle the error.
+  ///
+  /// Example:
+  /// ```dart
+  /// Stream.periodic(const Duration(seconds: 1), (count) {
+  ///   if (count == 2) {
+  ///     throw Exception('Exceptional event');
+  ///   }
+  ///   return count;
+  /// }).take(4).handleError(print).forEach(print);
+  ///
+  /// // Outputs:
+  /// // 0
+  /// // 1
+  /// // Exception: Exceptional event
+  /// // 3
+  /// // 4
+  /// ```
   Stream<T> handleError(Function onError, {bool test(error)?}) {
     if (onError is! void Function(Object, StackTrace) &&
         onError is! void Function(Object)) {
@@ -813,6 +966,13 @@
   /// If this stream emits an error, or the call to [combine] throws,
   /// the returned future is completed with that error,
   /// and processing is stopped.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result = await Stream.fromIterable([2, 6, 10, 8, 2])
+  ///     .reduce((previous, element) => previous + element);
+  /// print(result); // 28
+  /// ```
   Future<T> reduce(T combine(T previous, T element)) {
     _Future<T> result = new _Future<T>();
     bool seenFirst = false;
@@ -860,6 +1020,13 @@
   /// If this stream emits an error, or the call to [combine] throws,
   /// the returned future is completed with that error,
   /// and processing is stopped.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result = await Stream.fromIterable([2, 6, 10, 8, 2])
+  ///     .fold<int>(10, (previous, element) => previous + element);
+  /// print(result); // 38
+  /// ```
   Future<S> fold<S>(S initialValue, S combine(S previous, T element)) {
     _Future<S> result = new _Future<S>();
     S value = initialValue;
@@ -887,6 +1054,13 @@
   /// If this stream emits an error, or the call to [Object.toString] throws,
   /// the returned future is completed with that error,
   /// and processing stops.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result = await Stream.fromIterable(['Mars', 'Venus', 'Earth'])
+  ///     .join('--');
+  /// print(result); // 'Mars--Venus--Earth'
+  /// ```
   Future<String> join([String separator = ""]) {
     _Future<String> result = new _Future<String>();
     StringBuffer buffer = new StringBuffer();
@@ -927,6 +1101,13 @@
   /// If this stream emits an error, or the call to [Object.==] throws,
   /// the returned future is completed with that error,
   /// and processing stops.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result = await Stream.fromIterable(['Year', 2021, 12, 24, 'Dart'])
+  ///     .contains('Dart');
+  /// print(result); // true
+  /// ```
   Future<bool> contains(Object? needle) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -976,6 +1157,15 @@
   /// If this stream emits an error, or if the call to [test] throws,
   /// the returned future is completed with that error,
   /// and processing stops.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result =
+  ///     await Stream.periodic(const Duration(seconds: 1), (count) => count)
+  ///         .take(15)
+  ///         .every((x) => x <= 5);
+  /// print(result); // false
+  /// ```
   Future<bool> every(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -1004,6 +1194,16 @@
   /// If this stream emits an error, or if the call to [test] throws,
   /// the returned future is completed with that error,
   /// and processing stops.
+  ///
+  /// Example:
+  /// ```dart
+  /// final result =
+  ///     await Stream.periodic(const Duration(seconds: 1), (count) => count)
+  ///         .take(15)
+  ///         .any((element) => element >= 5);
+  ///
+  /// print(result); // true
+  /// ```
   Future<bool> any(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -1144,6 +1344,12 @@
   /// [futureValue].
   ///
   /// The [futureValue] must not be omitted if `null` is not assignable to [E].
+  ///
+  /// Example:
+  /// ```dart
+  /// final result = await Stream.fromIterable([1, 2, 3]).drain(100);
+  /// print(result); // Outputs: 100.
+  /// ```
   Future<E> drain<E>([E? futureValue]) {
     if (futureValue == null) {
       futureValue = futureValue as E;
@@ -1170,6 +1376,14 @@
   /// If this is a broadcast stream, the returned stream is a broadcast stream.
   /// In that case, the events are only counted from the time
   /// the returned stream is listened to.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(seconds: 1), (i) => i)
+  ///         .take(60);
+  /// stream.forEach(print); // Outputs events: 0, ... 59.
+  /// ```
   Stream<T> take(int count) {
     return new _TakeStream<T>(this, count);
   }
@@ -1194,6 +1408,13 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// For a broadcast stream, the events are only tested from the time
   /// the returned stream is listened to.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream = Stream<int>.periodic(const Duration(seconds: 1), (i) => i)
+  ///     .takeWhile((event) => event < 6);
+  /// stream.forEach(print); // Outputs events: 0, ..., 5.
+  /// ```
   Stream<T> takeWhile(bool test(T element)) {
     return new _TakeWhileStream<T>(this, test);
   }
@@ -1211,6 +1432,13 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// For a broadcast stream, the events are only counted from the time
   /// the returned stream is listened to.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream =
+  ///     Stream<int>.periodic(const Duration(seconds: 1), (i) => i).skip(7);
+  /// stream.forEach(print); // Skips events 0, ..., 6. Outputs events: 7, ...
+  /// ```
   Stream<T> skip(int count) {
     return new _SkipStream<T>(this, count);
   }
@@ -1231,6 +1459,14 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// For a broadcast stream, the events are only tested from the time
   /// the returned stream is listened to.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream = Stream<int>.periodic(const Duration(seconds: 1), (i) => i)
+  ///     .take(10)
+  ///     .skipWhile((x) => x < 5);
+  /// stream.forEach(print); // Outputs events: 5, ..., 9.
+  /// ```
   Stream<T> skipWhile(bool test(T element)) {
     return new _SkipWhileStream<T>(this, test);
   }
@@ -1254,6 +1490,12 @@
   /// The returned stream is a broadcast stream if this stream is.
   /// If a broadcast stream is listened to more than once, each subscription
   /// will individually perform the `equals` test.
+  ///
+  /// Example:
+  /// ```dart
+  /// final stream = Stream.fromIterable([2, 6, 6, 8, 12, 8, 8, 2]).distinct();
+  /// stream.forEach(print); // Outputs events: 2,6,8,12,8,2.
+  /// ```
   Stream<T> distinct([bool equals(T previous, T next)?]) {
     return new _DistinctStream<T>(this, equals);
   }
@@ -1366,9 +1608,9 @@
   /// Finds the first element of this stream matching [test].
   ///
   /// Returns a future that is completed with the first element of this stream
-  /// that [test] returns `true` for.
+  /// for which [test] returns `true`.
   ///
-  /// If no such element is found before this stream is done, and a
+  /// If no such element is found before this stream is done, and an
   /// [orElse] function is provided, the result of calling [orElse]
   /// becomes the value of the future. If [orElse] throws, the returned
   /// future is completed with that error.
@@ -1386,6 +1628,17 @@
   /// If an error occurs, or if this stream ends without finding a match and
   /// with no [orElse] function provided,
   /// the returned future is completed with an error.
+  ///
+  /// Example:
+  /// ```dart
+  /// var result = await Stream.fromIterable([1, 3, 4, 9, 12])
+  ///     .firstWhere((element) => element % 6 == 0, orElse: () => -1);
+  /// print(result); // 12
+  ///
+  /// result = await Stream.fromIterable([1, 2, 3, 4, 5])
+  ///     .firstWhere((element) => element % 6 == 0, orElse: () => -1);
+  /// print(result); // -1
+  /// ```
   Future<T> firstWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
     StreamSubscription<T> subscription =
@@ -1421,6 +1674,17 @@
   /// instead of the first.
   /// That means that a non-error result cannot be provided before this stream
   /// is done.
+  ///
+  /// Example:
+  /// ```dart
+  /// var result = await Stream.fromIterable([1, 3, 4, 7, 12, 24, 32])
+  ///     .lastWhere((element) => element % 6 == 0, orElse: () => -1);
+  /// print(result); // 24
+  ///
+  /// result = await Stream.fromIterable([1, 3, 4, 7, 12, 24, 32])
+  ///     .lastWhere((element) => element % 10 == 0, orElse: () => -1);
+  /// print(result); // -1
+  /// ```
   Future<T> lastWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
     late T result;
@@ -1457,6 +1721,21 @@
   ///
   /// Like [lastWhere], except that it is an error if more than one
   /// matching element occurs in this stream.
+  ///
+  /// Example:
+  /// ```dart
+  /// var result = await Stream.fromIterable([1, 2, 3, 6, 9, 12])
+  ///     .singleWhere((element) => element % 4 == 0, orElse: () => -1);
+  /// print(result); // 12
+  ///
+  /// result = await Stream.fromIterable([2, 6, 8, 12, 24, 32])
+  ///     .singleWhere((element) => element % 9 == 0, orElse: () => -1);
+  /// print(result); // -1
+  ///
+  /// result = await Stream.fromIterable([2, 6, 8, 12, 24, 32])
+  ///     .singleWhere((element) => element % 6 == 0, orElse: () => -1);
+  /// // Throws.
+  /// ```
   Future<T> singleWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future<T>();
     late T result;
@@ -1541,7 +1820,7 @@
   /// the returned stream.
   ///
   /// The countdown starts when the returned stream is listened to,
-  /// and is restarted when an event from the this stream is emitted,
+  /// and is restarted when an event from this stream is emitted,
   /// or when listening on the returned stream is paused and resumed.
   /// The countdown is stopped when listening on the returned stream is
   /// paused or cancelled.
@@ -1565,6 +1844,25 @@
   /// If a broadcast stream is listened to more than once, each subscription
   /// will have its individually timer that starts counting on listen,
   /// and the subscriptions' timers can be paused individually.
+  ///
+  /// Example:
+  /// ```dart
+  /// Future<String> waitTask() async {
+  ///   return await Future.delayed(
+  ///       const Duration(seconds: 4), () => 'Complete');
+  /// }
+  /// final stream = Stream<String>.fromFuture(waitTask())
+  ///     .timeout(const Duration(seconds: 2), onTimeout: (controller) {
+  ///   print('TimeOut occurred');
+  ///   controller.close();
+  /// });
+  ///
+  /// stream.listen(print, onDone: () => print('Done'));
+  ///
+  /// // Outputs:
+  /// // TimeOut occurred
+  /// // Done
+  /// ```
   Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)?}) {
     _StreamControllerBase<T> controller;
     if (isBroadcast) {
@@ -1648,6 +1946,31 @@
 /// and holds the callbacks used to handle the events.
 /// The subscription can also be used to unsubscribe from the events,
 /// or to temporarily pause the events from the stream.
+///
+/// Example:
+/// ```dart
+/// final stream = Stream.periodic(const Duration(seconds: 1), (i) => i * i)
+///     .take(10);
+///
+/// final subscription = stream.listen(print); // A StreamSubscription<int>.
+/// ```
+/// To pause the subscription, use [pause].
+/// ```dart continued
+/// // Do some work.
+/// subscription.pause();
+/// print(subscription.isPaused); // true
+/// ```
+/// To resume after the pause, use [resume].
+/// ```dart continued
+/// // Do some work.
+/// subscription.resume();
+/// print(subscription.isPaused); // false
+/// ```
+/// To cancel the subscription, use [cancel].
+/// ```dart continued
+/// // Do some work.
+/// subscription.cancel();
+/// ```
 abstract class StreamSubscription<T> {
   /// Cancels this subscription.
   ///
@@ -2223,7 +2546,7 @@
 /// As with any synchronous event delivery, the sender should be very careful
 /// to not deliver events at times when a new listener might not
 /// be ready to receive them.
-/// That generally means only delivering events synchronously in response to other
+/// That usually means only delivering events synchronously in response to other
 /// asynchronous events, because that is a time when an asynchronous event could
 /// happen.
 @Since("2.9")
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index ac592bd..499b781 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -8,6 +8,49 @@
 /// ```dart
 /// import 'dart:collection';
 /// ```
+///
+/// ## Map
+/// A finite mapping from unique keys to their associated values.
+/// Allows efficient lookup of the value associated with a key, if any,
+/// and iterating through the individual keys and values of the map.
+/// The [Map] interface has a number of implementations, including the following:
+/// * [HashMap] is unordered, the order of iteration is not guaranteed.
+/// * [LinkedHashMap] iterates in key insertion order.
+/// * [SplayTreeMap] iterates the keys in sorted order.
+/// * [UnmodifiableMapView] is a wrapper, an unmodifiable [Map] view of another
+/// `Map`.
+///
+/// ## Set
+/// A collection of objects in which each object can occur only once.
+/// The [Set] interface has a number of implementations, including the following:
+/// * [HashSet] the order of the objects in the iterations is not guaranteed.
+/// * [LinkedHashSet] iterates the objects in insertion order.
+/// * [SplayTreeSet] iterates the objects in sorted order.
+/// * [UnmodifiableSetView] is a wrapper, an unmodifiable [Set] view of another
+/// `Set`.
+///
+/// ## Queue
+/// A queue is a sequence of elements that is intended to be modified,
+/// by adding or removing elements, only at its ends.
+/// Dart queues are *double ended* queues, which means that they can be
+/// accessed equally from either end, and can therefore be used
+/// to implement both stack and queue behavior.
+/// * [Queue] is the general interface for queues.
+/// * [ListQueue] is a list-based queue. Default implementation for [Queue].
+/// * [DoubleLinkedQueue] is a queue implementation based on a double-linked
+/// list.
+///
+/// ## List
+/// An indexable Sequence of objects. Objects can be accessed using their
+/// position, index, in the sequence. [List] is also called an "array" in other
+/// programming languages.
+/// * [UnmodifiableListView] is a wrapper, an unmodifiable [List] view of
+/// another `List`.
+///
+/// ## LinkedList
+/// [LinkedList] is a specialized double-linked list of elements that extends
+/// [LinkedListEntry]. Each element knows its own place in the linked list,
+/// as well as which list it is in.
 /// {@category Core}
 library dart.collection;
 
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index b8673b1..e4a9357 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -125,9 +125,9 @@
   }
 
   void addAll(Map<K, V> other) {
-    for (K key in other.keys) {
-      this[key] = other[key] as V;
-    }
+    other.forEach((K key, V value) {
+      this[key] = value;
+    });
   }
 
   bool containsValue(Object? value) {
diff --git a/sdk/lib/convert/convert.dart b/sdk/lib/convert/convert.dart
index de5aa6f..9f9bfa6 100644
--- a/sdk/lib/convert/convert.dart
+++ b/sdk/lib/convert/convert.dart
@@ -2,13 +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.
 
-///
 /// Encoders and decoders for converting between different data representations,
 /// including JSON and UTF-8.
 ///
 /// In addition to converters for common data representations, this library
-/// provides support for implementing converters in a way which makes them easy to
-/// chain and to use with streams.
+/// provides support for implementing converters in a way which makes them easy
+/// to chain and to use with streams.
 ///
 /// To use this library in your code:
 /// ```dart
@@ -17,21 +16,91 @@
 /// Two commonly used converters are the top-level instances of
 /// [JsonCodec] and [Utf8Codec], named [json] and [utf8], respectively.
 ///
-/// JSON is a simple text format for representing
-/// structured objects and collections.
-/// The JSON encoder/decoder transforms between strings and
+/// ## JSON
+/// JSON is a simple text format for representing structured objects and
+/// collections.
+///
+/// A [JsonCodec] encodes JSON objects to strings and decodes strings to
+/// JSON objects. The [json] encoder/decoder transforms between strings and
 /// object structures, such as lists and maps, using the JSON format.
 ///
-/// UTF-8 is a common variable-width encoding that can represent
-/// every character in the Unicode character set.
-/// The UTF-8 encoder/decoder transforms between Strings and bytes.
+/// The [json] is the default implementation of [JsonCodec].
 ///
+/// Examples
+/// ```dart
+/// var encoded = json.encode([1, 2, { "a": null }]);
+/// var decoded = json.decode('["foo", { "bar": 499 }]');
+/// ```
+/// For more information, see also [JsonEncoder] and [JsonDecoder].
+///
+/// ## UTF-8
+/// A [Utf8Codec] encodes strings to UTF-8 code units (bytes) and decodes
+/// UTF-8 code units to strings.
+///
+/// The [utf8] is the default implementation of [Utf8Codec].
+///
+/// Example:
+/// ```dart
+/// var encoded = utf8.encode('Îñţérñåţîöñåļîžåţîờñ');
+/// var decoded = utf8.decode([
+///   195, 142, 195, 177, 197, 163, 195, 169, 114, 195, 177, 195, 165, 197,
+///   163, 195, 174, 195, 182, 195, 177, 195, 165, 196, 188, 195, 174, 197,
+///   190, 195, 165, 197, 163, 195, 174, 225, 187, 157, 195, 177]);
+/// ```
+/// For more information, see also [Utf8Encoder] and [Utf8Decoder].
+///
+/// ## ASCII
+/// An [AsciiCodec] encodes strings as ASCII codes stored as bytes and decodes
+/// ASCII bytes to strings. Not all characters can be represented as ASCII, so
+/// not all strings can be successfully converted.
+///
+/// The [ascii] is the default implementation of [AsciiCodec].
+///
+/// Example:
+/// ```dart
+/// var encoded = ascii.encode('This is ASCII!');
+/// var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+///                             0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
+/// ```
+/// For more information, see also [AsciiEncoder] and [AsciiDecoder].
+///
+/// ## Latin-1
+/// A [Latin1Codec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes
+/// and decodes Latin-1 bytes to strings. Not all characters can be represented
+/// as Latin-1, so not all strings can be successfully converted.
+///
+/// The [latin1] is the default implementation of [Latin1Codec].
+///
+/// Example:
+/// ```dart
+/// var encoded = latin1.encode('blåbærgrød');
+/// var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6,
+///                              0x72, 0x67, 0x72, 0xf8, 0x64]);
+/// ```
+/// For more information, see also [Latin1Encoder] and [Latin1Decoder].
+///
+/// ## Base64
+/// A [Base64Codec] encodes bytes using the default base64 alphabet,
+/// decodes using both the base64 and base64url alphabets,
+/// does not allow invalid characters and requires padding.
+///
+/// The [base64] is the default implementation of [Base64Codec].
+///
+/// Example:
+/// ```dart
+/// var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                              0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+/// var decoded = base64.decode('YmzDpWLDpnJncsO4ZAo=');
+/// ```
+/// For more information, see also [Base64Encoder] and [Base64Decoder].
+///
+/// ## Converters
 /// Converters are often used with streams
 /// to transform the data that comes through the stream
 /// as it becomes available.
 /// The following code uses two converters.
 /// The first is a UTF-8 decoder, which converts the data from bytes to UTF-8
-/// as it's read from a file,
+/// as it is read from a file,
 /// The second is an instance of [LineSplitter],
 /// which splits the data on newline boundaries.
 /// ```dart import:io
@@ -51,6 +120,45 @@
 /// See the documentation for the [Codec] and [Converter] classes
 /// for information about creating your own converters.
 ///
+/// ## HTML Escape
+/// [HtmlEscape] converter escapes characters with special meaning in HTML.
+/// The converter finds characters that are significant in HTML source and
+/// replaces them with corresponding HTML entities.
+///
+/// Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode]
+/// constructor.
+///
+/// Example:
+/// ```dart
+/// const htmlEscapeMode = HtmlEscapeMode(
+///   name: 'custom',
+///   escapeLtGt: true,
+///   escapeQuot: false,
+///   escapeApos: false,
+///   escapeSlash: false,
+///  );
+///
+/// const HtmlEscape htmlEscape = HtmlEscape(htmlEscapeMode);
+/// String unescaped = 'Text & subject';
+/// String escaped = htmlEscape.convert(unescaped);
+/// print(escaped); // Text &amp; subject
+///
+/// unescaped = '10 > 1 and 1 < 10';
+/// escaped = htmlEscape.convert(unescaped);
+/// print(escaped); // 10 &gt; 1 and 1 &lt; 10
+///
+/// unescaped = "Single-quoted: 'text'";
+/// escaped = htmlEscape.convert(unescaped);
+/// print(escaped); // Single-quoted: 'text'
+///
+/// unescaped = 'Double-quoted: "text"';
+/// escaped = htmlEscape.convert(unescaped);
+/// print(escaped); // Double-quoted: "text"
+///
+/// unescaped = 'Path: /system/';
+/// escaped = htmlEscape.convert(unescaped);
+/// print(escaped); // Path: /system/
+/// ```
 /// {@category Core}
 library dart.convert;
 
diff --git a/sdk/lib/core/bigint.dart b/sdk/lib/core/bigint.dart
index 63f9198..e5a871c 100644
--- a/sdk/lib/core/bigint.dart
+++ b/sdk/lib/core/bigint.dart
@@ -8,6 +8,39 @@
 ///
 /// Big integers are signed and can have an arbitrary number of
 /// significant digits, only limited by memory.
+///
+/// To create a big integer from the provided number, use [BigInt.from].
+/// ```dart
+/// var bigInteger = BigInt.from(-1); // -1
+/// bigInteger = BigInt.from(0.9999); // 0
+/// bigInteger = BigInt.from(-10.99); // -10
+/// bigInteger = BigInt.from(0x7FFFFFFFFFFFFFFF); // 9223372036854775807
+/// bigInteger = BigInt.from(1e+30); // 1000000000000000019884624838656
+/// ```
+/// To parse a large integer value from a string, use [parse] or [tryParse].
+/// ```dart
+/// var value = BigInt.parse('0x1ffffffffffffffff'); // 36893488147419103231
+/// value = BigInt.parse('12345678901234567890'); // 12345678901234567890
+/// ```
+/// To check whether a big integer can be represented as an [int] without losing
+/// precision, use [isValidInt].
+/// ```dart continued
+/// print(bigNumber.isValidInt); // false
+/// ```
+/// To convert a big integer into an [int], use [toInt].
+/// To convert a big integer into an [double], use [toDouble].
+/// ```dart
+/// var bigValue = BigInt.from(10).pow(3);
+/// print(bigValue.isValidInt); // true
+/// print(bigValue.toInt()); // 1000
+/// print(bigValue.toDouble()); // 1000.0
+/// ```
+/// **See also:**
+/// * [int]: An integer number.
+/// * [double]: A double-precision floating point number.
+/// * [num]: The super class for [int] and [double].
+/// * [Numbers](https://dart.dev/guides/language/numbers) in
+/// [A tour of the Dart language](https://dart.dev/guides/language/language-tour).
 abstract class BigInt implements Comparable<BigInt> {
   /// A big integer with the numerical value 0.
   external static BigInt get zero;
@@ -39,6 +72,31 @@
   ///
   /// Throws a [FormatException] if the [source] is not a valid integer literal,
   /// optionally prefixed by a sign.
+  /// Examples:
+  /// ```dart
+  /// print(BigInt.parse('-12345678901234567890')); // -12345678901234567890
+  /// print(BigInt.parse('0xFF')); // 255
+  /// print(BigInt.parse('0xffffffffffffffff')); // 18446744073709551615
+  ///
+  /// // From binary (base 2) value.
+  /// print(BigInt.parse('1100', radix: 2)); // 12
+  /// print(BigInt.parse('00011111', radix: 2)); // 31
+  /// print(BigInt.parse('011111100101', radix: 2)); // 2021
+  /// // From octal (base 8) value.
+  /// print(BigInt.parse('14', radix: 8)); // 12
+  /// print(BigInt.parse('37', radix: 8)); // 31
+  /// print(BigInt.parse('3745', radix: 8)); // 2021
+  /// // From hexadecimal (base 16) value.
+  /// print(BigInt.parse('c', radix: 16)); // 12
+  /// print(BigInt.parse('1f', radix: 16)); // 31
+  /// print(BigInt.parse('7e5', radix: 16)); // 2021
+  /// // From base 35 value.
+  /// print(BigInt.parse('y1', radix: 35)); // 1191 == 34 * 35 + 1
+  /// print(BigInt.parse('z1', radix: 35)); // Throws.
+  /// // From base 36 value.
+  /// print(BigInt.parse('y1', radix: 36)); // 1225 == 34 * 36 + 1
+  /// print(BigInt.parse('z1', radix: 36)); // 1261 == 35 * 36 + 1
+  /// ```
   external static BigInt parse(String source, {int? radix});
 
   /// Parses [source] as a, possibly signed, integer literal and returns its
@@ -46,9 +104,42 @@
   ///
   /// As [parse] except that this method returns `null` if the input is not
   /// valid
+  ///
+  /// Examples:
+  /// ```dart
+  /// print(BigInt.tryParse('-12345678901234567890')); // -12345678901234567890
+  /// print(BigInt.tryParse('0xFF')); // 255
+  /// print(BigInt.tryParse('0xffffffffffffffff')); // 18446744073709551615
+  ///
+  /// // From binary (base 2) value.
+  /// print(BigInt.tryParse('1100', radix: 2)); // 12
+  /// print(BigInt.tryParse('00011111', radix: 2)); // 31
+  /// print(BigInt.tryParse('011111100101', radix: 2)); // 2021
+  /// // From octal (base 8) value.
+  /// print(BigInt.tryParse('14', radix: 8)); // 12
+  /// print(BigInt.tryParse('37', radix: 8)); // 31
+  /// print(BigInt.tryParse('3745', radix: 8)); // 2021
+  /// // From hexadecimal (base 16) value.
+  /// print(BigInt.tryParse('c', radix: 16)); // 12
+  /// print(BigInt.tryParse('1f', radix: 16)); // 31
+  /// print(BigInt.tryParse('7e5', radix: 16)); // 2021
+  /// // From base 35 value.
+  /// print(BigInt.tryParse('y1', radix: 35)); // 1191 == 34 * 35 + 1
+  /// print(BigInt.tryParse('z1', radix: 35)); // null
+  /// // From base 36 value.
+  /// print(BigInt.tryParse('y1', radix: 36)); // 1225 == 34 * 36 + 1
+  /// print(BigInt.tryParse('z1', radix: 36)); // 1261 == 35 * 36 + 1
+  /// ```
   external static BigInt? tryParse(String source, {int? radix});
 
-  /// Allocates a big integer from the provided [value] number.
+  /// Creates a big integer from the provided [value] number.
+  ///
+  /// Examples:
+  /// ```dart
+  /// var bigInteger = BigInt.from(1); // 1
+  /// bigInteger = BigInt.from(0.9999); // 0
+  /// bigInteger = BigInt.from(-10.99); // -10
+  /// ```
   external factory BigInt.from(num value);
 
   /// Returns the absolute value of this integer.
@@ -83,7 +174,14 @@
   /// this operation first performs [toDouble] on both this big integer
   /// and [other], then does [double.operator/] on those values and
   /// returns the result.
-  /// The initial [toDouble] conversion may lose precision.
+  ///
+  /// **Note:** The initial [toDouble] conversion may lose precision.
+  ///
+  /// Example:
+  /// ```dart
+  /// print(BigInt.from(1) / BigInt.from(2)); // 0.5
+  /// print(BigInt.from(1.99999) / BigInt.from(2)); // 0.5
+  /// ```
   double operator /(BigInt other);
 
   /// Truncating integer division operator.
@@ -114,6 +212,14 @@
   /// The sign of the returned value `r` is always positive.
   ///
   /// See [remainder] for the remainder of the truncating division.
+  ///
+  /// Example:
+  /// ```dart
+  /// print(BigInt.from(5) % BigInt.from(3)); // 2
+  /// print(BigInt.from(-5) % BigInt.from(3)); // 1
+  /// print(BigInt.from(5) % BigInt.from(-3)); // 2
+  /// print(BigInt.from(-5) % BigInt.from(-3)); // 1
+  /// ```
   BigInt operator %(BigInt other);
 
   /// Returns the remainder of the truncating division of `this` by [other].
@@ -121,6 +227,14 @@
   /// The result `r` of this operation satisfies:
   /// `this == (this ~/ other) * other + r`.
   /// As a consequence the remainder `r` has the same sign as the divider `this`.
+  ///
+  /// Example:
+  /// ```dart
+  /// print(BigInt.from(5).remainder(BigInt.from(3))); // 2
+  /// print(BigInt.from(-5).remainder(BigInt.from(3))); // -2
+  /// print(BigInt.from(5).remainder(BigInt.from(-3))); // 2
+  /// print(BigInt.from(-5).remainder(BigInt.from(-3))); // -2
+  /// ```
   BigInt remainder(BigInt other);
 
   /// Shift the bits of this integer to the left by [shiftAmount].
@@ -198,12 +312,19 @@
   ///
   /// Returns a negative number if `this` is less than `other`, zero if they are
   /// equal, and a positive number if `this` is greater than `other`.
+  ///
+  /// Example:
+  /// ```dart
+  /// print(BigInt.from(1).compareTo(BigInt.from(2))); // => -1
+  /// print(BigInt.from(2).compareTo(BigInt.from(1))); // => 1
+  /// print(BigInt.from(1).compareTo(BigInt.from(1))); // => 0
+  /// ```
   int compareTo(BigInt other);
 
   /// Returns the minimum number of bits required to store this big integer.
   ///
   /// The number of bits excludes the sign bit, which gives the natural length
-  /// for non-negative (unsigned) values.  Negative values are complemented to
+  /// for non-negative (unsigned) values. Negative values are complemented to
   /// return the bit position of the first bit that differs from the sign bit.
   ///
   /// To find the number of bits needed to store the value as a signed value,
@@ -246,6 +367,20 @@
   ///
   /// The result is always equal to the mathematical result of this to the power
   /// [exponent], only limited by the available memory.
+  ///
+  /// Example:
+  /// ```dart
+  /// var value = BigInt.from(1000);
+  /// print(value.pow(0)); // 1
+  /// print(value.pow(1)); // 1000
+  /// print(value.pow(2)); // 1000000
+  /// print(value.pow(3)); // 1000000000
+  /// print(value.pow(4)); // 1000000000000
+  /// print(value.pow(5)); // 1000000000000000
+  /// print(value.pow(6)); // 1000000000000000000
+  /// print(value.pow(7)); // 1000000000000000000000
+  /// print(value.pow(8)); // 1000000000000000000000000
+  /// ```
   BigInt pow(int exponent);
 
   /// Returns this integer to the power of [exponent] modulo [modulus].
@@ -269,15 +404,24 @@
   /// integer dividing both `this` and `other`.
   ///
   /// The greatest common divisor is independent of the order,
-  /// so `x.gcd(y)` is  always the same as `y.gcd(x)`.
+  /// so `x.gcd(y)` is always the same as `y.gcd(x)`.
   ///
   /// For any integer `x`, `x.gcd(x)` is `x.abs()`.
   ///
   /// If both `this` and `other` is zero, the result is also zero.
+  ///
+  /// Example:
+  /// ```dart
+  /// print(BigInt.from(4).gcd(BigInt.from(2))); // 2
+  /// print(BigInt.from(8).gcd(BigInt.from(4))); // 4
+  /// print(BigInt.from(10).gcd(BigInt.from(12))); // 2
+  /// print(BigInt.from(10).gcd(BigInt.from(10))); // 10
+  /// print(BigInt.from(-2).gcd(BigInt.from(-3))); // 1
+  /// ```
   BigInt gcd(BigInt other);
 
   /// Returns the least significant [width] bits of this big integer as a
-  /// non-negative number (i.e. unsigned representation).  The returned value has
+  /// non-negative number (i.e. unsigned representation). The returned value has
   /// zeros in all bit positions higher than [width].
   ///
   /// ```dart
@@ -294,7 +438,7 @@
   /// `q` will count from `0` up to `255` and then wrap around to `0`.
   ///
   /// If the input fits in [width] bits without truncation, the result is the
-  /// same as the input.  The minimum width needed to avoid truncation of `x` is
+  /// same as the input. The minimum width needed to avoid truncation of `x` is
   /// given by `x.bitLength`, i.e.
   ///
   /// ```dart
@@ -303,8 +447,8 @@
   BigInt toUnsigned(int width);
 
   /// Returns the least significant [width] bits of this integer, extending the
-  /// highest retained bit to the sign.  This is the same as truncating the value
-  /// to fit in [width] bits using an signed 2-s complement representation.  The
+  /// highest retained bit to the sign. This is the same as truncating the value
+  /// to fit in [width] bits using an signed 2-s complement representation. The
   /// returned value has the same bit value in all positions higher than [width].
   ///
   /// ```dart
@@ -328,7 +472,7 @@
   /// `127`.
   ///
   /// If the input value fits in [width] bits without truncation, the result is
-  /// the same as the input.  The minimum width needed to avoid truncation of `x`
+  /// the same as the input. The minimum width needed to avoid truncation of `x`
   /// is `x.bitLength + 1`, i.e.
   ///
   /// ```dart
@@ -339,9 +483,18 @@
   /// Whether this big integer can be represented as an `int` without losing
   /// precision.
   ///
-  /// Warning: this function may give a different result on
+  /// **Warning:** this function may give a different result on
   /// dart2js, dev compiler, and the VM, due to the differences in
   /// integer precision.
+  ///
+  /// Example:
+  /// ```dart
+  /// var bigNumber = BigInt.parse('100000000000000000000000');
+  /// print(bigNumber.isValidInt); // false
+  ///
+  /// var value = BigInt.parse('0xFF'); // 255
+  /// print(value.isValidInt); // true
+  /// ```
   bool get isValidInt;
 
   /// Returns this [BigInt] as an [int].
@@ -349,9 +502,15 @@
   /// If the number does not fit, clamps to the max (or min)
   /// integer.
   ///
-  /// Warning: the clamping behaves differently on dart2js, dev
-  /// compiler, and the VM, due to the differences in integer
-  /// precision.
+  /// **Warning:** the clamping behaves differently between the web and
+  /// native platforms due to the differences in integer precision.
+  ///
+  /// Example:
+  /// ```dart
+  /// var bigNumber = BigInt.parse('100000000000000000000000');
+  /// print(bigNumber.isValidInt); // false
+  /// print(bigNumber.toInt()); // 9223372036854775807
+  /// ```
   int toInt();
 
   /// Returns this [BigInt] as a [double].
@@ -359,6 +518,12 @@
   /// If the number is not representable as a [double], an
   /// approximation is returned. For numerically large integers, the
   /// approximation may be infinite.
+  ///
+  /// Example:
+  /// ```dart
+  /// var bigNumber = BigInt.parse('100000000000000000000000');
+  /// print(bigNumber.toDouble()); // 1e+23
+  /// ```
   double toDouble();
 
   /// Returns a String-representation of this integer.
@@ -366,6 +531,12 @@
   /// The returned string is parsable by [parse].
   /// For any `BigInt` `i`, it is guaranteed that
   /// `i == BigInt.parse(i.toString())`.
+  ///
+  /// Example:
+  /// ```dart
+  /// var bigNumber = BigInt.parse('100000000000000000000000');
+  /// print(bigNumber.toString()); // "100000000000000000000000"
+  /// ```
   String toString();
 
   /// Converts [this] to a string representation in the given [radix].
@@ -374,5 +545,24 @@
   /// '9', with 'a' being 10 an 'z' being 35.
   ///
   /// The [radix] argument must be an integer in the range 2 to 36.
+  ///
+  /// Example:
+  /// ```dart
+  /// // Binary (base 2).
+  /// print(BigInt.from(12).toRadixString(2)); // 1100
+  /// print(BigInt.from(31).toRadixString(2)); // 11111
+  /// print(BigInt.from(2021).toRadixString(2)); // 11111100101
+  /// print(BigInt.from(-12).toRadixString(2)); // -1100
+  /// // Octal (base 8).
+  /// print(BigInt.from(12).toRadixString(8)); // 14
+  /// print(BigInt.from(31).toRadixString(8)); // 37
+  /// print(BigInt.from(2021).toRadixString(8)); // 3745
+  /// // Hexadecimal (base 16).
+  /// print(BigInt.from(12).toRadixString(16)); // c
+  /// print(BigInt.from(31).toRadixString(16)); // 1f
+  /// print(BigInt.from(2021).toRadixString(16)); // 7e5
+  /// // Base 36.
+  /// print(BigInt.from(35 * 36 + 1).toRadixString(36)); // z1
+  /// ```
   String toRadixString(int radix);
 }
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 3799c08..324a84b 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -181,7 +181,6 @@
 part "enum.dart";
 part "errors.dart";
 part "exceptions.dart";
-part "expando.dart";
 part "function.dart";
 part "identical.dart";
 part "int.dart";
@@ -206,3 +205,4 @@
 part "symbol.dart";
 part "type.dart";
 part "uri.dart";
+part "weak.dart";
diff --git a/sdk/lib/core/core_sources.gni b/sdk/lib/core/core_sources.gni
index 66362e9..12f70fb 100644
--- a/sdk/lib/core/core_sources.gni
+++ b/sdk/lib/core/core_sources.gni
@@ -16,7 +16,6 @@
   "enum.dart",
   "errors.dart",
   "exceptions.dart",
-  "expando.dart",
   "function.dart",
   "identical.dart",
   "int.dart",
@@ -41,4 +40,5 @@
   "symbol.dart",
   "type.dart",
   "uri.dart",
+  "weak.dart",
 ]
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 6190c83..00d69ce 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -64,6 +64,7 @@
 /// For example, the [String.contains] method will use a [RangeError]
 /// if its `startIndex` isn't in the range `0..length`,
 /// which is easily created by `RangeError.range(startIndex, 0, length)`.
+@pragma('flutter:keep-to-string-in-subtypes')
 class Error {
   Error(); // Prevent use as mixin.
 
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 889c991..f522d27 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -16,6 +16,7 @@
 /// is discouraged in library code since it doesn't give users a precise
 /// type they can catch. It may be reasonable to use instances of this
 /// class in tests or during development.
+@pragma('flutter:keep-to-string-in-subtypes')
 abstract class Exception {
   factory Exception([var message]) => _Exception(message);
 }
diff --git a/sdk/lib/core/expando.dart b/sdk/lib/core/expando.dart
deleted file mode 100644
index bcdee49..0000000
--- a/sdk/lib/core/expando.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.core;
-
-/// An [Expando] allows adding new properties to objects.
-///
-/// Does not work on numbers, strings, booleans, `null`, `dart:ffi` pointers,
-/// `dart:ffi` structs, or `dart:ffi` unions.
-///
-/// An `Expando` does not hold on to the added property value after an object
-/// becomes inaccessible.
-///
-/// Since you can always create a new number that is identical to an existing
-/// number, it means that an expando property on a number could never be
-/// released. To avoid this, expando properties cannot be added to numbers.
-/// The same argument applies to strings, booleans and `null`, which also have
-/// literals that evaluate to identical values when they occur more than once.
-///
-/// There is no restriction on other classes, even for compile time constant
-/// objects. Be careful if adding expando properties to compile time constants,
-/// since they will stay alive forever.
-class Expando<T extends Object> {
-  /// The name of the this [Expando] as passed to the constructor. If
-  /// no name was passed to the constructor, the name is `null`.
-  final String? name;
-
-  /// Creates a new [Expando]. The optional name is only used for
-  /// debugging purposes and creating two different [Expando]s with the
-  /// same name yields two [Expando]s that work on different properties
-  /// of the objects they are used on.
-  external Expando([String? name]);
-
-  /// Expando toString method override.
-  String toString() => "Expando:$name";
-
-  /// Gets the value of this [Expando]'s property on the given
-  /// object. If the object hasn't been expanded, the method returns
-  /// `null`.
-  ///
-  /// The object must not be a number, a string, a boolean, `null`, a
-  /// `dart:ffi` pointer, a `dart:ffi` struct, or a `dart:ffi` union.
-  external T? operator [](Object object);
-
-  /// Sets the value of this [Expando]'s property on the given
-  /// object. Properties can effectively be removed again by setting
-  /// their value to `null`.
-  ///
-  /// The object must not be a number, a string, a boolean, `null`, a
-  /// `dart:ffi` pointer, a `dart:ffi` struct, or a `dart:ffi` union.
-  external void operator []=(Object object, T? value);
-}
diff --git a/sdk/lib/core/function.dart b/sdk/lib/core/function.dart
index 1151354..ea2d614 100644
--- a/sdk/lib/core/function.dart
+++ b/sdk/lib/core/function.dart
@@ -20,16 +20,33 @@
   ///
   /// Example:
   /// ```dart
-  /// Function.apply(foo, [1, 2, 3], {#f: 4, #g: 5});
-  /// ```
+  /// void printWineDetails(int vintage, {String? country, String? name}) {
+  ///   print('Name: $name, Country: $country, Vintage: $vintage');
+  /// }
   ///
-  /// gives exactly the same result as
-  /// ```dart
-  /// foo(1, 2, 3, f: 4, g: 5).
+  /// void main() {
+  ///   Function.apply(
+  ///       printWineDetails, [2018], {#country: 'USA', #name: 'Dominus Estate'});
+  /// }
+  ///
+  /// // Output of the example is:
+  /// // Name: Dominus Estate, Country: USA, Vintage: 2018
   /// ```
   ///
   /// If [positionalArguments] is null, it's considered an empty list.
   /// If [namedArguments] is omitted or null, it is considered an empty map.
+  ///
+  /// ```dart
+  /// void helloWorld() {
+  ///   print('Hello world!');
+  /// }
+  ///
+  /// void main() {
+  ///   Function.apply(helloWorld, null);
+  /// }
+  /// // Output of the example is:
+  /// // Hello world!
+  /// ```
   external static apply(Function function, List<dynamic>? positionalArguments,
       [Map<Symbol, dynamic>? namedArguments]);
 
diff --git a/sdk/lib/core/identical.dart b/sdk/lib/core/identical.dart
index a8bdedf..c13ab27 100644
--- a/sdk/lib/core/identical.dart
+++ b/sdk/lib/core/identical.dart
@@ -5,6 +5,18 @@
 part of dart.core;
 
 /// Check whether two references are to the same object.
+///
+/// Example:
+/// ```dart
+/// var o = new Object();
+/// var isIdentical = identical(o, new Object()); // false, different objects.
+/// isIdentical = identical(o, o); // true, same object
+/// isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
+/// isIdentical = identical([1], [1]); // false
+/// isIdentical = identical(const [1], const [1]); // true
+/// isIdentical = identical(const [1], const [2]); // false
+/// isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
+/// ```
 external bool identical(Object? a, Object? b);
 
 /// The identity hash code of [object].
@@ -14,5 +26,14 @@
 ///
 /// This hash code is compatible with [identical],
 /// which just means that it's guaranteed to be stable over time.
+/// ```dart import:dart:collection
+/// var identitySet = HashSet(equals: identical, hashCode: identityHashCode);
+/// var dt1 = DateTime.now();
+/// var dt2 = DateTime.fromMicrosecondsSinceEpoch(dt1.microsecondsSinceEpoch);
+/// assert(dt1 == dt2);
+/// identitySet.add(dt1);
+/// print(identitySet.contains(dt1)); // true
+/// print(identitySet.contains(dt2)); // false
+/// ```
 @pragma("vm:entry-point")
 external int identityHashCode(Object? object);
diff --git a/sdk/lib/core/iterator.dart b/sdk/lib/core/iterator.dart
index 7ea322e..a33e273 100644
--- a/sdk/lib/core/iterator.dart
+++ b/sdk/lib/core/iterator.dart
@@ -49,6 +49,14 @@
   /// If that happens, the iterator may be in an inconsistent
   /// state, and any further behavior of the iterator is unspecified,
   /// including the effect of reading [current].
+  /// ```dart
+  /// final colors = ['blue', 'yellow', 'red'];
+  /// final colorsIterator = colors.iterator;
+  /// print(colorsIterator.moveNext()); // true
+  /// print(colorsIterator.moveNext()); // true
+  /// print(colorsIterator.moveNext()); // true
+  /// print(colorsIterator.moveNext()); // false
+  /// ```
   bool moveNext();
 
   /// The current element.
@@ -65,5 +73,18 @@
   /// [moveNext], even if an underlying collection changes.
   /// After a successful call to `moveNext`, the user doesn't need to cache
   /// the current value, but can keep reading it from the iterator.
+  /// ```dart
+  /// final colors = ['blue', 'yellow', 'red'];
+  /// var colorsIterator = colors.iterator;
+  /// while (colorsIterator.moveNext()) {
+  ///   print(colorsIterator.current);
+  /// }
+  /// ```
+  /// The output of the example is:
+  /// ```
+  /// blue
+  /// yellow
+  /// red
+  /// ```
   E get current;
 }
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index f6c6caf..ae091be 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -451,11 +451,32 @@
 }
 
 /// A key/value pair representing an entry in a [Map].
+///
+/// The [Map] interface contains various methods that can
+/// inspect or modify the map based on entry objects.
+/// ```dart
+/// final map = {'1': 'A', '2': 'B'};
+/// map.addEntries([
+///  MapEntry('3', 'C'),
+///  MapEntry('4', 'D'),
+/// ]);
+/// print(map); // {1: A, 2: B, 3: C, 4: D}
+/// ```
 class MapEntry<K, V> {
   /// The key of the entry.
+  /// ```dart
+  /// final map = {'theKey': 'theValue'};
+  /// var entry = map.entries.first;
+  /// print(entry.key); // theKey
+  /// ```
   final K key;
 
   /// The value associated to [key] in the map.
+  /// ```dart
+  /// final map = {'theKey': 'theValue'};
+  /// var entry = map.entries.first;
+  /// print(entry.value); // theValue
+  /// ```
   final V value;
 
   /// Creates an entry with [key] and [value].
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index 23b4445..fbf70ea 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.dart
@@ -20,15 +20,38 @@
   /// and then from the end of the previous match (but always
   /// at least one position later than the *start* of the previous
   /// match, in case the pattern matches an empty substring).
+  /// ```dart
+  /// RegExp exp = RegExp(r'(\w+)');
+  /// var str = 'Dash is a bird';
+  /// Iterable<Match> matches = exp.allMatches(str, 8);
+  /// for (final Match m in matches) {
+  ///   String match = m[0]!;
+  ///   print(match);
+  /// }
+  /// ```
+  /// The output of the example is:
+  /// ```
+  /// a
+  /// bird
+  /// ```
   Iterable<Match> allMatches(String string, [int start = 0]);
 
   /// Matches this pattern against the start of `string`.
   ///
   /// Returns a match if the pattern matches a substring of [string]
   /// starting at [start], and `null` if the pattern doesn't match
-  /// a that point.
+  /// at that point.
   ///
   /// The [start] must be non-negative and no greater than `string.length`.
+  /// ```dart
+  /// final string = 'Dash is a bird';
+  ///
+  /// var regExp = RegExp(r'bird');
+  /// var match = regExp.matchAsPrefix(string, 10); // Match found.
+  ///
+  /// regExp = RegExp(r'bird');
+  /// match = regExp.matchAsPrefix(string); // null
+  /// ```
   Match? matchAsPrefix(String string, [int start = 0]);
 }
 
@@ -41,10 +64,10 @@
 /// The following example finds all matches of a [RegExp] in a [String]
 /// and iterates through the returned iterable of `Match` objects.
 /// ```dart
-/// RegExp exp = RegExp(r"(\w+)");
-/// String str = "Parse my string";
-/// Iterable<Match> matches = exp.allMatches(str);
-/// for (Match m in matches) {
+/// final regExp = RegExp(r'(\w+)');
+/// const string = 'Parse my string';
+/// final matches = regExp.allMatches(string);
+/// for (final m in matches) {
 ///   String match = m[0]!;
 ///   print(match);
 /// }
@@ -72,6 +95,17 @@
   ///
   /// The result may be `null` if the pattern didn't assign a value to it
   /// as part of this match.
+  /// ```dart import:convert
+  ///
+  /// final string = '[00:13.37] This is a chat message.';
+  /// final regExp = RegExp(r'^\[\s*(\d+):(\d+)\.(\d+)\]\s*(.*)$');
+  /// final match = regExp.firstMatch(string)!;
+  /// final message = jsonEncode(match[0]!); // '[00:13.37] This is a chat message.'
+  /// final hours = jsonEncode(match[1]!); // '00'
+  /// final minutes = jsonEncode(match[2]!); // '13'
+  /// final seconds = jsonEncode(match[3]!); // '37'
+  /// final text = jsonEncode(match[4]!); // 'This is a chat message.'
+  /// ```
   String? group(int group);
 
   /// The string matched by the given [group].
@@ -85,6 +119,14 @@
   ///
   /// The list contains the strings returned by [group] for each index in
   /// [groupIndices].
+  /// ```dart import:convert
+  ///
+  /// final string = '[00:13.37] This is a chat message.';
+  /// final regExp = RegExp(r'^\[\s*(\d+):(\d+)\.(\d+)\]\s*(.*)$');
+  /// final match = regExp.firstMatch(string)!;
+  /// final message = jsonEncode(match.groups([1, 2, 3, 4]));
+  /// // ['00','13','37','This is a chat message.']
+  /// ```
   List<String?> groups(List<int> groupIndices);
 
   /// Returns the number of captured groups in the match.
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index 993da0a5..c2020a6 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -19,15 +19,32 @@
 /// and returns the first [RegExpMatch].
 /// All other methods in [RegExp] can be build from that.
 ///
+/// The following example finds the first match of a regular expression in
+/// a string.
+/// ```dart
+/// RegExp exp = RegExp(r'(\w+)');
+/// String str = 'Parse my string';
+/// RegExpMatch? match = exp.firstMatch(str);
+/// print(match![0]); // "Parse"
+/// ```
 /// Use [allMatches] to look for all matches of a regular expression in
 /// a string.
 ///
 /// The following example finds all matches of a regular expression in
 /// a string.
 /// ```dart
-/// RegExp exp = RegExp(r"(\w+)");
-/// String str = "Parse my string";
+/// RegExp exp = RegExp(r'(\w+)');
+/// String str = 'Parse my string';
 /// Iterable<RegExpMatch> matches = exp.allMatches(str);
+/// for (final m in matches) {
+///   print(m[0]);
+/// }
+/// ```
+/// The output of the example is:
+/// ```
+/// Parse
+/// my
+/// string
 /// ```
 ///
 /// Note the use of a _raw string_ (a string prefixed with `r`)
@@ -54,8 +71,8 @@
   /// Example:
   ///
   /// ```dart
-  /// var wordPattern = RegExp(r"(\w+)");
-  /// var bracketedNumberValue = RegExp("$key: \\[\\d+\\]");
+  /// final wordPattern = RegExp(r'(\w+)');
+  /// final digitPattern = RegExp(r'(\d+)');
   /// ```
   ///
   /// Notice the use of a _raw string_ in the first example, and a regular
@@ -82,22 +99,55 @@
   /// larger regular expression. Since a [String] is itself a [Pattern]
   /// which matches itself, converting the string to a regular expression
   /// isn't needed in order to search for just that string.
+  /// ```dart
+  /// print(RegExp.escape('dash@example.com')); // dash@example\.com
+  /// print(RegExp.escape('a+b')); // a\+b
+  /// print(RegExp.escape('a*b')); // a\*b
+  /// print(RegExp.escape('{a-b}')); // \{a-b\}
+  /// print(RegExp.escape('a?')); // a\?
+  /// ```
   external static String escape(String text);
 
   /// Finds the first match of the regular expression in the string [input].
   ///
   /// Returns `null` if there is no match.
+  /// ```dart
+  /// final string = '[00:13.37] This is a chat message.';
+  /// final regExp = RegExp(r'c\w*');
+  /// final match = regExp.firstMatch(string)!;
+  /// print(match[0]); // chat
+  /// ```
   RegExpMatch? firstMatch(String input);
 
   Iterable<RegExpMatch> allMatches(String input, [int start = 0]);
 
   /// Whether the regular expression has a match in the string [input].
+  /// ```dart
+  /// var string = 'Dash is a bird';
+  /// var regExp = RegExp(r'(humming)?bird');
+  /// var match = regExp.hasMatch(string); // true
+  ///
+  /// regExp = RegExp(r'dog');
+  /// match = regExp.hasMatch(string); // false
+  /// ```
   bool hasMatch(String input);
 
   /// The substring of the first match of this regular expression in [input].
+  /// ```dart
+  /// var string = 'Dash is a bird';
+  /// var regExp = RegExp(r'(humming)?bird');
+  /// var match = regExp.stringMatch(string); // Match
+  ///
+  /// regExp = RegExp(r'dog');
+  /// match = regExp.stringMatch(string); // No match
+  /// ```
   String? stringMatch(String input);
 
   /// The source regular expression string used to create this `RegExp`.
+  /// ```dart
+  /// final regExp = RegExp(r'\p{L}');
+  /// print(regExp.pattern); // \p{L}
+  /// ```
   String get pattern;
 
   /// Whether this regular expression matches multiple lines.
@@ -112,6 +162,16 @@
   /// If the regular expression is not case sensitive, it will match an input
   /// letter with a pattern letter even if the two letters are different case
   /// versions of the same letter.
+  /// ```dart
+  /// final str = 'Parse my string';
+  /// var regExp = RegExp(r'STRING', caseSensitive: false);
+  /// final hasMatch = regExp.hasMatch(str); // Has matches.
+  /// print(regExp.isCaseSensitive); // false
+  ///
+  /// regExp = RegExp(r'STRING', caseSensitive: true);
+  /// final hasCaseSensitiveMatch = regExp.hasMatch(str); // No matches.
+  /// print(regExp.isCaseSensitive); // true
+  /// ```
   bool get isCaseSensitive;
 
   /// Whether this regular expression is in Unicode mode.
@@ -124,6 +184,19 @@
   /// In Unicode mode, the syntax of the RegExp pattern is more restricted, but
   /// some pattern features, like Unicode property escapes, are only available in
   /// this mode.
+  /// ```dart
+  /// var regExp = RegExp(r'^\p{L}$', unicode: true);
+  /// print(regExp.hasMatch('a')); // true
+  /// print(regExp.hasMatch('b')); // true
+  /// print(regExp.hasMatch('?')); // false
+  /// print(regExp.hasMatch(r'p{L}')); // false
+  ///
+  /// regExp = RegExp(r'^\p{L}$', unicode: false);
+  /// print(regExp.hasMatch('a')); // false
+  /// print(regExp.hasMatch('b')); // false
+  /// print(regExp.hasMatch('?')); // false
+  /// print(regExp.hasMatch(r'p{L}')); // true
+  /// ```
   @Since("2.4")
   bool get isUnicode;
 
@@ -145,6 +218,41 @@
 /// Regular expression matches are [Match]es, but also include the ability
 /// to retrieve the names for any named capture groups and to retrieve
 /// matches for named capture groups by name instead of their index.
+///
+/// Example:
+/// ```dart
+/// const pattern =
+///     r'^\[(?<Time>\s*((?<hour>\d+)):((?<minute>\d+))\.((?<second>\d+)))\]'
+///     r'\s(?<Message>\s*(.*)$)';
+///
+/// final regExp = RegExp(
+///   pattern,
+///   multiLine: true,
+/// );
+///
+/// const multilineText = '[00:13.37] This is a first message.\n'
+///     '[01:15.57] This is a second message.\n';
+///
+/// RegExpMatch regExpMatch = regExp.firstMatch(multilineText)!;
+/// print(regExpMatch.groupNames.join('-')); // hour-minute-second-Time-Message.
+/// final time = regExpMatch.namedGroup('Time'); // 00:13.37
+/// final hour = regExpMatch.namedGroup('hour'); // 00
+/// final minute = regExpMatch.namedGroup('minute'); // 13
+/// final second = regExpMatch.namedGroup('second'); // 37
+/// final message =
+///     regExpMatch.namedGroup('Message'); // This is a first message.
+/// final date = regExpMatch.namedGroup('Date'); // Undefined `Date`, throws.
+///
+/// Iterable<RegExpMatch> matches = regExp.allMatches(multilineText);
+/// for (final m in matches) {
+///   print(m.namedGroup('Time'));
+///   print(m.namedGroup('Message'));
+///   // 00:13.37
+///   // This is a first message.
+///   // 01:15.57
+///   // This is a second message.
+/// }
+/// ```
 @Since("2.3")
 abstract class RegExpMatch implements Match {
   /// The string matched by the group named [name].
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 8764498..d3ec0f0 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -81,7 +81,7 @@
 /// ```
 /// For a character outside the Basic Multilingual Plane (plane 0) that is
 /// composed of a surrogate pair, [runes] combines the pair and returns a
-/// single integer.  For example, the Unicode character for a
+/// single integer. For example, the Unicode character for a
 /// musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate
 /// pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,
 /// and using `runes` returns their combined value:
@@ -198,7 +198,7 @@
   /// The length of the string.
   ///
   /// Returns the number of UTF-16 code units in this string. The number
-  /// of [runes] might be fewer, if the string contains characters outside
+  /// of [runes] might be fewer if the string contains characters outside
   /// the Basic Multilingual Plane (plane 0):
   /// ```dart
   /// 'Dart'.length;          // 4
@@ -346,7 +346,7 @@
   /// result = string.substring(1, 4); // 'art'
   /// ```
   ///
-  /// Both [start] and [end] must be non-negative and no greater than [length], and
+  /// Both [start] and [end] must be non-negative and no greater than [length];
   /// [end], if provided, must be greater than or equal to [start].
   String substring(int start, [int? end]);
 
@@ -494,7 +494,7 @@
   /// Example:
   /// ```dart
   /// '0.0001'.replaceFirst(RegExp(r'0'), ''); // '.0001'
-  /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1);  // '0.7001'
+  /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1); // '0.7001'
   /// ```
   String replaceFirst(Pattern from, String to, [int startIndex = 0]);
 
@@ -724,6 +724,44 @@
 }
 
 /// The runes (integer Unicode code points) of a [String].
+///
+/// The characters of a string are encoded in UTF-16. Decoding UTF-16, which
+/// combines surrogate pairs, yields Unicode code points. Following a similar
+/// terminology to Go, Dart uses the name 'rune' for an integer representing a
+/// Unicode code point. Use the `runes` property to get the runes of a string.
+///
+/// Example:
+/// ```dart
+/// const string = 'Dart';
+/// final runes = string.runes.toList();
+/// print(runes); // [68, 97, 114, 116]
+/// ```
+///
+/// For a character outside the Basic Multilingual Plane (plane 0) that is
+/// composed of a surrogate pair, runes combines the pair and returns a
+/// single integer.
+///
+/// For example, the Unicode character for "Man" emoji ('👨', `U+1F468`) is
+/// combined from the surrogates `U+d83d` and `U+dc68`.
+///
+/// Example:
+/// ```dart
+/// const emojiMan = '👨';
+/// print(emojiMan.runes); // (128104)
+///
+/// // Surrogate pairs:
+/// for (final item in emojiMan.codeUnits) {
+///   print(item.toRadixString(16));
+///   // d83d
+///   // dc68
+/// }
+/// ```
+///
+/// **See also:**
+/// * [Runes and grapheme clusters](
+/// https://dart.dev/guides/language/language-tour#runes-and-grapheme-clusters)
+/// in
+/// [A tour of the Dart language](https://dart.dev/guides/language/language-tour).
 class Runes extends Iterable<int> {
   /// The string that this is the runes of.
   final String string;
diff --git a/sdk/lib/core/weak.dart b/sdk/lib/core/weak.dart
new file mode 100644
index 0000000..01ef31c
--- /dev/null
+++ b/sdk/lib/core/weak.dart
@@ -0,0 +1,246 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.core;
+
+/// An [Expando] allows adding new properties to objects.
+///
+/// Does not work on numbers, strings, booleans, `null`, `dart:ffi` pointers,
+/// `dart:ffi` structs, or `dart:ffi` unions.
+///
+/// An `Expando` does not hold on to the added property value after an object
+/// becomes inaccessible.
+///
+/// Since you can always create a new number that is identical to an existing
+/// number, it means that an expando property on a number could never be
+/// released. To avoid this, expando properties cannot be added to numbers.
+/// The same argument applies to strings, booleans and `null`, which also have
+/// literals that evaluate to identical values when they occur more than once.
+///
+/// There is no restriction on other classes, even for compile time constant
+/// objects. Be careful if adding expando properties to compile time constants,
+/// since they will stay alive forever.
+class Expando<T extends Object> {
+  /// The name of the this [Expando] as passed to the constructor.
+  ///
+  /// If no name was passed to the constructor, the value is the `null` value.
+  final String? name;
+
+  /// Creates a new [Expando]. The optional name is only used for
+  /// debugging purposes and creating two different [Expando]s with the
+  /// same name yields two [Expando]s that work on different properties
+  /// of the objects they are used on.
+  external Expando([String? name]);
+
+  /// Expando toString method override.
+  String toString() => "Expando:$name";
+
+  /// Gets the value of this [Expando]'s property on the given object.
+  ///
+  /// If the object hasn't been expanded, the result is the `null` value.
+  ///
+  /// The object must not be a number, a string, a boolean, `null`, a
+  /// `dart:ffi` pointer, a `dart:ffi` struct, or a `dart:ffi` union.
+  external T? operator [](Object object);
+
+  /// Sets this [Expando]'s property value on the given object to [value].
+  ///
+  /// Properties can effectively be removed again
+  /// by setting their value to `null`.
+  ///
+  /// The object must not be a number, a string, a boolean, `null`, a
+  /// `dart:ffi` pointer, a `dart:ffi` struct, or a `dart:ffi` union.
+  external void operator []=(Object object, T? value);
+}
+
+/// A weak reference to a Dart object.
+///
+/// A _weak_ reference to the [target] object which may be cleared
+/// (set to reference `null` instead) at any time
+/// when there is no other way for the program to access the target object.
+///
+/// _Being the target of a weak reference does not keep an object
+/// from being garbage collected._
+///
+/// There are no guarantees that a weak reference will ever be cleared
+/// even if all references to its target are weak references.
+///
+/// Not all objects are supported as targets for weak references.
+/// The [WeakReference] constructor will reject any object that is not
+/// supported as an [Expando] key.
+@Since("2.17")
+abstract class WeakReference<T extends Object> {
+  /// Creates a [WeakReference] pointing to the given [target].
+  ///
+  /// The [target] must be an object supported as an [Expando] key,
+  /// which means [target] cannot be a number, a string, a boolean,
+  /// the `null` value, or certain other types of special objects.
+  external factory WeakReference(T target);
+
+  /// The current object weakly referenced by [this], if any.
+  ///
+  /// The value is either the object supplied in the constructor,
+  /// or `null` if the weak reference has been cleared.
+  T? get target;
+}
+
+/// A finalizer which can be attached to Dart objects.
+///
+/// A finalizer can create attachments between
+/// the finalizer and any number of Dart values,
+/// by calling [attach] with the value, along with a
+/// _finalization token_ and an optional _attach key_,
+/// which are part of the attachment.
+///
+/// When a Dart value becomes inaccessible to the program,
+/// any finalizer that currently has an attachment to
+/// the value *may* have its callback function called
+/// with the attachment's finalization token.
+///
+/// Example:
+/// ```dart template:none
+/// // Keep the finalizer itself reachable, otherwise might not do anything.
+/// final Finalizer<DBConnection> _finalizer = Finalizer((connection) {
+///   connection.close();
+/// });
+///
+/// /// Access the database.
+/// Database connect() {
+///   // Wraps the connection in a nicer user-facing API,
+///   // *and* closes connection if the user forgets to.
+///   var connection = _connectToDatabase();
+///   var wrapper = Database._fromConnection(connection, _finalizer);
+///   // Get finalizer callback when `wrapper` is no longer reachable.
+///   _finalizer.attach(wrapper, connection, detach: wrapper);
+///   return wrapper;
+/// }
+///
+/// class Database {
+///   final DBConnection _connection;
+///   final Finalizer<Connection> _finalizer;
+///   Database._fromConnection(this._connection, this._finalizer);
+///
+///   // Some useful methods.
+///
+///   void close() {
+///     // User requested close.
+///     _connection.close();
+///     // Detach from finalizer, no longer needed.
+///     _finalizer.detach(this);
+///   }
+/// }
+/// ```
+/// This example has an example of an external resource that needs clean-up.
+/// The finalizer is used to clean up an external connection when the
+/// user of the API no longer has access to that connection.
+/// The example uses the same object as attached object and detach key,
+/// which is a useful approach when each attached object can be detached
+/// individually. Being a detachment key doesn't keep an object alive.
+///
+/// No promises are made that the callback will ever be called.
+/// The only thing that is guaranteed is that if a finalizer's callback
+/// is called with a specific finalization token as argument,
+/// then at least one value with an attachment to to the finalizer
+/// that has that finalization token,
+/// is no longer accessible to the program.
+///
+/// If the finalzier *itself* becomes unreachable,
+/// it's allowed to be garbage collected
+/// and then it won't trigger any further callbacks.
+/// Always make sure to keep the finalizer itself reachable while it's needed.
+///
+/// If multiple finalizers are attached to a single object,
+/// or the same finalizer is attached multiple times to an object,
+/// and that object becomes inaccessible to the program,
+/// then any number (including zero) of those attachments may trigger
+/// their associated finalizer's callback.
+/// It will not necessarily be all or none of them.
+///
+/// Finalization callbacks will happen as *events*.
+/// They will not happen during execution of other code,
+/// and not as a microtask,
+/// but as high-level events similar to timer events.
+///
+/// Finalization callbacks must not throw.
+@Since("2.17")
+abstract class Finalizer<T> {
+  /// Creates a finalizer with the given finalization callback.
+  ///
+  /// The [callback] is bound to the current zone
+  /// when the [Finalizer] is created, and will run in that zone when called.
+  external factory Finalizer(void Function(T) callback);
+
+  /// Attaches this finalizer to [value].
+  ///
+  /// When [value] is longer accessible to the program,
+  /// while still having an attachement to this finalizer,
+  /// the callback of this finalizer *may* be called
+  /// with [finalizationToken] as argument.
+  /// The callback may be called at most once per active attachment,
+  /// ones which have not been detached by calling [Finalizer.detach].
+  ///
+  /// If a non-`null` [detach] value is provided, that object can be
+  /// passed to [Finalizer.detach] to remove the attachment again.
+  ///
+  /// The [value] and [detach] arguments do not count towards those
+  /// objects being accessible to the program.
+  /// Both must be objects supported as an [Expando] key.
+  /// They may be the *same* object.
+  ///
+  /// Example:
+  /// ```dart template:top
+  /// /// Access the data base.
+  /// Database connect() {
+  ///   // Wraps the connection in a nice user API,
+  ///   // *and* closes connection if the user forgets to.
+  ///   var connection = _connectToDatabase();
+  ///   var wrapper = Database._fromConnection(connection, _finalizer);
+  ///   // Get finalizer callback when `wrapper` is no longer reachable.
+  ///   _finalizer.attach(wrapper, connection, detach: wrapper);
+  ///   return wrapper;
+  /// }
+  /// ````
+  ///
+  /// Multiple objects may be attached using the same finalization token,
+  /// and the finalizer can be attached multiple times to the same object
+  /// with different, or the same, finalization token.
+  void attach(Object value, T finalizationToken, {Object? detach});
+
+  /// Detaches the finalizer from values attached with [detachToken].
+  ///
+  /// Each attachment between this finalizer and a value,
+  /// which was created by calling [attach] with the [detachToken] object as
+  /// `detach` argument, is removed.
+  ///
+  /// If the finalizer was attached multiple times to the same value
+  /// with different detachment keys,
+  /// only those attachments which used [detachToken] are removed.
+  ///
+  /// After detaching, an attachment won't cause any callbacks to happen
+  /// if the object become inaccessible.
+  ///
+  /// Example:
+  /// ```dart template:none
+  /// final Finalizer<DBConnection> _finalizer = Finalizer((connection) {
+  ///   connection.close();
+  /// });
+  ///
+  /// class Database {
+  ///   final DBConnection _connection;
+  ///   final Finalizer<Connection> _finalizer;
+  ///   Database._fromConnection(this._connection, this._finalizer);
+  ///
+  ///   // Some useful methods.
+  ///
+  ///   void close() {
+  ///     // User requested close.
+  ///     _connection.close();
+  ///     // Detach from finalizer, no longer needed.
+  ///     // Was attached using this object as `detach` token.
+  ///     _finalizer.detach(this);
+  ///   }
+  /// }
+  /// ```
+  void detach(Object detachToken);
+}
diff --git a/sdk/lib/ffi/abi.dart b/sdk/lib/ffi/abi.dart
index f5cba04..1efe4a5 100644
--- a/sdk/lib/ffi/abi.dart
+++ b/sdk/lib/ffi/abi.dart
@@ -57,6 +57,12 @@
   /// The application binary interface for linux on the X64 architecture.
   static const linuxX64 = _linuxX64;
 
+  /// The application binary interface for linux on 32-bit RISC-V.
+  static const linuxRiscv32 = _linuxRiscv32;
+
+  /// The application binary interface for linux on 64-bit RISC-V.
+  static const linuxRiscv64 = _linuxRiscv64;
+
   /// The application binary interface for MacOS on the Arm64 architecture.
   static const macosArm64 = _macosArm64;
 
@@ -94,6 +100,8 @@
     linuxArm64,
     linuxIA32,
     linuxX64,
+    linuxRiscv32,
+    linuxRiscv64,
     macosArm64,
     macosX64,
     windowsArm64,
@@ -134,6 +142,8 @@
   static const _linuxArm64 = Abi._(_Architecture.arm64, _OS.linux);
   static const _linuxIA32 = Abi._(_Architecture.ia32, _OS.linux);
   static const _linuxX64 = Abi._(_Architecture.x64, _OS.linux);
+  static const _linuxRiscv32 = Abi._(_Architecture.riscv32, _OS.linux);
+  static const _linuxRiscv64 = Abi._(_Architecture.riscv64, _OS.linux);
   static const _macosArm64 = Abi._(_Architecture.arm64, _OS.macos);
   static const _macosX64 = Abi._(_Architecture.x64, _OS.macos);
   static const _windowsArm64 = Abi._(_Architecture.arm64, _OS.windows);
@@ -147,6 +157,8 @@
   arm64,
   ia32,
   x64,
+  riscv32,
+  riscv64,
 }
 
 /// The operating systems the Dart VM runs on.
diff --git a/sdk/lib/ffi/abi_specific.dart b/sdk/lib/ffi/abi_specific.dart
index 560044a..a41308c 100644
--- a/sdk/lib/ffi/abi_specific.dart
+++ b/sdk/lib/ffi/abi_specific.dart
@@ -13,10 +13,12 @@
 /// For example:
 ///
 /// ```
-/// /// Represents a `uintptr_t` in C.
+/// /// The C `uintptr_t` type.
 /// ///
-/// /// [UintPtr] is not constructible in the Dart code and serves purely as
-/// /// marker in type signatures.
+/// /// The [UintPtr] type is a native type, and should not be constructed in
+/// /// Dart code.
+/// /// It occurs only in native type signatures and as annotation on [Struct]
+/// /// and [Union] fields.
 /// @AbiSpecificIntegerMapping({
 ///   Abi.androidArm: Uint32(),
 ///   Abi.androidArm64: Uint64(),
@@ -30,6 +32,8 @@
 ///   Abi.linuxArm64: Uint64(),
 ///   Abi.linuxIA32: Uint32(),
 ///   Abi.linuxX64: Uint64(),
+///   Abi.linuxRiscv32: Uint32(),
+///   Abi.linuxRiscv64: Uint64(),
 ///   Abi.macosArm64: Uint64(),
 ///   Abi.macosX64: Uint64(),
 ///   Abi.windowsIA32: Uint32(),
diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart
new file mode 100644
index 0000000..b1bc764
--- /dev/null
+++ b/sdk/lib/ffi/c_type.dart
@@ -0,0 +1,503 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library defines [NativeType]s for common C types.
+///
+/// Many C types only define a minimal size in the C standard, but they are
+/// consistent per [Abi]. Therefore we use [AbiSpecificInteger]s to define
+/// these C types in this library.
+part of dart.ffi;
+
+/// The C `signed char` type.
+///
+/// Typically a signed 8-bit integer.
+/// For a guaranteed 8-bit integer, use [Int8] with the C `int8_t` type.
+/// For an `unsigned char`, use [UnsignedChar].
+///
+/// The [SignedChar] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int8(),
+  Abi.androidArm64: Int8(),
+  Abi.androidIA32: Int8(),
+  Abi.androidX64: Int8(),
+  Abi.fuchsiaArm64: Int8(),
+  Abi.fuchsiaX64: Int8(),
+  Abi.iosArm: Int8(),
+  Abi.iosArm64: Int8(),
+  Abi.iosX64: Int8(),
+  Abi.linuxArm: Int8(),
+  Abi.linuxArm64: Int8(),
+  Abi.linuxIA32: Int8(),
+  Abi.linuxX64: Int8(),
+  Abi.linuxRiscv32: Int8(),
+  Abi.linuxRiscv64: Int8(),
+  Abi.macosArm64: Int8(),
+  Abi.macosX64: Int8(),
+  Abi.windowsArm64: Int8(),
+  Abi.windowsIA32: Int8(),
+  Abi.windowsX64: Int8(),
+})
+class SignedChar extends AbiSpecificInteger {
+  const SignedChar();
+}
+
+/// The C `unsigned char` type.
+///
+/// Typically an unsigned 8-bit integer.
+/// For a guaranteed 8-bit integer, use [Uint8] with the C `uint8_t` type.
+/// For a `signed char`, use [SignedChar].
+///
+/// The [UnsignedChar] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint8(),
+  Abi.androidArm64: Uint8(),
+  Abi.androidIA32: Uint8(),
+  Abi.androidX64: Uint8(),
+  Abi.fuchsiaArm64: Uint8(),
+  Abi.fuchsiaX64: Uint8(),
+  Abi.iosArm: Uint8(),
+  Abi.iosArm64: Uint8(),
+  Abi.iosX64: Uint8(),
+  Abi.linuxArm: Uint8(),
+  Abi.linuxArm64: Uint8(),
+  Abi.linuxIA32: Uint8(),
+  Abi.linuxX64: Uint8(),
+  Abi.linuxRiscv32: Uint8(),
+  Abi.linuxRiscv64: Uint8(),
+  Abi.macosArm64: Uint8(),
+  Abi.macosX64: Uint8(),
+  Abi.windowsArm64: Uint8(),
+  Abi.windowsIA32: Uint8(),
+  Abi.windowsX64: Uint8(),
+})
+class UnsignedChar extends AbiSpecificInteger {
+  const UnsignedChar();
+}
+
+/// The C `short` type.
+///
+/// Typically a signed 16-bit integer.
+/// For a guaranteed 16-bit integer, use [Int16] with the C `int16_t` type.
+/// For an `unsigned short`, use [UnsignedShort].
+///
+/// The [Short] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int16(),
+  Abi.androidArm64: Int16(),
+  Abi.androidIA32: Int16(),
+  Abi.androidX64: Int16(),
+  Abi.fuchsiaArm64: Int16(),
+  Abi.fuchsiaX64: Int16(),
+  Abi.iosArm: Int16(),
+  Abi.iosArm64: Int16(),
+  Abi.iosX64: Int16(),
+  Abi.linuxArm: Int16(),
+  Abi.linuxArm64: Int16(),
+  Abi.linuxIA32: Int16(),
+  Abi.linuxX64: Int16(),
+  Abi.linuxRiscv32: Int16(),
+  Abi.linuxRiscv64: Int16(),
+  Abi.macosArm64: Int16(),
+  Abi.macosX64: Int16(),
+  Abi.windowsArm64: Int16(),
+  Abi.windowsIA32: Int16(),
+  Abi.windowsX64: Int16(),
+})
+class Short extends AbiSpecificInteger {
+  const Short();
+}
+
+/// The C `unsigned short` type.
+///
+/// Typically an unsigned 16-bit integer.
+/// For a guaranteed 16-bit integer, use [Uint16] with the C `uint16_t` type.
+/// For a signed `short`, use [Short].
+///
+/// The [UnsignedShort] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint16(),
+  Abi.androidArm64: Uint16(),
+  Abi.androidIA32: Uint16(),
+  Abi.androidX64: Uint16(),
+  Abi.fuchsiaArm64: Uint16(),
+  Abi.fuchsiaX64: Uint16(),
+  Abi.iosArm: Uint16(),
+  Abi.iosArm64: Uint16(),
+  Abi.iosX64: Uint16(),
+  Abi.linuxArm: Uint16(),
+  Abi.linuxArm64: Uint16(),
+  Abi.linuxIA32: Uint16(),
+  Abi.linuxX64: Uint16(),
+  Abi.linuxRiscv32: Uint16(),
+  Abi.linuxRiscv64: Uint16(),
+  Abi.macosArm64: Uint16(),
+  Abi.macosX64: Uint16(),
+  Abi.windowsArm64: Uint16(),
+  Abi.windowsIA32: Uint16(),
+  Abi.windowsX64: Uint16(),
+})
+class UnsignedShort extends AbiSpecificInteger {
+  const UnsignedShort();
+}
+
+/// The C `int` type.
+///
+/// Typically a signed 32-bit integer.
+/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type.
+/// For an `unsigned int`, use [UnsignedInt].
+///
+/// The [Int] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int32(),
+  Abi.androidArm64: Int32(),
+  Abi.androidIA32: Int32(),
+  Abi.androidX64: Int32(),
+  Abi.fuchsiaArm64: Int32(),
+  Abi.fuchsiaX64: Int32(),
+  Abi.iosArm: Int32(),
+  Abi.iosArm64: Int32(),
+  Abi.iosX64: Int32(),
+  Abi.linuxArm: Int32(),
+  Abi.linuxArm64: Int32(),
+  Abi.linuxIA32: Int32(),
+  Abi.linuxX64: Int32(),
+  Abi.linuxRiscv32: Int32(),
+  Abi.linuxRiscv64: Int32(),
+  Abi.macosArm64: Int32(),
+  Abi.macosX64: Int32(),
+  Abi.windowsArm64: Int32(),
+  Abi.windowsIA32: Int32(),
+  Abi.windowsX64: Int32(),
+})
+class Int extends AbiSpecificInteger {
+  const Int();
+}
+
+/// The C `unsigned int` type.
+///
+/// Typically an unsigned 32-bit integer.
+/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type.
+/// For a signed `int`, use [Int].
+///
+/// The [UnsignedInt] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint32(),
+  Abi.androidArm64: Uint32(),
+  Abi.androidIA32: Uint32(),
+  Abi.androidX64: Uint32(),
+  Abi.fuchsiaArm64: Uint32(),
+  Abi.fuchsiaX64: Uint32(),
+  Abi.iosArm: Uint32(),
+  Abi.iosArm64: Uint32(),
+  Abi.iosX64: Uint32(),
+  Abi.linuxArm: Uint32(),
+  Abi.linuxArm64: Uint32(),
+  Abi.linuxIA32: Uint32(),
+  Abi.linuxX64: Uint32(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint32(),
+  Abi.macosArm64: Uint32(),
+  Abi.macosX64: Uint32(),
+  Abi.windowsArm64: Uint32(),
+  Abi.windowsIA32: Uint32(),
+  Abi.windowsX64: Uint32(),
+})
+class UnsignedInt extends AbiSpecificInteger {
+  const UnsignedInt();
+}
+
+/// The C `long int`, aka. `long`, type.
+///
+/// Typically a signed 32- or 64-bit integer.
+/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type.
+/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type.
+/// For an `unsigned long`, use [UnsignedLong].
+///
+/// The [Long] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int32(),
+  Abi.androidArm64: Int64(),
+  Abi.androidIA32: Int32(),
+  Abi.androidX64: Int64(),
+  Abi.fuchsiaArm64: Int64(),
+  Abi.fuchsiaX64: Int64(),
+  Abi.iosArm: Int32(),
+  Abi.iosArm64: Int64(),
+  Abi.iosX64: Int64(),
+  Abi.linuxArm: Int32(),
+  Abi.linuxArm64: Int64(),
+  Abi.linuxIA32: Int32(),
+  Abi.linuxX64: Int64(),
+  Abi.linuxRiscv32: Int32(),
+  Abi.linuxRiscv64: Int64(),
+  Abi.macosArm64: Int64(),
+  Abi.macosX64: Int64(),
+  Abi.windowsArm64: Int32(),
+  Abi.windowsIA32: Int32(),
+  Abi.windowsX64: Int32(),
+})
+class Long extends AbiSpecificInteger {
+  const Long();
+}
+
+/// The C `unsigned long int`, aka. `unsigned long`, type.
+///
+/// Typically an unsigned 32- or 64-bit integer.
+/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type.
+/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type.
+/// For a signed `long`, use [Long].
+///
+/// The [UnsignedLong] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint32(),
+  Abi.androidArm64: Uint64(),
+  Abi.androidIA32: Uint32(),
+  Abi.androidX64: Uint64(),
+  Abi.fuchsiaArm64: Uint64(),
+  Abi.fuchsiaX64: Uint64(),
+  Abi.iosArm: Uint32(),
+  Abi.iosArm64: Uint64(),
+  Abi.iosX64: Uint64(),
+  Abi.linuxArm: Uint32(),
+  Abi.linuxArm64: Uint64(),
+  Abi.linuxIA32: Uint32(),
+  Abi.linuxX64: Uint64(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint64(),
+  Abi.macosArm64: Uint64(),
+  Abi.macosX64: Uint64(),
+  Abi.windowsArm64: Uint32(),
+  Abi.windowsIA32: Uint32(),
+  Abi.windowsX64: Uint32(),
+})
+class UnsignedLong extends AbiSpecificInteger {
+  const UnsignedLong();
+}
+
+/// The C `long long` type.
+///
+/// Typically a signed 64-bit integer.
+/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type.
+/// For an `unsigned long long`, use [UnsignedLongLong].
+///
+/// The [LongLong] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int64(),
+  Abi.androidArm64: Int64(),
+  Abi.androidIA32: Int64(),
+  Abi.androidX64: Int64(),
+  Abi.fuchsiaArm64: Int64(),
+  Abi.fuchsiaX64: Int64(),
+  Abi.iosArm: Int64(),
+  Abi.iosArm64: Int64(),
+  Abi.iosX64: Int64(),
+  Abi.linuxArm: Int64(),
+  Abi.linuxArm64: Int64(),
+  Abi.linuxIA32: Int64(),
+  Abi.linuxX64: Int64(),
+  Abi.linuxRiscv32: Int64(),
+  Abi.linuxRiscv64: Int64(),
+  Abi.macosArm64: Int64(),
+  Abi.macosX64: Int64(),
+  Abi.windowsArm64: Int64(),
+  Abi.windowsIA32: Int64(),
+  Abi.windowsX64: Int64(),
+})
+class LongLong extends AbiSpecificInteger {
+  const LongLong();
+}
+
+/// The C `unsigned long long` type.
+///
+/// Typically an unsigned 64-bit integer.
+/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type.
+/// For a signed `long long`, use [LongLong].
+///
+/// The [UnsignedLongLong] type is a native type, and should not be constructed
+/// in Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint64(),
+  Abi.androidArm64: Uint64(),
+  Abi.androidIA32: Uint64(),
+  Abi.androidX64: Uint64(),
+  Abi.fuchsiaArm64: Uint64(),
+  Abi.fuchsiaX64: Uint64(),
+  Abi.iosArm: Uint64(),
+  Abi.iosArm64: Uint64(),
+  Abi.iosX64: Uint64(),
+  Abi.linuxArm: Uint64(),
+  Abi.linuxArm64: Uint64(),
+  Abi.linuxIA32: Uint64(),
+  Abi.linuxX64: Uint64(),
+  Abi.linuxRiscv32: Uint64(),
+  Abi.linuxRiscv64: Uint64(),
+  Abi.macosArm64: Uint64(),
+  Abi.macosX64: Uint64(),
+  Abi.windowsArm64: Uint64(),
+  Abi.windowsIA32: Uint64(),
+  Abi.windowsX64: Uint64(),
+})
+class UnsignedLongLong extends AbiSpecificInteger {
+  const UnsignedLongLong();
+}
+
+/// The C `intptr_t` type.
+///
+/// The [IntPtr] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Int32(),
+  Abi.androidArm64: Int64(),
+  Abi.androidIA32: Int32(),
+  Abi.androidX64: Int64(),
+  Abi.fuchsiaArm64: Int64(),
+  Abi.fuchsiaX64: Int64(),
+  Abi.iosArm: Int32(),
+  Abi.iosArm64: Int64(),
+  Abi.iosX64: Int64(),
+  Abi.linuxArm: Int32(),
+  Abi.linuxArm64: Int64(),
+  Abi.linuxIA32: Int32(),
+  Abi.linuxX64: Int64(),
+  Abi.linuxRiscv32: Int32(),
+  Abi.linuxRiscv64: Int64(),
+  Abi.macosArm64: Int64(),
+  Abi.macosX64: Int64(),
+  Abi.windowsArm64: Int64(),
+  Abi.windowsIA32: Int32(),
+  Abi.windowsX64: Int64(),
+})
+class IntPtr extends AbiSpecificInteger {
+  const IntPtr();
+}
+
+/// The C `uintptr_t` type.
+///
+/// The [UintPtr] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint32(),
+  Abi.androidArm64: Uint64(),
+  Abi.androidIA32: Uint32(),
+  Abi.androidX64: Uint64(),
+  Abi.fuchsiaArm64: Uint64(),
+  Abi.fuchsiaX64: Uint64(),
+  Abi.iosArm: Uint32(),
+  Abi.iosArm64: Uint64(),
+  Abi.iosX64: Uint64(),
+  Abi.linuxArm: Uint32(),
+  Abi.linuxArm64: Uint64(),
+  Abi.linuxIA32: Uint32(),
+  Abi.linuxX64: Uint64(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint64(),
+  Abi.macosArm64: Uint64(),
+  Abi.macosX64: Uint64(),
+  Abi.windowsArm64: Uint64(),
+  Abi.windowsIA32: Uint32(),
+  Abi.windowsX64: Uint64(),
+})
+class UintPtr extends AbiSpecificInteger {
+  const UintPtr();
+}
+
+/// The C `size_t` type.
+///
+/// The [Size] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint32(),
+  Abi.androidArm64: Uint64(),
+  Abi.androidIA32: Uint32(),
+  Abi.androidX64: Uint64(),
+  Abi.fuchsiaArm64: Uint64(),
+  Abi.fuchsiaX64: Uint64(),
+  Abi.iosArm: Uint32(),
+  Abi.iosArm64: Uint64(),
+  Abi.iosX64: Uint64(),
+  Abi.linuxArm: Uint32(),
+  Abi.linuxArm64: Uint64(),
+  Abi.linuxIA32: Uint32(),
+  Abi.linuxX64: Uint64(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint64(),
+  Abi.macosArm64: Uint64(),
+  Abi.macosX64: Uint64(),
+  Abi.windowsArm64: Uint64(),
+  Abi.windowsIA32: Uint32(),
+  Abi.windowsX64: Uint64(),
+})
+class Size extends AbiSpecificInteger {
+  const Size();
+}
+
+/// The C `wchar_t` type.
+///
+/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as the
+/// defaults on the tested [Abi]s.
+///
+/// The [WChar] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint32(),
+  Abi.androidArm64: Uint32(),
+  Abi.androidIA32: Uint32(),
+  Abi.androidX64: Uint32(),
+  Abi.fuchsiaArm64: Uint32(),
+  Abi.fuchsiaX64: Int32(),
+  Abi.iosArm: Int32(),
+  Abi.iosArm64: Int32(),
+  Abi.iosX64: Int32(),
+  Abi.linuxArm: Uint32(),
+  Abi.linuxArm64: Uint32(),
+  Abi.linuxIA32: Int32(),
+  Abi.linuxX64: Int32(),
+  Abi.linuxRiscv32: Uint32(),
+  Abi.linuxRiscv64: Uint32(),
+  Abi.macosArm64: Int32(),
+  Abi.macosX64: Int32(),
+  Abi.windowsArm64: Uint16(),
+  Abi.windowsIA32: Uint16(),
+  Abi.windowsX64: Uint16(),
+})
+class WChar extends AbiSpecificInteger {
+  const WChar();
+}
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index eba4ea8..9a7afe2 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -20,6 +20,7 @@
 part 'native_type.dart';
 part 'allocation.dart';
 part 'annotations.dart';
+part 'c_type.dart';
 part 'dynamic_library.dart';
 part 'struct.dart';
 part 'union.dart';
@@ -448,50 +449,6 @@
   external Uint64List asTypedList(int length);
 }
 
-/// Extension on [Pointer] specialized for the type argument [IntPtr].
-extension IntPtrPointer on Pointer<IntPtr> {
-  /// The 32 or 64-bit two's complement integer at [address].
-  ///
-  /// On 32-bit platforms this is a 32-bit integer, and on 64-bit platforms
-  /// this is a 64-bit integer.
-  ///
-  /// On 32-bit platforms a Dart integer is truncated to 32 bits (as if by
-  /// `.toSigned(32)`) before being stored, and the 32-bit value is
-  /// sign-extended when it is loaded.
-  ///
-  /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit
-  /// platforms the [address] must be 8-byte aligned.
-  external int get value;
-
-  external void set value(int value);
-
-  /// The 32 or 64-bit two's complement integer at `address + (4 or 8) * index`.
-  ///
-  /// On 32-bit platforms this is a 32-bit integer, and on 64-bit platforms
-  /// this is a 64-bit integer.
-  ///
-  /// On 32-bit platforms a Dart integer is truncated to 32 bits (as if by
-  /// `.toSigned(32)`) before being stored, and the 32-bit value is
-  /// sign-extended when it is loaded.
-  ///
-  /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit
-  /// platforms the [address] must be 8-byte aligned.
-  external int operator [](int index);
-
-  /// The 32 or 64-bit two's complement integer at `address + (4 or 8) * index`.
-  ///
-  /// On 32-bit platforms this is a 32-bit integer, and on 64-bit platforms
-  /// this is a 64-bit integer.
-  ///
-  /// On 32-bit platforms a Dart integer is truncated to 32 bits (as if by
-  /// `.toSigned(32)`) before being stored, and the 32-bit value is
-  /// sign-extended when it is loaded.
-  ///
-  /// On 32-bit platforms the [address] must be 4-byte aligned, and on 64-bit
-  /// platforms the [address] must be 8-byte aligned.
-  external void operator []=(int index, int value);
-}
-
 /// Extension on [Pointer] specialized for the type argument [Float].
 extension FloatPointer on Pointer<Float> {
   /// The float at [address].
@@ -633,13 +590,6 @@
   external void operator []=(int index, int value);
 }
 
-/// Bounds checking indexing methods on [Array]s of [IntPtr].
-extension IntPtrArray on Array<IntPtr> {
-  external int operator [](int index);
-
-  external void operator []=(int index, int value);
-}
-
 /// Bounds checking indexing methods on [Array]s of [Float].
 extension FloatArray on Array<Float> {
   external double operator [](int index);
@@ -699,14 +649,20 @@
 
 /// Extension on [Pointer] specialized for the type argument [Struct].
 extension StructPointer<T extends Struct> on Pointer<T> {
-  /// Creates a reference to access the fields of this struct backed by native
-  /// memory at [address].
+  /// A Dart view of the struct referenced by this pointer.
   ///
+  /// Reading [ref] creates a reference accessing the fields of this struct
+  /// backed by native memory at [address].
   /// The [address] must be aligned according to the struct alignment rules of
   /// the platform.
   ///
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// Assigning to [ref] copies contents of the struct into the native memory
+  /// starting at [address].
+  ///
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T get ref;
+  external set ref(T value);
 
   /// Creates a reference to access the fields of this struct backed by native
   /// memory at `address + sizeOf<T>() * index`.
@@ -714,20 +670,34 @@
   /// The [address] must be aligned according to the struct alignment rules of
   /// the platform.
   ///
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T operator [](int index);
+
+  /// Copies the [value] struct into native memory, starting at
+  /// `address * sizeOf<T>() * index`.
+  ///
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
+  external void operator []=(int index, T value);
 }
 
 /// Extension on [Pointer] specialized for the type argument [Union].
 extension UnionPointer<T extends Union> on Pointer<T> {
-  /// Creates a reference to access the fields of this union backed by native
-  /// memory at [address].
+  /// A Dart view of the union referenced by this pointer.
   ///
+  /// Reading [ref] creates a reference accessing the fields of this union
+  /// backed by native memory at [address].
   /// The [address] must be aligned according to the union alignment rules of
   /// the platform.
   ///
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// Assigning to [ref] copies contents of the union into the native memory
+  /// starting at [address].
+  ///
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T get ref;
+  external set ref(T value);
 
   /// Creates a reference to access the fields of this union backed by native
   /// memory at `address + sizeOf<T>() * index`.
@@ -735,8 +705,16 @@
   /// The [address] must be aligned according to the union alignment rules of
   /// the platform.
   ///
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T operator [](int index);
+
+  /// Copies the [value] union into native memory, starting at
+  /// `address * sizeOf<T>() * index`.
+  ///
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
+  external void operator []=(int index, T value);
 }
 
 /// Extension on [Pointer] specialized for the type argument
@@ -764,13 +742,15 @@
 
 /// Bounds checking indexing methods on [Array]s of [Struct].
 extension StructArray<T extends Struct> on Array<T> {
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T operator [](int index);
 }
 
 /// Bounds checking indexing methods on [Array]s of [Union].
 extension UnionArray<T extends Union> on Array<T> {
-  /// This extension method must be invoked with a compile-time constant [T].
+  /// This extension method must be invoked on a receiver of type `Pointer<T>`
+  /// where `T` is a compile-time constant type.
   external T operator [](int index);
 }
 
diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni
index b725fe0..4197369 100644
--- a/sdk/lib/ffi/ffi_sources.gni
+++ b/sdk/lib/ffi/ffi_sources.gni
@@ -10,6 +10,7 @@
   "abi_specific.dart",
   "allocation.dart",
   "annotations.dart",
+  "c_type.dart",
   "dynamic_library.dart",
   "native_type.dart",
   "struct.dart",
diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart
index 217a68a..55a9f6d 100644
--- a/sdk/lib/ffi/native_type.dart
+++ b/sdk/lib/ffi/native_type.dart
@@ -98,14 +98,6 @@
   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
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 182872b..33e2611 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13989,6 +13989,41 @@
 
   int get scrollWidth => JS<num>('num', '#.scrollWidth', this).round();
 
+  /**
+   * Displays this element fullscreen.
+   *
+   * ## Other resources
+   *
+   * * [Fullscreen
+   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
+   *   from MDN.
+   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
+   */
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  Future<void> requestFullscreen([Map? options]) {
+    var retValue;
+    if (options != null) {
+      retValue = JS(
+          '',
+          '(#.requestFullscreen||#.webkitRequestFullscreen).call(#, #)',
+          this,
+          this,
+          this,
+          convertDartToNative_Dictionary(options));
+    } else {
+      retValue = JS(
+          '',
+          '(#.requestFullscreen||#.webkitRequestFullscreen).call(#)',
+          this,
+          this,
+          this);
+    }
+    if (retValue != null) return promiseToFuture(retValue);
+    return Future<void>.value();
+  }
+
   // To suppress missing implicit constructor warnings.
   factory Element._() {
     throw new UnsupportedError("Not supported");
@@ -14896,21 +14931,6 @@
 
   void setPointerCapture(int pointerId) native;
 
-  @JSName('webkitRequestFullscreen')
-  /**
-   * Displays this element fullscreen.
-   *
-   * ## Other resources
-   *
-   * * [Fullscreen
-   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
-   *   from MDN.
-   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
-   */
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  void requestFullscreen() native;
-
   // From ChildNode
 
   void after(Object nodes) native;
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index e26356c..1df1cc9 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -507,14 +507,10 @@
   }
 
   /**
-   * Checks to see if getDatabaseNames is supported by the current platform.
-   * TODO(terry): Should be able to always return false?
+   * Deprecated. Always returns `false`.
    */
-  bool get supportsDatabaseNames {
-    return supported &&
-        JS('bool', '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this,
-            this);
-  }
+  @Deprecated('No longer supported on modern browsers. Always returns false.')
+  bool get supportsDatabaseNames => false;
 
   // To suppress missing implicit constructor warnings.
   factory IdbFactory._() {
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index cbda1c3..dabd9f4 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -234,7 +234,7 @@
   /// with a [Directory] for the renamed directory.
   ///
   /// If [newPath] identifies an existing directory, then the behavior is
-  /// platform-specific. On all platforms, the future completes with an
+  /// platform-specific. On all platforms, the future completes with a
   /// [FileSystemException] if the existing directory is not empty. On POSIX
   /// systems, if [newPath] identifies an existing empty directory then that
   /// directory is deleted before this directory is renamed.
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 453f333..bf2058f 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -85,6 +85,12 @@
 ///
 /// Use this with care, as no asynchronous operations can be processed
 /// in a isolate while it is blocked in a [sleep] call.
+/// ```dart
+/// var duration = const Duration(seconds: 5);
+/// print('Start sleeping');
+/// sleep(duration);
+/// print('5 seconds has passed');
+/// ```
 void sleep(Duration duration) {
   int milliseconds = duration.inMilliseconds;
   if (milliseconds < 0) {
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index c59dc6f..8573ca4 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -32,7 +32,8 @@
         "uri": "collection/collection.dart",
         "patches": [
           "_internal/vm/lib/collection_patch.dart",
-          "_internal/vm/lib/compact_hash.dart"
+          "_internal/vm/lib/compact_hash.dart",
+          "_internal/vm/lib/hash_factories.dart"
         ]
       },
       "convert": {
@@ -154,27 +155,12 @@
     }
   },
   "dart2js": {
+    "include": [
+      {
+        "target": "_dart2js_common"
+      }
+    ],
     "libraries": {
-      "async": {
-        "uri": "async/async.dart",
-        "patches": "_internal/js_runtime/lib/async_patch.dart"
-      },
-      "collection": {
-        "uri": "collection/collection.dart",
-        "patches": "_internal/js_runtime/lib/collection_patch.dart"
-      },
-      "convert": {
-        "uri": "convert/convert.dart",
-        "patches": "_internal/js_runtime/lib/convert_patch.dart"
-      },
-      "core": {
-        "uri": "core/core.dart",
-        "patches": "_internal/js_runtime/lib/core_patch.dart"
-      },
-      "developer": {
-        "uri": "developer/developer.dart",
-        "patches": "_internal/js_runtime/lib/developer_patch.dart"
-      },
       "html": {
         "uri": "html/dart2js/html_dart2js.dart"
       },
@@ -184,44 +170,10 @@
       "indexed_db": {
         "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
       },
-      "_http": {
-        "uri": "_http/http.dart"
-      },
-      "io": {
-        "uri": "io/io.dart",
-        "patches": "_internal/js_runtime/lib/io_patch.dart",
-        "supported": false
-      },
-      "isolate": {
-        "uri": "isolate/isolate.dart",
-        "patches": "_internal/js_runtime/lib/isolate_patch.dart",
-        "supported": false
-      },
-      "js": {
-        "uri": "js/js.dart",
-        "patches": "_internal/js_runtime/lib/js_patch.dart"
-      },
       "_js": {
         "uri": "js/_js.dart",
         "patches": "js/_js_client.dart"
       },
-      "_js_annotations": {
-        "uri": "js/_js_annotations.dart"
-      },
-      "js_util": {
-        "uri": "js_util/js_util.dart"
-      },
-      "math": {
-        "uri": "math/math.dart",
-        "patches": "_internal/js_runtime/lib/math_patch.dart"
-      },
-      "typed_data": {
-        "uri": "typed_data/typed_data.dart",
-        "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
-      },
-      "_native_typed_data": {
-        "uri": "_internal/js_runtime/lib/native_typed_data.dart"
-      },
       "svg": {
         "uri": "svg/dart2js/svg_dart2js.dart"
       },
@@ -231,49 +183,25 @@
       "web_gl": {
         "uri": "web_gl/dart2js/web_gl_dart2js.dart"
       },
-      "_dart2js_runtime_metrics": {
-        "uri": "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
-      },
-      "_internal": {
-        "uri": "internal/internal.dart",
-        "patches": "_internal/js_runtime/lib/internal_patch.dart"
-      },
-      "_js_helper": {
-        "uri": "_internal/js_runtime/lib/js_helper.dart"
-      },
-      "_late_helper": {
-        "uri": "_internal/js_runtime/lib/late_helper.dart"
-      },
-      "_rti": {
-        "uri": "_internal/js_runtime/lib/rti.dart"
-      },
-      "_interceptors": {
-        "uri": "_internal/js_runtime/lib/interceptors.dart"
-      },
-      "_foreign_helper": {
-        "uri": "_internal/js_runtime/lib/foreign_helper.dart"
-      },
-      "_js_names": {
-        "uri": "_internal/js_runtime/lib/js_names.dart"
-      },
-      "_js_primitives": {
-        "uri": "_internal/js_runtime/lib/js_primitives.dart"
-      },
-      "_js_embedded_names": {
-        "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
-      },
-      "_async_await_error_codes": {
-        "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
-      },
-      "_recipe_syntax": {
-        "uri": "_internal/js_runtime/lib/shared/recipe_syntax.dart"
-      },
       "_metadata": {
         "uri": "html/html_common/metadata.dart"
       }
     }
   },
   "dart2js_server": {
+    "include": [
+      {
+        "target": "_dart2js_common"
+      }
+    ],
+    "libraries": {
+      "_js": {
+        "uri": "js/_js.dart",
+        "patches": "js/_js_server.dart"
+      }
+    }
+  },
+  "_dart2js_common": {
     "libraries": {
       "async": {
         "uri": "async/async.dart",
@@ -312,10 +240,6 @@
         "uri": "js/js.dart",
         "patches": "_internal/js_runtime/lib/js_patch.dart"
       },
-      "_js": {
-        "uri": "js/_js.dart",
-        "patches": "js/_js_server.dart"
-      },
       "_js_annotations": {
         "uri": "js/_js_annotations.dart"
       },
@@ -476,4 +400,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 812487a..dcf81c0 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -41,6 +41,7 @@
       patches:
         - "_internal/vm/lib/collection_patch.dart"
         - "_internal/vm/lib/compact_hash.dart"
+        - "_internal/vm/lib/hash_factories.dart"
 
     convert:
       uri: "convert/convert.dart"
@@ -152,27 +153,9 @@
       uri: "_internal/vm/bin/vmservice_io.dart"
 
 dart2js:
+  include:
+    - target: "_dart2js_common"
   libraries:
-    async:
-      uri: "async/async.dart"
-      patches: "_internal/js_runtime/lib/async_patch.dart"
-
-    collection:
-      uri: "collection/collection.dart"
-      patches: "_internal/js_runtime/lib/collection_patch.dart"
-
-    convert:
-      uri: "convert/convert.dart"
-      patches: "_internal/js_runtime/lib/convert_patch.dart"
-
-    core:
-      uri: "core/core.dart"
-      patches: "_internal/js_runtime/lib/core_patch.dart"
-
-    developer:
-      uri: "developer/developer.dart"
-      patches: "_internal/js_runtime/lib/developer_patch.dart"
-
     html:
       uri: "html/dart2js/html_dart2js.dart"
 
@@ -182,44 +165,10 @@
     indexed_db:
       uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
 
-    _http:
-      uri: "_http/http.dart"
-
-    io:
-      uri: "io/io.dart"
-      patches: "_internal/js_runtime/lib/io_patch.dart"
-      supported: false
-
-    isolate:
-      uri: "isolate/isolate.dart"
-      patches: "_internal/js_runtime/lib/isolate_patch.dart"
-      supported: false
-
-    js:
-      uri: "js/js.dart"
-      patches: "_internal/js_runtime/lib/js_patch.dart"
-
     _js:
       uri: "js/_js.dart"
       patches: "js/_js_client.dart"
 
-    _js_annotations:
-      uri: "js/_js_annotations.dart"
-
-    js_util:
-      uri: "js_util/js_util.dart"
-
-    math:
-      uri: "math/math.dart"
-      patches: "_internal/js_runtime/lib/math_patch.dart"
-
-    typed_data:
-      uri: "typed_data/typed_data.dart"
-      patches: "_internal/js_runtime/lib/typed_data_patch.dart"
-
-    _native_typed_data:
-      uri: "_internal/js_runtime/lib/native_typed_data.dart"
-
     svg:
       uri: "svg/dart2js/svg_dart2js.dart"
 
@@ -229,47 +178,18 @@
     web_gl:
       uri: "web_gl/dart2js/web_gl_dart2js.dart"
 
-    _dart2js_runtime_metrics:
-      uri: "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
-
-    _internal:
-      uri: "internal/internal.dart"
-      patches: "_internal/js_runtime/lib/internal_patch.dart"
-
-    _js_helper:
-      uri: "_internal/js_runtime/lib/js_helper.dart"
-
-    _late_helper:
-      uri: "_internal/js_runtime/lib/late_helper.dart"
-
-    _rti:
-      uri: "_internal/js_runtime/lib/rti.dart"
-
-    _interceptors:
-      uri: "_internal/js_runtime/lib/interceptors.dart"
-
-    _foreign_helper:
-      uri: "_internal/js_runtime/lib/foreign_helper.dart"
-
-    _js_names:
-      uri: "_internal/js_runtime/lib/js_names.dart"
-
-    _js_primitives:
-      uri: "_internal/js_runtime/lib/js_primitives.dart"
-
-    _js_embedded_names:
-      uri: "_internal/js_runtime/lib/shared/embedded_names.dart"
-
-    _async_await_error_codes:
-      uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
-
-    _recipe_syntax:
-      uri: "_internal/js_runtime/lib/shared/recipe_syntax.dart"
-
     _metadata:
       uri: "html/html_common/metadata.dart"
 
 dart2js_server:
+  include:
+    - target: "_dart2js_common"
+  libraries:
+    _js:
+      uri: "js/_js.dart"
+      patches: "js/_js_server.dart"
+
+_dart2js_common:
   libraries:
     async:
       uri: "async/async.dart"
@@ -308,10 +228,6 @@
       uri: "js/js.dart"
       patches: "_internal/js_runtime/lib/js_patch.dart"
 
-    _js:
-      uri: "js/_js.dart"
-      patches: "js/_js_server.dart"
-
     _js_annotations:
       uri: "js/_js_annotations.dart"
 
diff --git a/sdk/lib/math/random.dart b/sdk/lib/math/random.dart
index fd75e12..35fdd14 100644
--- a/sdk/lib/math/random.dart
+++ b/sdk/lib/math/random.dart
@@ -10,6 +10,24 @@
 /// not suitable for cryptographic purposes.
 ///
 /// Use the [Random.secure]() constructor for cryptographic purposes.
+///
+/// To create a non-negative random integer uniformly distributed in the range
+/// from 0, inclusive, to max, exclusive, use [nextInt(int max)].
+/// ```dart
+/// var intValue = Random().nextInt(10); // Value is >= 0 and < 10.
+/// intValue = Random().nextInt(100) + 50; // Value is >= 50 and < 150.
+/// ```
+/// To create a non-negative random floating point value uniformly distributed
+/// in the range from 0.0, inclusive, to 1.0, exclusive, use [nextDouble].
+/// ```dart
+/// var doubleValue = Random().nextDouble(); // Value is >= 0.0 and < 1.0.
+/// doubleValue = Random().nextDouble() * 256; // Value is >= 0.0 and < 256.0.
+/// ```
+/// To create a random Boolean value, use [nextBool].
+/// ```dart
+/// var boolValue = Random().nextBool(); // true or false, with equal chance.
+/// ```
+///
 abstract class Random {
   /// Creates a random number generator.
   ///
@@ -29,12 +47,29 @@
   ///
   /// Implementation note: The default implementation supports [max] values
   /// between 1 and (1<<32) inclusive.
+  ///
+  /// Example:
+  /// ```dart
+  /// var intValue = Random().nextInt(10); // Value is >= 0 and < 10.
+  /// intValue = Random().nextInt(100) + 50; // Value is >= 50 and < 150.
+  /// ```
   int nextInt(int max);
 
   /// Generates a non-negative random floating point value uniformly distributed
   /// in the range from 0.0, inclusive, to 1.0, exclusive.
+  ///
+  /// Example:
+  /// ```dart
+  /// var doubleValue = Random().nextDouble(); // Value is >= 0.0 and < 1.0.
+  /// doubleValue = Random().nextDouble() * 256; // Value is >= 0.0 and < 256.0.
+  /// ```
   double nextDouble();
 
   /// Generates a random boolean value.
+  ///
+  /// Example:
+  /// ```dart
+  /// var boolValue = Random().nextBool(); // true or false, with equal chance.
+  /// ```
   bool nextBool();
 }
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 5d07d41..2a67153 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -82,7 +82,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 16-bit aligned,
-  /// and contains [length] 16-bit integers.
+  /// and contains [length] 16-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not even, the last byte can't be part of the view.
@@ -103,7 +104,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 16-bit aligned,
-  /// and contains [length] 16-bit integers.
+  /// and contains [length] 16-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not even, the last byte can't be part of the view.
@@ -124,7 +126,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 32-bit aligned,
-  /// and contains [length] 32-bit integers.
+  /// and contains [length] 32-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not divisible by four, the last bytes can't be part
@@ -146,7 +149,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 32-bit aligned,
-  /// and contains [length] 32-bit integers.
+  /// and contains [length] 32-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not divisible by four, the last bytes can't be part
@@ -168,7 +172,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 64-bit aligned,
-  /// and contains [length] 64-bit integers.
+  /// and contains [length] 64-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not divisible by eight, the last bytes can't be part
@@ -190,7 +195,8 @@
   /// and vice versa.
   ///
   /// The viewed region start at [offsetInBytes], which must be 64-bit aligned,
-  /// and contains [length] 64-bit integers.
+  /// and contains [length] 64-bit integers with
+  /// the same endianness as the host ([Endian.host]).
   /// If [length] is omitted, the range extends as far towards the end of
   /// the buffer as possible -
   /// if [lengthInBytes] is not divisible by eight, the last bytes can't be part
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index 5af3cfd..ae16c86 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -549,7 +549,9 @@
       return encodeRpcError(message, kStreamAlreadySubscribed);
     }
     if (!_isAnyClientSubscribed(streamId)) {
-      if (!serviceStreams.contains(streamId) && !_vmListenStream(streamId)) {
+      final includePrivates = message.params['_includePrivateMembers'] == true;
+      if (!serviceStreams.contains(streamId) &&
+          !_vmListenStream(streamId, includePrivates)) {
         return encodeRpcError(message, kInvalidParams,
             details: "streamListen: invalid 'streamId' parameter: ${streamId}");
       }
@@ -831,7 +833,7 @@
 
 /// Subscribe to a service stream.
 @pragma("vm:external-name", "VMService_ListenStream")
-external bool _vmListenStream(String streamId);
+external bool _vmListenStream(String streamId, bool include_privates);
 
 /// Cancel a subscription to a service stream.
 @pragma("vm:external-name", "VMService_CancelStream")
diff --git a/tests/corelib/string_replace_all_common.dart b/tests/corelib/string_replace_all_common.dart
new file mode 100644
index 0000000..4bdbff0
--- /dev/null
+++ b/tests/corelib/string_replace_all_common.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+testAll(Pattern Function(Pattern) wrap) {
+  testReplaceAll(wrap);
+  testReplaceAllMapped(wrap);
+  testSplitMapJoin(wrap);
+}
+
+testReplaceAll(Pattern Function(Pattern) wrap) {
+  Expect.equals("aXXcaXXdae", "abcabdae".replaceAll(wrap("b"), "XX"));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("XXbcXXbdXXe", "abcabdae".replaceAll(wrap("a"), "XX"));
+
+  // Test with the replaced string at the end.
+  Expect.equals("abcabdaXX", "abcabdae".replaceAll(wrap("e"), "XX"));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("abcabdae", "abcabdae".replaceAll(wrap("f"), "XX"));
+
+  // Test when the string to change is the empty string.
+  Expect.equals("", "".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("fro", "fro".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is the replaced string.
+  Expect.equals("to", "from".replaceAll(wrap("from"), "to"));
+
+  // Test when matches are adjacent
+  Expect.equals("toto", "fromfrom".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is the replacement string.
+  Expect.equals("to", "to".replaceAll(wrap("from"), "to"));
+
+  // Test replacing by the empty string.
+  Expect.equals("bcbde", "abcabdae".replaceAll(wrap("a"), ""));
+  Expect.equals("AB", "AfromB".replaceAll(wrap("from"), ""));
+
+  // Test changing the empty string.
+  Expect.equals("to", "".replaceAll(wrap(""), "to"));
+
+  // Test replacing the empty string.
+  Expect.equals("toAtoBtoCto", "ABC".replaceAll(wrap(""), "to"));
+
+  // Pattern strings containing RegExp metacharacters - these are not
+  // interpreted as RegExps.
+  Expect.equals(r"$$", "||".replaceAll(wrap("|"), r"$"));
+  Expect.equals(r"$$$$", "||".replaceAll(wrap("|"), r"$$"));
+  Expect.equals(r"x$|x", "x|.|x".replaceAll(wrap("|."), r"$"));
+  Expect.equals(r"$$", "..".replaceAll(wrap("."), r"$"));
+  Expect.equals(r"[$$$$]", "[..]".replaceAll(wrap("."), r"$$"));
+  Expect.equals(r"[$]", "[..]".replaceAll(wrap(".."), r"$"));
+  Expect.equals(r"$$", r"\\".replaceAll(wrap(r"\"), r"$"));
+}
+
+testReplaceAllMapped(Pattern Function(Pattern) wrap) {
+  String mark(Match m) => "[${m[0]}]";
+  Expect.equals("a[b]ca[b]dae", "abcabdae".replaceAllMapped(wrap("b"), mark));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".replaceAllMapped(wrap("a"), mark));
+
+  // Test with the replaced string at the end.
+  Expect.equals("abcabda[e]", "abcabdae".replaceAllMapped(wrap("e"), mark));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("abcabdae", "abcabdae".replaceAllMapped(wrap("f"), mark));
+
+  // Test when the string to change is the empty string.
+  Expect.equals("", "".replaceAllMapped(wrap("from"), mark));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("fro", "fro".replaceAllMapped(wrap("from"), mark));
+
+  // Test when matches are adjacent
+  Expect.equals(
+      "[from][from]", "fromfrom".replaceAllMapped(wrap("from"), mark));
+
+  // Test replacing by the empty string.
+  Expect.equals("bcbde", "abcabdae".replaceAllMapped(wrap("a"), (m) => ""));
+  Expect.equals("AB", "AfromB".replaceAllMapped(wrap("from"), (m) => ""));
+
+  // Test changing the empty string.
+  Expect.equals("[]", "".replaceAllMapped(wrap(""), mark));
+
+  // Test replacing the empty string.
+  Expect.equals("[]A[]B[]C[]", "ABC".replaceAllMapped(wrap(""), mark));
+}
+
+testSplitMapJoin(Pattern Function(Pattern) wrap) {
+  String mark(Match m) => "[${m[0]}]";
+  String rest(String s) => "<${s}>";
+
+  Expect.equals("<a>[b]<ca>[b]<dae>",
+      "abcabdae".splitMapJoin(wrap("b"), onMatch: mark, onNonMatch: rest));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("<>[a]<bc>[a]<bd>[a]<e>",
+      "abcabdae".splitMapJoin(wrap("a"), onMatch: mark, onNonMatch: rest));
+
+  // Test with the replaced string at the end.
+  Expect.equals("<abcabda>[e]<>",
+      "abcabdae".splitMapJoin(wrap("e"), onMatch: mark, onNonMatch: rest));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("<abcabdae>",
+      "abcabdae".splitMapJoin(wrap("f"), onMatch: mark, onNonMatch: rest));
+
+  // Test when the string to change is the empty string.
+  Expect.equals(
+      "<>", "".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("<fro>",
+      "fro".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test when matches are adjacent
+  Expect.equals("<>[from]<>[from]<>",
+      "fromfrom".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test changing the empty string.
+  Expect.equals(
+      "<>[]<>", "".splitMapJoin(wrap(""), onMatch: mark, onNonMatch: rest));
+
+  // Test replacing the empty string.
+  Expect.equals("<>[]<A>[]<B>[]<C>[]<>",
+      "ABC".splitMapJoin(wrap(""), onMatch: mark, onNonMatch: rest));
+
+  // Test with only onMatch.
+  Expect.equals(
+      "[a]bc[a]bd[a]e", "abcabdae".splitMapJoin(wrap("a"), onMatch: mark));
+
+  // Test with only onNonMatch
+  Expect.equals(
+      "<>a<bc>a<bd>a<e>", "abcabdae".splitMapJoin(wrap("a"), onNonMatch: rest));
+}
diff --git a/tests/corelib/string_replace_all_pattern_test.dart b/tests/corelib/string_replace_all_pattern_test.dart
new file mode 100644
index 0000000..0ca86e7
--- /dev/null
+++ b/tests/corelib/string_replace_all_pattern_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "string_replace_all_common.dart";
+
+main() {
+  testAll(Wrapper.wrap);
+}
+
+/// A wrapper that is not recognizable as a String or RegExp.
+class Wrapper implements Pattern {
+  final Pattern _pattern;
+  Wrapper(this._pattern);
+
+  static Pattern wrap(Pattern p) => Wrapper(p);
+
+  Iterable<Match> allMatches(String string, [int start = 0]) =>
+      _pattern.allMatches(string, start);
+
+  Match? matchAsPrefix(String string, [int start = 0]) =>
+      _pattern.matchAsPrefix(string, start);
+
+  String toString() => "Wrap($_pattern)";
+}
diff --git a/tests/corelib/string_replace_all_test.dart b/tests/corelib/string_replace_all_test.dart
index 548ad62..b6eb43b 100644
--- a/tests/corelib/string_replace_all_test.dart
+++ b/tests/corelib/string_replace_all_test.dart
@@ -1,140 +1,9 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
 // for details. All 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";
-
-testReplaceAll() {
-  Expect.equals("aXXcaXXdae", "abcabdae".replaceAll("b", "XX"));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("XXbcXXbdXXe", "abcabdae".replaceAll("a", "XX"));
-
-  // Test with the replaced string at the end.
-  Expect.equals("abcabdaXX", "abcabdae".replaceAll("e", "XX"));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("abcabdae", "abcabdae".replaceAll("f", "XX"));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("", "".replaceAll("from", "to"));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals("fro", "fro".replaceAll("from", "to"));
-
-  // Test when the string to change is the replaced string.
-  Expect.equals("to", "from".replaceAll("from", "to"));
-
-  // Test when matches are adjacent
-  Expect.equals("toto", "fromfrom".replaceAll("from", "to"));
-
-  // Test when the string to change is the replacement string.
-  Expect.equals("to", "to".replaceAll("from", "to"));
-
-  // Test replacing by the empty string.
-  Expect.equals("bcbde", "abcabdae".replaceAll("a", ""));
-  Expect.equals("AB", "AfromB".replaceAll("from", ""));
-
-  // Test changing the empty string.
-  Expect.equals("to", "".replaceAll("", "to"));
-
-  // Test replacing the empty string.
-  Expect.equals("toAtoBtoCto", "ABC".replaceAll("", "to"));
-
-  // Pattern strings containing RegExp metacharacters - these are not
-  // interpreted as RegExps.
-  Expect.equals(r"$$", "||".replaceAll("|", r"$"));
-  Expect.equals(r"$$$$", "||".replaceAll("|", r"$$"));
-  Expect.equals(r"x$|x", "x|.|x".replaceAll("|.", r"$"));
-  Expect.equals(r"$$", "..".replaceAll(".", r"$"));
-  Expect.equals(r"[$$$$]", "[..]".replaceAll(".", r"$$"));
-  Expect.equals(r"[$]", "[..]".replaceAll("..", r"$"));
-  Expect.equals(r"$$", r"\\".replaceAll(r"\", r"$"));
-}
-
-testReplaceAllMapped() {
-  String mark(Match m) => "[${m[0]}]";
-  Expect.equals("a[b]ca[b]dae", "abcabdae".replaceAllMapped("b", mark));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".replaceAllMapped("a", mark));
-
-  // Test with the replaced string at the end.
-  Expect.equals("abcabda[e]", "abcabdae".replaceAllMapped("e", mark));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("abcabdae", "abcabdae".replaceAllMapped("f", mark));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("", "".replaceAllMapped("from", mark));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals("fro", "fro".replaceAllMapped("from", mark));
-
-  // Test when matches are adjacent
-  Expect.equals("[from][from]", "fromfrom".replaceAllMapped("from", mark));
-
-  // Test replacing by the empty string.
-  Expect.equals("bcbde", "abcabdae".replaceAllMapped("a", (m) => ""));
-  Expect.equals("AB", "AfromB".replaceAllMapped("from", (m) => ""));
-
-  // Test changing the empty string.
-  Expect.equals("[]", "".replaceAllMapped("", mark));
-
-  // Test replacing the empty string.
-  Expect.equals("[]A[]B[]C[]", "ABC".replaceAllMapped("", mark));
-}
-
-testSplitMapJoin() {
-  String mark(Match m) => "[${m[0]}]";
-  String wrap(String s) => "<${s}>";
-
-  Expect.equals("<a>[b]<ca>[b]<dae>",
-      "abcabdae".splitMapJoin("b", onMatch: mark, onNonMatch: wrap));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("<>[a]<bc>[a]<bd>[a]<e>",
-      "abcabdae".splitMapJoin("a", onMatch: mark, onNonMatch: wrap));
-
-  // Test with the replaced string at the end.
-  Expect.equals("<abcabda>[e]<>",
-      "abcabdae".splitMapJoin("e", onMatch: mark, onNonMatch: wrap));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("<abcabdae>",
-      "abcabdae".splitMapJoin("f", onMatch: mark, onNonMatch: wrap));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("<>", "".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals(
-      "<fro>", "fro".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test when matches are adjacent
-  Expect.equals("<>[from]<>[from]<>",
-      "fromfrom".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test changing the empty string.
-  Expect.equals("<>[]<>", "".splitMapJoin("", onMatch: mark, onNonMatch: wrap));
-
-  // Test replacing the empty string.
-  Expect.equals("<>[]<A>[]<B>[]<C>[]<>",
-      "ABC".splitMapJoin("", onMatch: mark, onNonMatch: wrap));
-
-  // Test with only onMatch.
-  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".splitMapJoin("a", onMatch: mark));
-
-  // Test with only onNonMatch
-  Expect.equals(
-      "<>a<bc>a<bd>a<e>", "abcabdae".splitMapJoin("a", onNonMatch: wrap));
-}
+import "string_replace_all_common.dart";
 
 main() {
-  testReplaceAll();
-  testReplaceAllMapped();
-  testSplitMapJoin();
+  testAll((pattern) => pattern); // unwrapped
 }
diff --git a/tests/corelib_2/string_replace_all_common.dart b/tests/corelib_2/string_replace_all_common.dart
new file mode 100644
index 0000000..780761c
--- /dev/null
+++ b/tests/corelib_2/string_replace_all_common.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import "package:expect/expect.dart";
+
+testAll(Pattern Function(Pattern) wrap) {
+  testReplaceAll(wrap);
+  testReplaceAllMapped(wrap);
+  testSplitMapJoin(wrap);
+}
+
+testReplaceAll(Pattern Function(Pattern) wrap) {
+  Expect.equals("aXXcaXXdae", "abcabdae".replaceAll(wrap("b"), "XX"));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("XXbcXXbdXXe", "abcabdae".replaceAll(wrap("a"), "XX"));
+
+  // Test with the replaced string at the end.
+  Expect.equals("abcabdaXX", "abcabdae".replaceAll(wrap("e"), "XX"));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("abcabdae", "abcabdae".replaceAll(wrap("f"), "XX"));
+
+  // Test when the string to change is the empty string.
+  Expect.equals("", "".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("fro", "fro".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is the replaced string.
+  Expect.equals("to", "from".replaceAll(wrap("from"), "to"));
+
+  // Test when matches are adjacent
+  Expect.equals("toto", "fromfrom".replaceAll(wrap("from"), "to"));
+
+  // Test when the string to change is the replacement string.
+  Expect.equals("to", "to".replaceAll(wrap("from"), "to"));
+
+  // Test replacing by the empty string.
+  Expect.equals("bcbde", "abcabdae".replaceAll(wrap("a"), ""));
+  Expect.equals("AB", "AfromB".replaceAll(wrap("from"), ""));
+
+  // Test changing the empty string.
+  Expect.equals("to", "".replaceAll(wrap(""), "to"));
+
+  // Test replacing the empty string.
+  Expect.equals("toAtoBtoCto", "ABC".replaceAll(wrap(""), "to"));
+
+  // Pattern strings containing RegExp metacharacters - these are not
+  // interpreted as RegExps.
+  Expect.equals(r"$$", "||".replaceAll(wrap("|"), r"$"));
+  Expect.equals(r"$$$$", "||".replaceAll(wrap("|"), r"$$"));
+  Expect.equals(r"x$|x", "x|.|x".replaceAll(wrap("|."), r"$"));
+  Expect.equals(r"$$", "..".replaceAll(wrap("."), r"$"));
+  Expect.equals(r"[$$$$]", "[..]".replaceAll(wrap("."), r"$$"));
+  Expect.equals(r"[$]", "[..]".replaceAll(wrap(".."), r"$"));
+  Expect.equals(r"$$", r"\\".replaceAll(wrap(r"\"), r"$"));
+}
+
+testReplaceAllMapped(Pattern Function(Pattern) wrap) {
+  String mark(Match m) => "[${m[0]}]";
+  Expect.equals("a[b]ca[b]dae", "abcabdae".replaceAllMapped(wrap("b"), mark));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".replaceAllMapped(wrap("a"), mark));
+
+  // Test with the replaced string at the end.
+  Expect.equals("abcabda[e]", "abcabdae".replaceAllMapped(wrap("e"), mark));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("abcabdae", "abcabdae".replaceAllMapped(wrap("f"), mark));
+
+  // Test when the string to change is the empty string.
+  Expect.equals("", "".replaceAllMapped(wrap("from"), mark));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("fro", "fro".replaceAllMapped(wrap("from"), mark));
+
+  // Test when matches are adjacent
+  Expect.equals(
+      "[from][from]", "fromfrom".replaceAllMapped(wrap("from"), mark));
+
+  // Test replacing by the empty string.
+  Expect.equals("bcbde", "abcabdae".replaceAllMapped(wrap("a"), (m) => ""));
+  Expect.equals("AB", "AfromB".replaceAllMapped(wrap("from"), (m) => ""));
+
+  // Test changing the empty string.
+  Expect.equals("[]", "".replaceAllMapped(wrap(""), mark));
+
+  // Test replacing the empty string.
+  Expect.equals("[]A[]B[]C[]", "ABC".replaceAllMapped(wrap(""), mark));
+}
+
+testSplitMapJoin(Pattern Function(Pattern) wrap) {
+  String mark(Match m) => "[${m[0]}]";
+  String rest(String s) => "<${s}>";
+
+  Expect.equals("<a>[b]<ca>[b]<dae>",
+      "abcabdae".splitMapJoin(wrap("b"), onMatch: mark, onNonMatch: rest));
+
+  // Test with the replaced string at the beginning.
+  Expect.equals("<>[a]<bc>[a]<bd>[a]<e>",
+      "abcabdae".splitMapJoin(wrap("a"), onMatch: mark, onNonMatch: rest));
+
+  // Test with the replaced string at the end.
+  Expect.equals("<abcabda>[e]<>",
+      "abcabdae".splitMapJoin(wrap("e"), onMatch: mark, onNonMatch: rest));
+
+  // Test when there are no occurence of the string to replace.
+  Expect.equals("<abcabdae>",
+      "abcabdae".splitMapJoin(wrap("f"), onMatch: mark, onNonMatch: rest));
+
+  // Test when the string to change is the empty string.
+  Expect.equals(
+      "<>", "".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test when the string to change is a substring of the string to
+  // replace.
+  Expect.equals("<fro>",
+      "fro".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test when matches are adjacent
+  Expect.equals("<>[from]<>[from]<>",
+      "fromfrom".splitMapJoin(wrap("from"), onMatch: mark, onNonMatch: rest));
+
+  // Test changing the empty string.
+  Expect.equals(
+      "<>[]<>", "".splitMapJoin(wrap(""), onMatch: mark, onNonMatch: rest));
+
+  // Test replacing the empty string.
+  Expect.equals("<>[]<A>[]<B>[]<C>[]<>",
+      "ABC".splitMapJoin(wrap(""), onMatch: mark, onNonMatch: rest));
+
+  // Test with only onMatch.
+  Expect.equals(
+      "[a]bc[a]bd[a]e", "abcabdae".splitMapJoin(wrap("a"), onMatch: mark));
+
+  // Test with only onNonMatch
+  Expect.equals(
+      "<>a<bc>a<bd>a<e>", "abcabdae".splitMapJoin(wrap("a"), onNonMatch: rest));
+}
diff --git a/tests/corelib_2/string_replace_all_pattern_test.dart b/tests/corelib_2/string_replace_all_pattern_test.dart
new file mode 100644
index 0000000..10827c9
--- /dev/null
+++ b/tests/corelib_2/string_replace_all_pattern_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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 = 2.9
+
+import "string_replace_all_common.dart";
+
+main() {
+  testAll(Wrapper.wrap);
+}
+
+/// A wrapper that is not recognizable as a String or RegExp.
+class Wrapper implements Pattern {
+  final Pattern _pattern;
+  Wrapper(this._pattern);
+
+  static Pattern wrap(Pattern p) => Wrapper(p);
+
+  Iterable<Match> allMatches(String string, [int start = 0]) =>
+      _pattern.allMatches(string, start);
+
+  Match matchAsPrefix(String string, [int start = 0]) =>
+      _pattern.matchAsPrefix(string, start);
+
+  String toString() => "Wrap($_pattern)";
+}
diff --git a/tests/corelib_2/string_replace_all_test.dart b/tests/corelib_2/string_replace_all_test.dart
index e4e340b..9d43fb7 100644
--- a/tests/corelib_2/string_replace_all_test.dart
+++ b/tests/corelib_2/string_replace_all_test.dart
@@ -1,142 +1,11 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
 // for 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 = 2.9
 
-import "package:expect/expect.dart";
-
-testReplaceAll() {
-  Expect.equals("aXXcaXXdae", "abcabdae".replaceAll("b", "XX"));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("XXbcXXbdXXe", "abcabdae".replaceAll("a", "XX"));
-
-  // Test with the replaced string at the end.
-  Expect.equals("abcabdaXX", "abcabdae".replaceAll("e", "XX"));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("abcabdae", "abcabdae".replaceAll("f", "XX"));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("", "".replaceAll("from", "to"));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals("fro", "fro".replaceAll("from", "to"));
-
-  // Test when the string to change is the replaced string.
-  Expect.equals("to", "from".replaceAll("from", "to"));
-
-  // Test when matches are adjacent
-  Expect.equals("toto", "fromfrom".replaceAll("from", "to"));
-
-  // Test when the string to change is the replacement string.
-  Expect.equals("to", "to".replaceAll("from", "to"));
-
-  // Test replacing by the empty string.
-  Expect.equals("bcbde", "abcabdae".replaceAll("a", ""));
-  Expect.equals("AB", "AfromB".replaceAll("from", ""));
-
-  // Test changing the empty string.
-  Expect.equals("to", "".replaceAll("", "to"));
-
-  // Test replacing the empty string.
-  Expect.equals("toAtoBtoCto", "ABC".replaceAll("", "to"));
-
-  // Pattern strings containing RegExp metacharacters - these are not
-  // interpreted as RegExps.
-  Expect.equals(r"$$", "||".replaceAll("|", r"$"));
-  Expect.equals(r"$$$$", "||".replaceAll("|", r"$$"));
-  Expect.equals(r"x$|x", "x|.|x".replaceAll("|.", r"$"));
-  Expect.equals(r"$$", "..".replaceAll(".", r"$"));
-  Expect.equals(r"[$$$$]", "[..]".replaceAll(".", r"$$"));
-  Expect.equals(r"[$]", "[..]".replaceAll("..", r"$"));
-  Expect.equals(r"$$", r"\\".replaceAll(r"\", r"$"));
-}
-
-testReplaceAllMapped() {
-  String mark(Match m) => "[${m[0]}]";
-  Expect.equals("a[b]ca[b]dae", "abcabdae".replaceAllMapped("b", mark));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".replaceAllMapped("a", mark));
-
-  // Test with the replaced string at the end.
-  Expect.equals("abcabda[e]", "abcabdae".replaceAllMapped("e", mark));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("abcabdae", "abcabdae".replaceAllMapped("f", mark));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("", "".replaceAllMapped("from", mark));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals("fro", "fro".replaceAllMapped("from", mark));
-
-  // Test when matches are adjacent
-  Expect.equals("[from][from]", "fromfrom".replaceAllMapped("from", mark));
-
-  // Test replacing by the empty string.
-  Expect.equals("bcbde", "abcabdae".replaceAllMapped("a", (m) => ""));
-  Expect.equals("AB", "AfromB".replaceAllMapped("from", (m) => ""));
-
-  // Test changing the empty string.
-  Expect.equals("[]", "".replaceAllMapped("", mark));
-
-  // Test replacing the empty string.
-  Expect.equals("[]A[]B[]C[]", "ABC".replaceAllMapped("", mark));
-}
-
-testSplitMapJoin() {
-  String mark(Match m) => "[${m[0]}]";
-  String wrap(String s) => "<${s}>";
-
-  Expect.equals("<a>[b]<ca>[b]<dae>",
-      "abcabdae".splitMapJoin("b", onMatch: mark, onNonMatch: wrap));
-
-  // Test with the replaced string at the beginning.
-  Expect.equals("<>[a]<bc>[a]<bd>[a]<e>",
-      "abcabdae".splitMapJoin("a", onMatch: mark, onNonMatch: wrap));
-
-  // Test with the replaced string at the end.
-  Expect.equals("<abcabda>[e]<>",
-      "abcabdae".splitMapJoin("e", onMatch: mark, onNonMatch: wrap));
-
-  // Test when there are no occurence of the string to replace.
-  Expect.equals("<abcabdae>",
-      "abcabdae".splitMapJoin("f", onMatch: mark, onNonMatch: wrap));
-
-  // Test when the string to change is the empty string.
-  Expect.equals("<>", "".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test when the string to change is a substring of the string to
-  // replace.
-  Expect.equals(
-      "<fro>", "fro".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test when matches are adjacent
-  Expect.equals("<>[from]<>[from]<>",
-      "fromfrom".splitMapJoin("from", onMatch: mark, onNonMatch: wrap));
-
-  // Test changing the empty string.
-  Expect.equals("<>[]<>", "".splitMapJoin("", onMatch: mark, onNonMatch: wrap));
-
-  // Test replacing the empty string.
-  Expect.equals("<>[]<A>[]<B>[]<C>[]<>",
-      "ABC".splitMapJoin("", onMatch: mark, onNonMatch: wrap));
-
-  // Test with only onMatch.
-  Expect.equals("[a]bc[a]bd[a]e", "abcabdae".splitMapJoin("a", onMatch: mark));
-
-  // Test with only onNonMatch
-  Expect.equals(
-      "<>a<bc>a<bd>a<e>", "abcabdae".splitMapJoin("a", onNonMatch: wrap));
-}
+import "string_replace_all_common.dart";
 
 main() {
-  testReplaceAll();
-  testReplaceAllMapped();
-  testSplitMapJoin();
+  testAll((pattern) => pattern); // unwrapped
 }
diff --git a/tests/ffi/abi_specific_int_test.dart b/tests/ffi/abi_specific_int_test.dart
index 266655c..cea45b1 100644
--- a/tests/ffi/abi_specific_int_test.dart
+++ b/tests/ffi/abi_specific_int_test.dart
@@ -8,8 +8,6 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
-import 'abi_specific_ints.dart';
-
 void main() {
   testSizeOf();
   testStoreLoad();
diff --git a/tests/ffi/abi_specific_ints.dart b/tests/ffi/abi_specific_ints.dart
deleted file mode 100644
index 94e05a4..0000000
--- a/tests/ffi/abi_specific_ints.dart
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. 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';
-
-// TODO(dacoharkes): These should move to `package:ffi`.
-
-// `int` in C.
-typedef Int = Int32;
-
-// `unsigned int` in C.
-typedef UnsignedInt = Uint32;
-
-// `size_t` in C.
-typedef Size = UintPtr;
-
-// `ssize_t` in C.
-typedef SSize = IntPtr;
-
-// `off_t` in C.
-typedef Off = Long;
-
-/// Represents a native unsigned pointer-sized integer in C.
-///
-/// [UintPtr] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint64(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint64(),
-})
-class UintPtr extends AbiSpecificInteger {
-  const UintPtr();
-}
-
-/// `long` in C.
-///
-/// [Long] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Int32(),
-  Abi.androidArm64: Int64(),
-  Abi.androidIA32: Int32(),
-  Abi.androidX64: Int64(),
-  Abi.fuchsiaArm64: Int64(),
-  Abi.fuchsiaX64: Int64(),
-  Abi.iosArm: Int32(),
-  Abi.iosArm64: Int64(),
-  Abi.iosX64: Int64(),
-  Abi.linuxArm: Int32(),
-  Abi.linuxArm64: Int64(),
-  Abi.linuxIA32: Int32(),
-  Abi.linuxX64: Int64(),
-  Abi.macosArm64: Int64(),
-  Abi.macosX64: Int64(),
-  Abi.windowsArm64: Int32(),
-  Abi.windowsIA32: Int32(),
-  Abi.windowsX64: Int32(),
-})
-class Long extends AbiSpecificInteger {
-  const Long();
-}
-
-/// `unsigned long` in C.
-///
-/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint32(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint32(),
-})
-class UnsignedLong extends AbiSpecificInteger {
-  const UnsignedLong();
-}
-
-/// `wchar_t` in C.
-///
-/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an
-/// unsigned integer.
-///
-/// [WChar] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint32(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint32(),
-  Abi.fuchsiaArm64: Uint32(),
-  Abi.fuchsiaX64: Uint32(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint32(),
-  Abi.iosX64: Uint32(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint32(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint32(),
-  Abi.macosArm64: Uint32(),
-  Abi.macosX64: Uint32(),
-  Abi.windowsArm64: Uint16(),
-  Abi.windowsIA32: Uint16(),
-  Abi.windowsX64: Uint16(),
-})
-class WChar extends AbiSpecificInteger {
-  const WChar();
-}
diff --git a/tests/ffi/c_types_test.dart b/tests/ffi/c_types_test.dart
index d423c2c..c132f3b 100644
--- a/tests/ffi/c_types_test.dart
+++ b/tests/ffi/c_types_test.dart
@@ -7,11 +7,11 @@
 // SharedObjects=ffi_test_functions
 
 import 'dart:ffi';
-
-import "package:expect/expect.dart";
 import 'dart:io' show Platform;
 
-import 'abi_specific_ints.dart';
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
 import 'ffi_test_helpers.dart';
 
 void main() {
@@ -20,62 +20,156 @@
   testIntAssumptions();
   testSizeTAssumptions();
   testLongAssumptions();
-  testOffTAssumptions();
   testWCharTAssumptions();
 }
 
 class CType {
   final int ffiSize;
+  final int Function(Pointer)? ffiLoad;
   final String modifier;
   final String type;
+  final String type2;
 
-  CType(this.ffiSize, this.type, [this.modifier = ""]);
+  CType(this.ffiSize, this.type,
+      {this.type2 = '', this.modifier = '', this.ffiLoad});
 
-  String get cRepresentation => "$modifier $type".trim();
+  String get cRepresentation => '$modifier $type $type2'.trim();
 
-  String get _getSizeName => "FfiSizeOf_$modifier\_$type";
+  String get _getSizeName => 'FfiSizeOf_$modifier\_$type\_$type2';
+
+  String get _getSignName => 'FfiSignOf_$modifier\_$type\_$type2';
 
   int Function() get sizeFunction => ffiTestFunctions
       .lookupFunction<Uint64 Function(), int Function()>(_getSizeName);
 
+  int Function() get signFunction => ffiTestFunctions
+      .lookupFunction<Uint64 Function(), int Function()>(_getSignName);
+
   int get size => sizeFunction();
 
+  bool get isSigned => signFunction() != 0;
+
+  bool? get ffiIsSigned {
+    final ffiLoad_ = ffiLoad;
+    if (ffiLoad_ == null) {
+      return null;
+    }
+    assert(size < 8);
+    return using((Arena arena) {
+      final p = arena<Int64>()..value = -1;
+      return ffiLoad_(p) < 0;
+    });
+  }
+
   String toString() => cRepresentation;
 }
 
-final intptr_t = CType(sizeOf<IntPtr>(), "intptr_t");
-final uintptr_t = CType(sizeOf<UintPtr>(), "uintptr_t");
-final int_ = CType(sizeOf<Int>(), "int");
-final uint = CType(sizeOf<UnsignedInt>(), "int", "unsigned");
-final long = CType(sizeOf<Long>(), "long");
-final ulong = CType(sizeOf<UnsignedLong>(), "long", "unsigned");
-final wchar_t = CType(sizeOf<WChar>(), "wchar_t");
-final size_t = CType(sizeOf<Size>(), "size_t");
-final ssize_t = CType(sizeOf<SSize>(), "ssize_t");
-final off_t = CType(sizeOf<Off>(), "off_t");
+final uchar = CType(
+  sizeOf<UnsignedChar>(),
+  'char',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedChar>().value,
+);
+final schar = CType(
+  sizeOf<SignedChar>(),
+  'char',
+  modifier: 'signed',
+  ffiLoad: (Pointer p) => p.cast<SignedChar>().value,
+);
+final short = CType(
+  sizeOf<Short>(),
+  'short',
+  ffiLoad: (Pointer p) => p.cast<Short>().value,
+);
+final ushort = CType(
+  sizeOf<UnsignedShort>(),
+  'short',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedShort>().value,
+);
+final int_ = CType(
+  sizeOf<Int>(),
+  'int',
+  ffiLoad: (Pointer p) => p.cast<Int>().value,
+);
+final uint = CType(
+  sizeOf<UnsignedInt>(),
+  'int',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedInt>().value,
+);
+final long = CType(
+  sizeOf<Long>(),
+  'long',
+);
+final ulong = CType(
+  sizeOf<UnsignedLong>(),
+  'long',
+  modifier: 'unsigned',
+);
+final longlong = CType(
+  sizeOf<LongLong>(),
+  'long',
+  type2: 'long',
+);
+final ulonglong = CType(
+  sizeOf<UnsignedLongLong>(),
+  'long',
+  type2: 'long',
+  modifier: 'unsigned',
+);
+final intptr_t = CType(
+  sizeOf<IntPtr>(),
+  'intptr_t',
+);
+final uintptr_t = CType(
+  sizeOf<UintPtr>(),
+  'uintptr_t',
+);
+final size_t = CType(
+  sizeOf<Size>(),
+  'size_t',
+);
+final wchar_t = CType(
+  sizeOf<WChar>(),
+  'wchar_t',
+  ffiLoad: (Pointer p) => p.cast<WChar>().value,
+);
 
 final cTypes = [
-  intptr_t,
-  uintptr_t,
+  uchar,
+  schar,
+  short,
+  ushort,
   int_,
   uint,
   long,
   ulong,
-  wchar_t,
+  longlong,
+  ulonglong,
+  intptr_t,
+  uintptr_t,
   size_t,
-  ssize_t,
-  off_t
+  wchar_t,
 ];
 
 void printSizes() {
   cTypes.forEach((element) {
-    print("${element.cRepresentation.padRight(20)}: ${element.size}");
+    final cName = element.cRepresentation.padRight(20);
+    final size = element.size;
+    final signed = element.isSigned ? 'signed' : 'unsigned';
+    print('$cName: $size $signed');
   });
 }
 
 void testSizes() {
   cTypes.forEach((element) {
+    print(element);
     Expect.equals(element.size, element.ffiSize);
+    final ffiIsSigned = element.ffiIsSigned;
+    if (ffiIsSigned != null) {
+      Expect.equals(element.isSigned, ffiIsSigned);
+    }
   });
 }
 
@@ -86,7 +180,6 @@
 
 void testSizeTAssumptions() {
   Expect.equals(intptr_t.size, size_t.size);
-  Expect.equals(intptr_t.size, ssize_t.size);
 }
 
 void testLongAssumptions() {
@@ -99,13 +192,9 @@
   }
 }
 
-void testOffTAssumptions() {
-  Expect.equals(long.size, off_t.size);
-}
-
 void testWCharTAssumptions() {
-  final bool isSigned = wCharMinValue() != 0;
-  print("wchar_t isSigned $isSigned");
+  final bool isSigned = wchar_t.isSigned;
+  print('wchar_t isSigned $isSigned');
   if (Platform.isWindows) {
     Expect.equals(2, wchar_t.size);
     if (isSigned) {
diff --git a/tests/ffi/extension_methods_test.dart b/tests/ffi/extension_methods_test.dart
index b8f187e..fb71378 100644
--- a/tests/ffi/extension_methods_test.dart
+++ b/tests/ffi/extension_methods_test.dart
@@ -11,6 +11,7 @@
   for (int i = 0; i < 100; i++) {
     testStoreLoad();
     testReifiedGeneric();
+    testCompoundLoadAndStore();
   }
 }
 
@@ -50,6 +51,14 @@
   foo.a = 1;
   Expect.equals(1, foo.a);
   calloc.free(p3);
+
+  final p4 = calloc<Foo>(2);
+  Foo src = p4[1];
+  src.a = 2;
+  p4.ref = src;
+  Foo dst = p4.ref;
+  Expect.equals(2, dst.a);
+  calloc.free(p4);
 }
 
 testReifiedGeneric() {
@@ -59,7 +68,37 @@
   calloc.free(p);
 }
 
+testCompoundLoadAndStore() {
+  final foos = calloc<Foo>(10);
+  final reference = foos.ref..a = 10;
+
+  for (var i = 1; i < 9; i++) {
+    foos[i] = reference;
+    Expect.isTrue(foos[i].a == 10);
+
+    foos.elementAt(i).ref = reference;
+    Expect.isTrue(foos.elementAt(i).ref.a == 10);
+  }
+
+  final bars = calloc<Bar>(10);
+  bars[0].foo = reference;
+
+  for (var i = 1; i < 9; i++) {
+    bars[i] = bars[0];
+    Expect.isTrue(bars.elementAt(i).ref.foo.a == 10);
+  }
+
+  calloc.free(foos);
+  calloc.free(bars);
+}
+
 class Foo extends Struct {
   @Int8()
   external int a;
 }
+
+class Bar extends Union {
+  external Foo foo;
+  @Int32()
+  external int baz;
+}
diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
index 2276d2f..2fbccd1 100644
--- a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
@@ -16,9 +16,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'callback_tests_utils.dart';
 
 import 'dylib_utils.dart';
diff --git a/tests/ffi/function_structs_by_value_generated_compounds.dart b/tests/ffi/function_structs_by_value_generated_compounds.dart
index 439e9a34..666ef20 100644
--- a/tests/ffi/function_structs_by_value_generated_compounds.dart
+++ b/tests/ffi/function_structs_by_value_generated_compounds.dart
@@ -7,9 +7,6 @@
 
 import 'dart:ffi';
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 class Struct1ByteBool extends Struct {
   @Bool()
   external bool a0;
diff --git a/tests/ffi/function_structs_by_value_generated_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_leaf_test.dart
index 283faad..7704417 100644
--- a/tests/ffi/function_structs_by_value_generated_leaf_test.dart
+++ b/tests/ffi/function_structs_by_value_generated_leaf_test.dart
@@ -16,9 +16,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'dylib_utils.dart';
 
 // Reuse the compound classes.
diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart
index 1f4c5d3..897472c 100644
--- a/tests/ffi/function_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_structs_by_value_generated_test.dart
@@ -16,9 +16,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'dylib_utils.dart';
 
 // Reuse the compound classes.
diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart
index 4c260b9..3a18095 100644
--- a/tests/ffi/generator/structs_by_value_tests_generator.dart
+++ b/tests/ffi/generator/structs_by_value_tests_generator.dart
@@ -922,8 +922,6 @@
 
 import 'dart:ffi';
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
 """;
 }
 
@@ -967,8 +965,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
 
 import 'dylib_utils.dart';
 
@@ -1029,8 +1025,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
 
 import 'callback_tests_utils.dart';
 
diff --git a/tests/ffi_2/abi_specific_int_test.dart b/tests/ffi_2/abi_specific_int_test.dart
index 152c159..57daa3f 100644
--- a/tests/ffi_2/abi_specific_int_test.dart
+++ b/tests/ffi_2/abi_specific_int_test.dart
@@ -10,8 +10,6 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
-import 'abi_specific_ints.dart';
-
 void main() {
   testSizeOf();
   testStoreLoad();
diff --git a/tests/ffi_2/abi_specific_ints.dart b/tests/ffi_2/abi_specific_ints.dart
deleted file mode 100644
index 91c9875..0000000
--- a/tests/ffi_2/abi_specific_ints.dart
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for 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 = 2.9
-
-import 'dart:ffi';
-
-// TODO(dacoharkes): These should move to `package:ffi`.
-
-/// Represents a native unsigned pointer-sized integer in C.
-///
-/// [UintPtr] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint64(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint64(),
-})
-class UintPtr extends AbiSpecificInteger {
-  const UintPtr();
-}
-
-/// `long` in C.
-///
-/// [Long] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Int32(),
-  Abi.androidArm64: Int64(),
-  Abi.androidIA32: Int32(),
-  Abi.androidX64: Int64(),
-  Abi.fuchsiaArm64: Int64(),
-  Abi.fuchsiaX64: Int64(),
-  Abi.iosArm: Int32(),
-  Abi.iosArm64: Int64(),
-  Abi.iosX64: Int64(),
-  Abi.linuxArm: Int32(),
-  Abi.linuxArm64: Int64(),
-  Abi.linuxIA32: Int32(),
-  Abi.linuxX64: Int64(),
-  Abi.macosArm64: Int64(),
-  Abi.macosX64: Int64(),
-  Abi.windowsArm64: Int32(),
-  Abi.windowsIA32: Int32(),
-  Abi.windowsX64: Int32(),
-})
-class Long extends AbiSpecificInteger {
-  const Long();
-}
-
-/// `unsigned long` in C.
-///
-/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint64(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint64(),
-  Abi.fuchsiaArm64: Uint64(),
-  Abi.fuchsiaX64: Uint64(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint64(),
-  Abi.iosX64: Uint64(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint64(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint64(),
-  Abi.macosArm64: Uint64(),
-  Abi.macosX64: Uint64(),
-  Abi.windowsArm64: Uint32(),
-  Abi.windowsIA32: Uint32(),
-  Abi.windowsX64: Uint32(),
-})
-class UnsignedLong extends AbiSpecificInteger {
-  const UnsignedLong();
-}
-
-/// `wchar_t` in C.
-///
-/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an
-/// unsigned integer.
-///
-/// [WChar] is not constructible in the Dart code and serves purely as marker in
-/// type signatures.
-@AbiSpecificIntegerMapping({
-  Abi.androidArm: Uint32(),
-  Abi.androidArm64: Uint32(),
-  Abi.androidIA32: Uint32(),
-  Abi.androidX64: Uint32(),
-  Abi.fuchsiaArm64: Uint32(),
-  Abi.fuchsiaX64: Uint32(),
-  Abi.iosArm: Uint32(),
-  Abi.iosArm64: Uint32(),
-  Abi.iosX64: Uint32(),
-  Abi.linuxArm: Uint32(),
-  Abi.linuxArm64: Uint32(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint32(),
-  Abi.macosArm64: Uint32(),
-  Abi.macosX64: Uint32(),
-  Abi.windowsArm64: Uint16(),
-  Abi.windowsIA32: Uint16(),
-  Abi.windowsX64: Uint16(),
-})
-class WChar extends AbiSpecificInteger {
-  const WChar();
-}
diff --git a/tests/ffi_2/c_types_test.dart b/tests/ffi_2/c_types_test.dart
index fa762bd..032853c 100644
--- a/tests/ffi_2/c_types_test.dart
+++ b/tests/ffi_2/c_types_test.dart
@@ -9,65 +9,181 @@
 // @dart = 2.9
 
 import 'dart:ffi';
-
-import "package:expect/expect.dart";
 import 'dart:io' show Platform;
 
-import 'abi_specific_ints.dart';
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
 import 'ffi_test_helpers.dart';
 
 void main() {
   printSizes();
   testSizes();
+  testIntAssumptions();
+  testSizeTAssumptions();
   testLongAssumptions();
   testWCharTAssumptions();
 }
 
 class CType {
   final int ffiSize;
+  final int Function(Pointer) ffiLoad;
   final String modifier;
   final String type;
+  final String type2;
 
-  CType(this.ffiSize, this.type, [this.modifier = ""]);
+  CType(this.ffiSize, this.type,
+      {this.type2 = '', this.modifier = '', this.ffiLoad});
 
-  String get cRepresentation => "$modifier $type".trim();
+  String get cRepresentation => '$modifier $type $type2'.trim();
 
-  String get _getSizeName => "FfiSizeOf_$modifier\_$type";
+  String get _getSizeName => 'FfiSizeOf_$modifier\_$type\_$type2';
+
+  String get _getSignName => 'FfiSignOf_$modifier\_$type\_$type2';
 
   int Function() get sizeFunction => ffiTestFunctions
       .lookupFunction<Uint64 Function(), int Function()>(_getSizeName);
 
+  int Function() get signFunction => ffiTestFunctions
+      .lookupFunction<Uint64 Function(), int Function()>(_getSignName);
+
   int get size => sizeFunction();
 
+  bool get isSigned => signFunction() != 0;
+
+  bool get ffiIsSigned {
+    final ffiLoad_ = ffiLoad;
+    if (ffiLoad_ == null) {
+      return null;
+    }
+    assert(size < 8);
+    return using((Arena arena) {
+      final p = arena<Int64>()..value = -1;
+      return ffiLoad_(p) < 0;
+    });
+  }
+
   String toString() => cRepresentation;
 }
 
-final intptr_t = CType(sizeOf<IntPtr>(), "intptr_t");
-final uintptr_t = CType(sizeOf<UintPtr>(), "uintptr_t");
-final long = CType(sizeOf<Long>(), "long");
-final ulong = CType(sizeOf<UnsignedLong>(), "long", "unsigned");
-final wchar_t = CType(sizeOf<WChar>(), "wchar_t");
+final uchar = CType(
+  sizeOf<UnsignedChar>(),
+  'char',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedChar>().value,
+);
+final schar = CType(
+  sizeOf<SignedChar>(),
+  'char',
+  modifier: 'signed',
+  ffiLoad: (Pointer p) => p.cast<SignedChar>().value,
+);
+final short = CType(
+  sizeOf<Short>(),
+  'short',
+  ffiLoad: (Pointer p) => p.cast<Short>().value,
+);
+final ushort = CType(
+  sizeOf<UnsignedShort>(),
+  'short',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedShort>().value,
+);
+final int_ = CType(
+  sizeOf<Int>(),
+  'int',
+  ffiLoad: (Pointer p) => p.cast<Int>().value,
+);
+final uint = CType(
+  sizeOf<UnsignedInt>(),
+  'int',
+  modifier: 'unsigned',
+  ffiLoad: (Pointer p) => p.cast<UnsignedInt>().value,
+);
+final long = CType(
+  sizeOf<Long>(),
+  'long',
+);
+final ulong = CType(
+  sizeOf<UnsignedLong>(),
+  'long',
+  modifier: 'unsigned',
+);
+final longlong = CType(
+  sizeOf<LongLong>(),
+  'long',
+  type2: 'long',
+);
+final ulonglong = CType(
+  sizeOf<UnsignedLongLong>(),
+  'long',
+  type2: 'long',
+  modifier: 'unsigned',
+);
+final intptr_t = CType(
+  sizeOf<IntPtr>(),
+  'intptr_t',
+);
+final uintptr_t = CType(
+  sizeOf<UintPtr>(),
+  'uintptr_t',
+);
+final size_t = CType(
+  sizeOf<Size>(),
+  'size_t',
+);
+final wchar_t = CType(
+  sizeOf<WChar>(),
+  'wchar_t',
+  ffiLoad: (Pointer p) => p.cast<WChar>().value,
+);
 
 final cTypes = [
-  intptr_t,
-  uintptr_t,
+  uchar,
+  schar,
+  short,
+  ushort,
+  int_,
+  uint,
   long,
   ulong,
+  longlong,
+  ulonglong,
+  intptr_t,
+  uintptr_t,
+  size_t,
   wchar_t,
 ];
 
 void printSizes() {
   cTypes.forEach((element) {
-    print("${element.cRepresentation.padRight(20)}: ${element.size}");
+    final cName = element.cRepresentation.padRight(20);
+    final size = element.size;
+    final signed = element.isSigned ? 'signed' : 'unsigned';
+    print('$cName: $size $signed');
   });
 }
 
 void testSizes() {
   cTypes.forEach((element) {
+    print(element);
     Expect.equals(element.size, element.ffiSize);
+    final ffiIsSigned = element.ffiIsSigned;
+    if (ffiIsSigned != null) {
+      Expect.equals(element.isSigned, ffiIsSigned);
+    }
   });
 }
 
+void testIntAssumptions() {
+  Expect.equals(4, int_.size);
+  Expect.equals(4, uint.size);
+}
+
+void testSizeTAssumptions() {
+  Expect.equals(intptr_t.size, size_t.size);
+}
+
 void testLongAssumptions() {
   if (Platform.isWindows) {
     Expect.equals(4, long.size);
@@ -79,8 +195,8 @@
 }
 
 void testWCharTAssumptions() {
-  final bool isSigned = wCharMinValue() != 0;
-  print("wchar_t isSigned $isSigned");
+  final bool isSigned = wchar_t.isSigned;
+  print('wchar_t isSigned $isSigned');
   if (Platform.isWindows) {
     Expect.equals(2, wchar_t.size);
     if (isSigned) {
diff --git a/tests/ffi_2/extension_methods_test.dart b/tests/ffi_2/extension_methods_test.dart
index 9d96f41..cb124af 100644
--- a/tests/ffi_2/extension_methods_test.dart
+++ b/tests/ffi_2/extension_methods_test.dart
@@ -13,6 +13,7 @@
   for (int i = 0; i < 100; i++) {
     testStoreLoad();
     testReifiedGeneric();
+    testCompoundLoadAndStore();
   }
 }
 
@@ -52,6 +53,14 @@
   foo.a = 1;
   Expect.equals(1, foo.a);
   calloc.free(p3);
+
+  final p4 = calloc<Foo>(2);
+  Foo src = p4[1];
+  src.a = 2;
+  p4.ref = src;
+  Foo dst = p4.ref;
+  Expect.equals(2, dst.a);
+  calloc.free(p4);
 }
 
 testReifiedGeneric() {
@@ -61,7 +70,37 @@
   calloc.free(p);
 }
 
+testCompoundLoadAndStore() {
+  final foos = calloc<Foo>(10);
+  final reference = foos.ref..a = 10;
+
+  for (var i = 1; i < 9; i++) {
+    foos[i] = reference;
+    Expect.isTrue(foos[i].a == 10);
+
+    foos.elementAt(i).ref = reference;
+    Expect.isTrue(foos.elementAt(i).ref.a == 10);
+  }
+
+  final bars = calloc<Bar>(10);
+  bars[0].foo = reference;
+
+  for (var i = 1; i < 9; i++) {
+    bars[i] = bars[0];
+    Expect.isTrue(bars.elementAt(i).ref.foo.a == 10);
+  }
+
+  calloc.free(foos);
+  calloc.free(bars);
+}
+
 class Foo extends Struct {
   @Int8()
   int a;
 }
+
+class Bar extends Union {
+  Foo foo;
+  @Int32()
+  int baz;
+}
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
index f4100fb..b890cbc 100644
--- a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
@@ -18,9 +18,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'callback_tests_utils.dart';
 
 import 'dylib_utils.dart';
diff --git a/tests/ffi_2/function_structs_by_value_generated_compounds.dart b/tests/ffi_2/function_structs_by_value_generated_compounds.dart
index 6908177..cd3fdf1 100644
--- a/tests/ffi_2/function_structs_by_value_generated_compounds.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_compounds.dart
@@ -9,9 +9,6 @@
 
 import 'dart:ffi';
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 class Struct1ByteBool extends Struct {
   @Bool()
   bool a0;
diff --git a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
index 7c64296..8c01056 100644
--- a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
@@ -18,9 +18,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'dylib_utils.dart';
 
 // Reuse the compound classes.
diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart
index ef24ad2..6329287 100644
--- a/tests/ffi_2/function_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_test.dart
@@ -18,9 +18,6 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-// Reuse the AbiSpecificInts.
-import 'abi_specific_ints.dart';
-
 import 'dylib_utils.dart';
 
 // Reuse the compound classes.
diff --git a/tests/language/bool/conditional_expression_condition_context_error_test.dart b/tests/language/bool/conditional_expression_condition_context_error_test.dart
new file mode 100644
index 0000000..ade91d5
--- /dev/null
+++ b/tests/language/bool/conditional_expression_condition_context_error_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+T castObject<T>(Object value) => value as T;
+
+main() {
+  print((castObject(true)..whatever()) ? 1 : 2);
+  //                       ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
+  // [cfe] The method 'whatever' isn't defined for the class 'bool'.
+}
diff --git a/tests/language/control_flow_collections/await_for_dynamic_null_test.dart b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
index aad701f2..36286b9 100644
--- a/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
+++ b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
@@ -9,11 +9,14 @@
   asyncTest(() async {
     // Null stream.
     dynamic nullStream = null;
-    asyncExpectThrows<Error>(
-        () async => <int>[await for (var i in nullStream) 1]);
-    asyncExpectThrows<Error>(
-        () async => <int, int>{await for (var i in nullStream) 1: 1});
-    asyncExpectThrows<Error>(
-        () async => <int>{await for (var i in nullStream) 1});
+    asyncExpectThrows<Error>(() async {
+      <int>[await for (var i in nullStream) 1];
+    }());
+    asyncExpectThrows<Error>(() async {
+      <int, int>{await for (var i in nullStream) 1: 1};
+    }());
+    asyncExpectThrows<Error>(() async {
+      <int>{await for (var i in nullStream) 1};
+    }());
   });
 }
diff --git a/tests/language/control_flow_collections/await_for_test.dart b/tests/language/control_flow_collections/await_for_test.dart
index ce84fe0..d98f9f2 100644
--- a/tests/language/control_flow_collections/await_for_test.dart
+++ b/tests/language/control_flow_collections/await_for_test.dart
@@ -30,17 +30,28 @@
   Expect.listEquals(list, <int>[await for (var i in stream(list)) i]);
 
   // Await for at beginning.
-  Expect.listEquals(list, <int>[await for (var i in stream([1, 2])) i, 3, 4]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, 2])) i,
+    3,
+    4
+  ]);
 
   // Await for in middle.
-  Expect.listEquals(list, <int>[1, await for (var i in stream([2, 3])) i, 4]);
+  Expect.listEquals(list, <int>[
+    1,
+    await for (var i in stream([2, 3])) i,
+    4
+  ]);
 
   // Await for at end.
-  Expect.listEquals(list, <int>[1, 2, await for (var i in stream([3, 4])) i]);
+  Expect.listEquals(list, <int>[
+    1,
+    2,
+    await for (var i in stream([3, 4])) i
+  ]);
 
   // Empty await for.
-  Expect.listEquals(list,
-      <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
+  Expect.listEquals(list, <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
 
   // Multiple await fors.
   Expect.listEquals(list, <int>[
@@ -50,26 +61,44 @@
   ]);
 
   // Spread inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+  ]);
 
   // If inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i
+  ]);
 
   // Else inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i else i
+  ]);
 
   // For inside await for.
   Expect.listEquals(list, <int>[
-    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+    await for (var i in stream([0, 2]))
+      for (var j = 1; j <= 2; j++) i + j
   ]);
 
   // Does not flatten nested collection literal.
-  Expect.listEquals([1], [await for (var i in stream([1])) [i]].first);
-  Expect.mapEquals({1: 1}, [await for (var i in stream([1])) {i: i}].first);
-  Expect.setEquals({1}, [await for (var i in stream([1])) {i}].first);
+  Expect.listEquals(
+      [1],
+      [
+        await for (var i in stream([1])) [i]
+      ].first);
+  Expect.mapEquals(
+      {1: 1},
+      [
+        await for (var i in stream([1])) {i: i}
+      ].first);
+  Expect.setEquals(
+      {1},
+      [
+        await for (var i in stream([1])) {i}
+      ].first);
 }
 
 Future<void> testMap() async {
@@ -77,26 +106,30 @@
   Expect.mapEquals(map, <int, int>{await for (var i in stream(list)) i: i});
 
   // Await for at beginning.
-  Expect.mapEquals(map,
-      <int, int>{await for (var i in stream([1, 2])) i: i, 3: 3, 4: 4});
-
-  // Await for in middle.
-  Expect.mapEquals(map,
-      <int, int>{1: 1, await for (var i in stream([2, 3])) i: i, 4: 4});
-
-  // Await for at end.
-  Expect.mapEquals(map,
-      <int, int>{1: 1, 2: 2, await for (var i in stream([3, 4])) i: i});
-
-  // Empty await for.
   Expect.mapEquals(map, <int, int>{
-    1: 1,
-    await for (var i in stream([])) i: i,
-    2: 2,
+    await for (var i in stream([1, 2])) i: i,
     3: 3,
     4: 4
   });
 
+  // Await for in middle.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    await for (var i in stream([2, 3])) i: i,
+    4: 4
+  });
+
+  // Await for at end.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    2: 2,
+    await for (var i in stream([3, 4])) i: i
+  });
+
+  // Empty await for.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, await for (var i in stream([])) i: i, 2: 2, 3: 3, 4: 4});
+
   // Multiple await fors.
   Expect.mapEquals(map, <int, int>{
     await for (var i in stream([1])) i: i,
@@ -106,18 +139,22 @@
 
   // Spread inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([0, 2]))
-      ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+    await for (var i in stream([0, 2])) ...<int, int>{
+      1 + i: 1 + i,
+      2 + i: 2 + i
+    }
   });
 
   // If inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i: i
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i: i
   });
 
   // Else inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i: -i else i: i
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i: -i else i: i
   });
 
   // For inside await for.
@@ -132,17 +169,28 @@
   Expect.setEquals(set, <int>{await for (var i in stream(list)) i});
 
   // Await for at beginning.
-  Expect.setEquals(set, <int>{await for (var i in stream([1, 2])) i, 3, 4});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, 2])) i,
+    3,
+    4
+  });
 
   // Await for in middle.
-  Expect.setEquals(set, <int>{1, await for (var i in stream([2, 3])) i, 4});
+  Expect.setEquals(set, <int>{
+    1,
+    await for (var i in stream([2, 3])) i,
+    4
+  });
 
   // Await for at end.
-  Expect.setEquals(set, <int>{1, 2, await for (var i in stream([3, 4])) i});
+  Expect.setEquals(set, <int>{
+    1,
+    2,
+    await for (var i in stream([3, 4])) i
+  });
 
   // Empty await for.
-  Expect.setEquals(set,
-      <int>{1, await for (var i in stream([])) i, 2, 3, 4});
+  Expect.setEquals(set, <int>{1, await for (var i in stream([])) i, 2, 3, 4});
 
   // Multiple await fors.
   Expect.setEquals(set, <int>{
@@ -152,26 +200,44 @@
   });
 
   // Spread inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+  });
 
   // If inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i
+  });
 
   // Else inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i else i
+  });
 
   // For inside await for.
   Expect.setEquals(set, <int>{
-    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+    await for (var i in stream([0, 2]))
+      for (var j = 1; j <= 2; j++) i + j
   });
 
   // Does not flatten nested collection literal.
-  Expect.listEquals([1], {await for (var i in stream([1])) [i]}.first);
-  Expect.mapEquals({1: 1}, {await for (var i in stream([1])) {i: i}}.first);
-  Expect.setEquals({1}, {await for (var i in stream([1])) {i}}.first);
+  Expect.listEquals(
+      [1],
+      {
+        await for (var i in stream([1])) [i]
+      }.first);
+  Expect.mapEquals(
+      {1: 1},
+      {
+        await for (var i in stream([1])) {i: i}
+      }.first);
+  Expect.setEquals(
+      {1},
+      {
+        await for (var i in stream([1])) {i}
+      }.first);
 }
 
 Future<void> testDuplicateKeys() async {
@@ -207,28 +273,46 @@
   Expect.equals("1:a,2:a", map.keys.join(","));
   Expect.equals("2,4", map.values.join(","));
 
-  var set = <Equality>{e1a, await for (var i in stream([0, 1, 2])) keys[i]};
+  var set = <Equality>{
+    e1a,
+    await for (var i in stream([0, 1, 2])) keys[i]
+  };
   Expect.equals("1:a,2:a", set.join(","));
 }
 
 Future<void> testRuntimeErrors() async {
   // Cast variable.
   dynamic nonStream = 3;
-  asyncExpectThrows<TypeError>(
-      () async => <int>[await for (int i in nonStream) 1]);
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (int i in nonStream) 1: 1});
-  asyncExpectThrows<TypeError>(
-      () async => <int>{await for (int i in nonStream) 1});
+  asyncExpectThrows<TypeError>(() async {
+    <int>[await for (int i in nonStream) 1];
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{await for (int i in nonStream) 1: 1};
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int>{await for (int i in nonStream) 1};
+  }());
 
   // Wrong element type.
   dynamic nonInt = "string";
-  asyncExpectThrows<TypeError>(
-      () async => <int>[await for (var i in stream([1])) nonInt]);
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (var i in stream([1])) nonInt: 1});
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (var i in stream([1])) 1: nonInt});
-  asyncExpectThrows<TypeError>(
-      () async => <int>{await for (var i in stream([1])) nonInt});
+  asyncExpectThrows<TypeError>(() async {
+    <int>[
+      await for (var i in stream([1])) nonInt
+    ];
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{
+      await for (var i in stream([1])) nonInt: 1
+    };
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{
+      await for (var i in stream([1])) 1: nonInt
+    };
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int>{
+      await for (var i in stream([1])) nonInt
+    };
+  }());
 }
diff --git a/tests/language/enum/enhanced_enums_basic_test.dart b/tests/language/enum/enhanced_enums_basic_test.dart
new file mode 100644
index 0000000..655a1f0
--- /dev/null
+++ b/tests/language/enum/enhanced_enums_basic_test.dart
@@ -0,0 +1,370 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for 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=enhanced-enums
+
+// Test new enhanced enum syntax.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  Expect.equals(3, EnumPlain.values.length);
+  Expect.identical(EnumPlain.v1, EnumPlain.values[0]);
+  Expect.identical(EnumPlain.v2, EnumPlain.values[1]);
+  Expect.identical(EnumPlain.v3, EnumPlain.values[2]);
+
+  Expect.equals(3, EnumPlainTrailingComma.values.length);
+  Expect.identical(EnumPlainTrailingComma.v1, EnumPlainTrailingComma.values[0]);
+  Expect.identical(EnumPlainTrailingComma.v2, EnumPlainTrailingComma.values[1]);
+  Expect.identical(EnumPlainTrailingComma.v3, EnumPlainTrailingComma.values[2]);
+
+  Expect.equals(3, EnumPlainNoSemicolon.values.length);
+  Expect.identical(EnumPlainNoSemicolon.v1, EnumPlainNoSemicolon.values[0]);
+  Expect.identical(EnumPlainNoSemicolon.v2, EnumPlainNoSemicolon.values[1]);
+  Expect.identical(EnumPlainNoSemicolon.v3, EnumPlainNoSemicolon.values[2]);
+  Expect.type<EnumNoSemicolon<num>>(EnumNoSemicolon.v1);
+
+  Expect.equals(3, EnumPlainSemicolon.values.length);
+  Expect.identical(EnumPlainSemicolon.v1, EnumPlainSemicolon.values[0]);
+  Expect.identical(EnumPlainSemicolon.v2, EnumPlainSemicolon.values[1]);
+  Expect.identical(EnumPlainSemicolon.v3, EnumPlainSemicolon.values[2]);
+
+  Expect.equals(3, EnumPlainTrailingCommaSemicolon.values.length);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v1,
+      EnumPlainTrailingCommaSemicolon.values[0]);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v2,
+      EnumPlainTrailingCommaSemicolon.values[1]);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v3,
+      EnumPlainTrailingCommaSemicolon.values[2]);
+
+  Expect.equals(6, EnumAll.values.length);
+  Expect.identical(EnumAll.v1, EnumAll.values[0]);
+  Expect.identical(EnumAll.v2, EnumAll.values[1]);
+  Expect.identical(EnumAll.v3, EnumAll.values[2]);
+  Expect.identical(EnumAll.v4, EnumAll.values[3]);
+  Expect.identical(EnumAll.v5, EnumAll.values[4]);
+  Expect.identical(EnumAll.v6, EnumAll.values[5]);
+
+  Expect.equals("unnamed", EnumAll.v1.constructor);
+  Expect.equals("unnamed", EnumAll.v2.constructor);
+  Expect.equals("unnamed", EnumAll.v3.constructor);
+  Expect.equals("named", EnumAll.v4.constructor);
+  Expect.equals("renamed", EnumAll.v5.constructor);
+  Expect.equals("unnamed", EnumAll.v6.constructor);
+
+  Expect.type<EnumAll<num, num>>(EnumAll.v1);
+  Expect.type<EnumAll<num, int>>(EnumAll.v2);
+  Expect.type<EnumAll<int, int>>(EnumAll.v3);
+  Expect.type<EnumAll<int, int>>(EnumAll.v4);
+  Expect.type<EnumAll<int, int>>(EnumAll.v5);
+  Expect.type<EnumAll<num, num>>(EnumAll.v6);
+
+  // Access static members.
+  Expect.identical(EnumAll.v3, EnumAll.sConst);
+  Expect.identical(EnumAll.v3, EnumAll.sFinal);
+
+  Expect.throws(() => EnumAll.sLateFinal);
+  EnumAll.sLateFinal = EnumAll.v1;
+  Expect.identical(EnumAll.v1, EnumAll.sLateFinal);
+  Expect.throws(() => EnumAll.sLateFinal = EnumAll.v1);
+
+  Expect.identical(EnumAll.v3, EnumAll.sFinalInit);
+
+  Expect.throws(() => EnumAll.sLate);
+  EnumAll.sLate = EnumAll.v1;
+  Expect.identical(EnumAll.v1, EnumAll.sLate);
+  EnumAll.sLate = EnumAll.v3;
+  Expect.identical(EnumAll.v3, EnumAll.sLate);
+  Expect.identical(EnumAll.v3, EnumAll.sLateVarInit);
+  Expect.isNull(EnumAll.sVar);
+  Expect.identical(EnumAll.v3, EnumAll.sVarInit);
+
+  Expect.identical(EnumAll.v3, EnumAll.staticGetSet);
+  EnumAll.staticGetSet = EnumAll.v5;
+  Expect.equals(42, EnumAll.staticMethod());
+
+  Expect.identical(EnumAll.v2, EnumAll<num, num>.factory(2));
+  Expect.identical(EnumAll.v2, EnumAll<num, num>.refactory(2));
+
+  // Access static members through typedef.
+  Expect.identical(EnumAll.v3, TypeDefAll.sConst);
+  Expect.identical(EnumAll.v3, TypeDefAll.sFinal);
+  Expect.identical(EnumAll.v1, TypedefAll.sLateFinal);
+  Expect.identical(EnumAll.v3, TypedefAll.sFinalInit);
+
+  Expect.identical(EnumAll.v3, TypeDefAll.staticGetSet);
+  TypeDefAll.staticGetSet = EnumAll.v5;
+  Expect.equals(42, TypeDefAll.staticMethod());
+
+  Expect.identical(EnumAll.v2, TypeDefAll.factory(2));
+  Expect.identical(EnumAll.v2, TypeDefAll.refactory(2));
+
+  // Access instance members.
+  Expect.equals(0, EnumAll.v1.instanceGetSet);
+  EnumAll.v1.instanceGetSet = 0.5;
+  Expect.equals(0, EnumAll.v1.instanceMethod());
+  Expect.identical(EnumAll.v1, EnumAll.v3 ^ EnumAll.v2);
+
+  Expect.equals("EnumAll.v1:EnumMixin<num>:ObjectMixin:this",
+      EnumAll.v1.thisAndSuper());
+
+  // Which can reference type parameters.
+  Expect.isTrue(EnumAll.v2.test(2)); // does `is T` with `T` being `int`.
+  Expect.isFalse(EnumAll.v2.test(2.5));
+
+  // Including `call`.
+  Expect.equals(42, EnumAll.v1<int>(42));
+  Expect.equals(42, EnumAll.v1(42));
+  // Also as tear-off.
+  Function eaf1 = EnumAll.v1;
+  Expect.type<T Function<T>(T)>(eaf1);
+  Function eaf2 = EnumAll.v1<String>;
+  Expect.type<String Function(String)>(eaf2);
+
+  // Instance members shadow extensions.
+  Expect.equals("not extension", EnumAll.v1.notExtension);
+  // But you can call extension members if there is no conflict.
+  Expect.equals("extension", EnumAll.v1.extension);
+
+  // The `index` and `toString` implementations are inherited from
+  // the `Enum` implementing superclass.
+  Expect.equals(3.5, StringIndexEnum.v1.index);
+  Expect.equals(3.5, StringIndexEnum.v2.index);
+  Expect.equals(0, StringIndexEnum.v1.realIndex);
+  Expect.equals(1, StringIndexEnum.v2.realIndex);
+  Expect.equals("FakeString", StringIndexEnum.v1.toString());
+  Expect.equals("FakeString", StringIndexEnum.v2.toString());
+  Expect.equals("StringIndexEnum.v1", StringIndexEnum.v1.realToString());
+  Expect.equals("StringIndexEnum.v2", StringIndexEnum.v2.realToString());
+
+  // Enum elements are always distinct, even if their state doesn't differ.
+  Expect.distinct(Canonical.v1, Canonical.v2, "Canonical - type only");
+  Expect.distinct(Canonical.v2, Canonical.v3, "Canonical - no difference");
+
+  // A `values` static constant is added only if *not* causing a conflict.
+  Expect.equals("StaticDeclaration", DeclaresValuesStatic.values);
+  Expect.equals("Declaration", DeclaresValues.v1.values);
+  Expect.equals("Mixin", InheritsValues.v1.values);
+  Expect.equals("NSM", ImplementsValues.v1.values);
+}
+
+// Original syntax still works, without semicolon after values.
+enum EnumPlain { v1, v2, v3 }
+
+// Also with trailing comma.
+enum EnumPlainTrailingComma {
+  v1,
+  v2,
+  v3,
+}
+
+// Also if using type parameters, mixins or interfaces.
+// It only matters whether there is something after the values.
+enum EnumNoSemicolon<T extends num> with ObjectMixin implements Interface {
+  v1, v2, v3
+}
+
+
+// Allows semicolon after values, even when not needed.
+// Without trailing comma.
+enum EnumPlainSemicolon { v1, v2, v3; }
+
+// With trailing comma.
+enum EnumPlainTrailingCommaSemicolon {
+  v1,
+  v2,
+  v3,
+  ;
+}
+
+// Full syntax, with every possible option.
+@EnumAll.v1
+@EnumAll.sConst
+enum EnumAll<S extends num, T extends num>
+    with GenericEnumMixin<T>, ObjectMixin
+    implements Interface, GenericInterface<S> {
+  @v1
+  @v2
+  v1,
+  @EnumAll.v2
+  v2(y: 2),
+  @sConst
+  v3<int, int>(y: 2),
+  v4.named(1, y: 2),
+  v5<int, int>.renamed(1, y: 2),
+  v6.new(),
+  ;
+
+  /// Static members.
+  ///
+  /// Any kind of static variable.
+  static const sConst = v3;
+  static final sFinal = v3;
+  static late final EnumAll sLateFinal;
+  static late final sLateFinalInit = v3;
+  static late EnumAll sLateVar;
+  static late var sLateVarInit = v3;
+  static EnumAll? sVar;
+  static EnumAll sVarInit = v3;
+  /// Static getters, setters and methods
+  static EnumAll<int, int> get staticGetSet => v3;
+  static set staticGetSet(EnumAll<int, int> _) {}
+  static int staticMethod() => 42;
+
+  // Constructors.
+  // Generative, non-redirecting, unnamed.
+  const EnumAll({T? y})
+      : constructor = "unnamed", this.x = 0 as S, y = y ?? (0 as T);
+  // Generative, non-redirecting, named.
+  const EnumAll.named(this.x, {T? y, String? constructor})
+      : constructor = constructor ?? "named", y = y ?? (0 as T);
+  // Generative, redirecting.
+  const EnumAll.renamed(S x, {T? y})
+      : this.named(x, y: y, constructor: "renamed");
+  // Factory, non-redirecting.
+  factory EnumAll.factory(int index) => values[index] as EnumAll<S, T>;
+  // Factory, redirecting (only to other factory constructor).
+  factory EnumAll.refactory(int index) = EnumAll<S, T>.factory;
+
+  // Cannot have factory constructors redirecting to generative constructors.
+  // (Nothing can refer to generative constructors except redirecting generative
+  // constructors and the implicit element creation expressions.)
+  // Cannot have const factory constructor, because they *must* redirect to
+  // generative constructors.
+  // Cannot have `super`-constuctor invocations in initializer lists.
+
+  // Instance members.
+
+  // Instance variables must be final and non-late because of const constructor.
+  final String constructor;
+  final S x;
+  final num y;
+
+  // Getters, setters, methods and operators.
+  S get instanceGetSet => x;
+  set instanceGetSet(S _) {}
+  S instanceMethod() => x;
+  EnumAll<num, num> operator ^(EnumAll<num, num> other) {
+    var newIndex = index ^ other.index;
+    if (newIndex > 4) newIndex = 4;
+    return values[newIndex]; // Can refer to `values`.
+  }
+
+  // Can have non-primitive equality and hashCode.
+  int get hashCode => index;
+  bool operator==(covariant EnumAll other) => index == other.index;
+
+  // Can access `this` and `super` in an instance method.
+  String thisAndSuper() => "${super.toString()}:${this.toString()}";
+
+  // Can be callable.
+  T call<T>(T value) => value;
+
+  // Instance members shadow extensions.
+  String get notExtension => "not extension";
+
+  String toString() => "this";
+}
+
+extension EnumAllExtension on EnumAll {
+  String get notExtension => Expect.fail("Unreachable");
+  String get extension => "extension";
+}
+
+typedef TypeDefAll = EnumAll<num, num>;
+
+// Can have no unnamed constructor.
+enum EnumNoUnnamedConstructor {
+  v1.named(1),
+  v2.named(2);
+
+  final int x;
+  EnumNoUnnamedConstructor.named(this.x);
+}
+
+// Can have an unnamed factory constructor.
+enum EnumFactoryUnnamedConstructor {
+  v1.named(1),
+  v2.named(2);
+
+  final int x;
+  factory EnumFactoryUnnamedConstructor() => v1;
+  EnumFactoryUnnamedConstructor.named(this.x);
+}
+
+// Elements which do not differ in public state are still different.
+// Ditto if only differing in type arguments.
+enum Canonical<T> {
+  v1<int>(1),
+  v2<num>(1),
+  v3<num>(1);
+  final T value;
+  Canonical(this.value);
+}
+
+// Both `toString` and `index` are inherited from superclass.
+enum StringIndexEnum {
+  v1, v2;
+  num get index => 3.5;
+  int get realIndex => super.index;
+  String toString() => "FakeString";
+  String realToString() => super.toString();
+}
+
+enum DeclaresValuesStatic {
+  v1;
+  static String get values => "StaticDeclaration";
+}
+
+enum DeclaresValues {
+  v1;
+  String get values => "Declaration";
+}
+
+enum InheritsValues with ValuesMixin {
+  v1;
+}
+
+enum ImplementsValues implements ValuesInterface {
+  v1;
+  dynamic noSuchMethod(i) => "NSM";
+}
+
+// --------------------------------------------------------------------
+// Helper declarations
+
+mixin ObjectMixin on Object {
+  String toString() => "${super.toString()}:ObjectMixin";
+}
+
+mixin EnumMixin on Enum {
+  String toString() => "${super.toString()}:EnumMixin";
+}
+
+mixin GenericObjectMixin<T> on Object {
+  bool test(Object o) => o is T;
+  String toString() => "${super.toString()}:ObjectMixin<$T>";
+}
+
+mixin GenericEnumMixin<T> on Enum {
+  bool test(Object o) => o is T;
+  String toString() => "${super.toString()}:EnumMixin<$T>";
+}
+
+abstract class Interface {
+
+}
+
+abstract class GenericInterface<T> {
+  // Implemented by mixins.
+  bool test(Object o);
+}
+
+abstract class ValuesInterface {
+  String get values;
+}
+
+mixin ValuesMixin {
+  String get values => "Mixin";
+}
diff --git a/tests/language/final/initialize_inside_closure_test.dart b/tests/language/final/initialize_inside_closure_test.dart
new file mode 100644
index 0000000..f8fbcc8
--- /dev/null
+++ b/tests/language/final/initialize_inside_closure_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for 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 - see https://github.com/dart-lang/sdk/issues/47991
+
+import 'dart:math';
+
+void main() {
+  () {
+    final should = Random().nextBool() || Random().nextBool();
+    final int a;
+
+    if (should) {
+      a = 1;
+    } else {
+      a = 2;
+    }
+  };
+}
diff --git a/tests/language/library/env_test.dart b/tests/language/library/env_test.dart
index 9adcf8d..3dc36dd 100644
--- a/tests/language/library/env_test.dart
+++ b/tests/language/library/env_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:expect/expect.dart';
+import 'package:expect/config.dart';
 
 main() {
   const NOT_PRESENT = false;
@@ -61,18 +62,12 @@
         const bool.fromEnvironment("dart.library.io", defaultValue: false));
   }
 
-  bool? hasMirrorSupport;
-  hasMirrorSupport = true; //# has_mirror_support: ok
-  hasMirrorSupport = false; //# has_no_mirror_support: ok
-
-  if (hasMirrorSupport != null) {
-    bool expectedResult = hasMirrorSupport ? true : NOT_PRESENT;
-
-    Expect.equals(
-        expectedResult,
-        const bool.fromEnvironment("dart.library.mirrors",
-            defaultValue: NOT_PRESENT));
-  }
+  bool hasMirrorSupport = !isDart2jsConfiguration &&
+      !isDdcConfiguration && !isVmAotConfiguration;
+  Expect.equals(
+      hasMirrorSupport,
+      const bool.fromEnvironment("dart.library.mirrors",
+          defaultValue: NOT_PRESENT));
 
   Expect.equals(
       NOT_PRESENT,
diff --git a/tests/language/vm/fuzzer_unsigned_shift_right_test.dart b/tests/language/vm/fuzzer_unsigned_shift_right_test.dart
new file mode 100644
index 0000000..01e935a
--- /dev/null
+++ b/tests/language/vm/fuzzer_unsigned_shift_right_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// VMOptions=--deterministic
+
+// The Dart Project Fuzz Tester (1.93).
+// Program generated as:
+//   dart dartfuzz.dart --seed 316265767 --no-fp --no-ffi --flat
+
+import 'dart:typed_data';
+
+Int16List? foo0_0(int par4) {
+  if (par4 >= 36) {
+    return Int16List(40);
+  }
+  for (int loc0 = 0; loc0 < 31; loc0++) {
+    for (int loc1 in ((Uint8ClampedList.fromList(Uint8List(26)))
+        .sublist((11 >>> loc0), null))) {}
+  }
+  return foo0_0(par4 + 1);
+}
+
+main() {
+  foo0_0(0);
+}
diff --git a/tests/language_2/bool/conditional_expression_condition_context_error_test.dart b/tests/language_2/bool/conditional_expression_condition_context_error_test.dart
new file mode 100644
index 0000000..ade91d5
--- /dev/null
+++ b/tests/language_2/bool/conditional_expression_condition_context_error_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+T castObject<T>(Object value) => value as T;
+
+main() {
+  print((castObject(true)..whatever()) ? 1 : 2);
+  //                       ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
+  // [cfe] The method 'whatever' isn't defined for the class 'bool'.
+}
diff --git a/tests/language_2/control_flow_collections/await_for_null_test.dart b/tests/language_2/control_flow_collections/await_for_null_test.dart
index 47529b2..482cbff 100644
--- a/tests/language_2/control_flow_collections/await_for_null_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_null_test.dart
@@ -11,11 +11,14 @@
   asyncTest(() async {
     // Null stream.
     Stream<int> nullStream = null;
-    asyncExpectThrows<Error>(
-        () async => <int>[await for (var i in nullStream) 1]);
-    asyncExpectThrows<Error>(
-        () async => <int, int>{await for (var i in nullStream) 1: 1});
-    asyncExpectThrows<Error>(
-        () async => <int>{await for (var i in nullStream) 1});
+    asyncExpectThrows<Error>(() async {
+      <int>[await for (var i in nullStream) 1];
+    }());
+    asyncExpectThrows<Error>(() async {
+      <int, int>{await for (var i in nullStream) 1: 1};
+    }());
+    asyncExpectThrows<Error>(() async {
+      <int>{await for (var i in nullStream) 1};
+    }());
   });
 }
diff --git a/tests/language_2/control_flow_collections/await_for_test.dart b/tests/language_2/control_flow_collections/await_for_test.dart
index 402820b..d661143 100644
--- a/tests/language_2/control_flow_collections/await_for_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_test.dart
@@ -32,17 +32,28 @@
   Expect.listEquals(list, <int>[await for (var i in stream(list)) i]);
 
   // Await for at beginning.
-  Expect.listEquals(list, <int>[await for (var i in stream([1, 2])) i, 3, 4]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, 2])) i,
+    3,
+    4
+  ]);
 
   // Await for in middle.
-  Expect.listEquals(list, <int>[1, await for (var i in stream([2, 3])) i, 4]);
+  Expect.listEquals(list, <int>[
+    1,
+    await for (var i in stream([2, 3])) i,
+    4
+  ]);
 
   // Await for at end.
-  Expect.listEquals(list, <int>[1, 2, await for (var i in stream([3, 4])) i]);
+  Expect.listEquals(list, <int>[
+    1,
+    2,
+    await for (var i in stream([3, 4])) i
+  ]);
 
   // Empty await for.
-  Expect.listEquals(list,
-      <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
+  Expect.listEquals(list, <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
 
   // Multiple await fors.
   Expect.listEquals(list, <int>[
@@ -52,38 +63,58 @@
   ]);
 
   // Spread inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+  ]);
 
   // If inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i
+  ]);
 
   // Else inside await for.
-  Expect.listEquals(list,
-      <int>[await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i]);
+  Expect.listEquals(list, <int>[
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i else i
+  ]);
 
   // For inside await for.
   Expect.listEquals(list, <int>[
-    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+    await for (var i in stream([0, 2]))
+      for (var j = 1; j <= 2; j++) i + j
   ]);
 
   // Does not flatten nested collection literal.
-  Expect.listEquals([1], [await for (var i in stream([1])) [i]].first);
-  Expect.mapEquals({1: 1}, [await for (var i in stream([1])) {i: i}].first);
-  Expect.setEquals({1}, [await for (var i in stream([1])) {i}].first);
+  Expect.listEquals(
+      [1],
+      [
+        await for (var i in stream([1])) [i]
+      ].first);
+  Expect.mapEquals(
+      {1: 1},
+      [
+        await for (var i in stream([1])) {i: i}
+      ].first);
+  Expect.setEquals(
+      {1},
+      [
+        await for (var i in stream([1])) {i}
+      ].first);
 
   // Downcast stream.
   Object obj = stream([1, 2, 3, 4]);
   Expect.listEquals(list, <int>[await for (var n in obj) n]);
 
   // Downcast variable.
-  Expect.listEquals(list,
-      <int>[await for (int n in numStream([1, 2, 3, 4])) n]);
+  Expect.listEquals(list, <int>[
+    await for (int n in numStream([1, 2, 3, 4])) n
+  ]);
 
   // Downcast element.
-  Expect.listEquals(list,
-      <int>[await for (num n in numStream([1, 2, 3, 4])) n]);
+  Expect.listEquals(list, <int>[
+    await for (num n in numStream([1, 2, 3, 4])) n
+  ]);
 }
 
 Future<void> testMap() async {
@@ -91,26 +122,30 @@
   Expect.mapEquals(map, <int, int>{await for (var i in stream(list)) i: i});
 
   // Await for at beginning.
-  Expect.mapEquals(map,
-      <int, int>{await for (var i in stream([1, 2])) i: i, 3: 3, 4: 4});
-
-  // Await for in middle.
-  Expect.mapEquals(map,
-      <int, int>{1: 1, await for (var i in stream([2, 3])) i: i, 4: 4});
-
-  // Await for at end.
-  Expect.mapEquals(map,
-      <int, int>{1: 1, 2: 2, await for (var i in stream([3, 4])) i: i});
-
-  // Empty await for.
   Expect.mapEquals(map, <int, int>{
-    1: 1,
-    await for (var i in stream([])) i: i,
-    2: 2,
+    await for (var i in stream([1, 2])) i: i,
     3: 3,
     4: 4
   });
 
+  // Await for in middle.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    await for (var i in stream([2, 3])) i: i,
+    4: 4
+  });
+
+  // Await for at end.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    2: 2,
+    await for (var i in stream([3, 4])) i: i
+  });
+
+  // Empty await for.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, await for (var i in stream([])) i: i, 2: 2, 3: 3, 4: 4});
+
   // Multiple await fors.
   Expect.mapEquals(map, <int, int>{
     await for (var i in stream([1])) i: i,
@@ -120,18 +155,22 @@
 
   // Spread inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([0, 2]))
-      ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+    await for (var i in stream([0, 2])) ...<int, int>{
+      1 + i: 1 + i,
+      2 + i: 2 + i
+    }
   });
 
   // If inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i: i
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i: i
   });
 
   // Else inside await for.
   Expect.mapEquals(map, <int, int>{
-    await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i: -i else i: i
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i: -i else i: i
   });
 
   // For inside await for.
@@ -145,12 +184,14 @@
   Expect.mapEquals(map, <int, int>{await for (var n in obj) n: n});
 
   // Downcast variable.
-  Expect.mapEquals(map,
-      <int, int>{await for (int n in numStream([1, 2, 3, 4])) n: n});
+  Expect.mapEquals(map, <int, int>{
+    await for (int n in numStream([1, 2, 3, 4])) n: n
+  });
 
   // Downcast element.
-  Expect.mapEquals(map,
-      <int, int>{await for (num n in numStream([1, 2, 3, 4])) n: n});
+  Expect.mapEquals(map, <int, int>{
+    await for (num n in numStream([1, 2, 3, 4])) n: n
+  });
 }
 
 Future<void> testSet() async {
@@ -158,17 +199,28 @@
   Expect.setEquals(set, <int>{await for (var i in stream(list)) i});
 
   // Await for at beginning.
-  Expect.setEquals(set, <int>{await for (var i in stream([1, 2])) i, 3, 4});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, 2])) i,
+    3,
+    4
+  });
 
   // Await for in middle.
-  Expect.setEquals(set, <int>{1, await for (var i in stream([2, 3])) i, 4});
+  Expect.setEquals(set, <int>{
+    1,
+    await for (var i in stream([2, 3])) i,
+    4
+  });
 
   // Await for at end.
-  Expect.setEquals(set, <int>{1, 2, await for (var i in stream([3, 4])) i});
+  Expect.setEquals(set, <int>{
+    1,
+    2,
+    await for (var i in stream([3, 4])) i
+  });
 
   // Empty await for.
-  Expect.setEquals(set,
-      <int>{1, await for (var i in stream([])) i, 2, 3, 4});
+  Expect.setEquals(set, <int>{1, await for (var i in stream([])) i, 2, 3, 4});
 
   // Multiple await fors.
   Expect.setEquals(set, <int>{
@@ -178,36 +230,58 @@
   });
 
   // Spread inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+  });
 
   // If inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, 9, 2, 3, 9, 4]))
+      if (i != 9) i
+  });
 
   // Else inside await for.
-  Expect.setEquals(set,
-      <int>{await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i});
+  Expect.setEquals(set, <int>{
+    await for (var i in stream([1, -2, 3, -4]))
+      if (i < 0) -i else i
+  });
 
   // For inside await for.
   Expect.setEquals(set, <int>{
-    await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+    await for (var i in stream([0, 2]))
+      for (var j = 1; j <= 2; j++) i + j
   });
 
   // Does not flatten nested collection literal.
-  Expect.listEquals([1], {await for (var i in stream([1])) [i]}.first);
-  Expect.mapEquals({1: 1}, {await for (var i in stream([1])) {i: i}}.first);
-  Expect.setEquals({1}, {await for (var i in stream([1])) {i}}.first);
+  Expect.listEquals(
+      [1],
+      {
+        await for (var i in stream([1])) [i]
+      }.first);
+  Expect.mapEquals(
+      {1: 1},
+      {
+        await for (var i in stream([1])) {i: i}
+      }.first);
+  Expect.setEquals(
+      {1},
+      {
+        await for (var i in stream([1])) {i}
+      }.first);
 
   // Downcast stream.
   Object obj = stream([1, 2, 3, 4]);
   Expect.setEquals(set, <int>{await for (var n in obj) n});
 
   // Downcast variable.
-  Expect.setEquals(set, <int>{await for (int n in numStream([1, 2, 3, 4])) n});
+  Expect.setEquals(set, <int>{
+    await for (int n in numStream([1, 2, 3, 4])) n
+  });
 
   // Downcast element.
-  Expect.setEquals(set, <int>{await for (num n in numStream([1, 2, 3, 4])) n});
+  Expect.setEquals(set, <int>{
+    await for (num n in numStream([1, 2, 3, 4])) n
+  });
 }
 
 Future<void> testDuplicateKeys() async {
@@ -243,28 +317,46 @@
   Expect.equals("1:a,2:a", map.keys.join(","));
   Expect.equals("2,4", map.values.join(","));
 
-  var set = <Equality>{e1a, await for (var i in stream([0, 1, 2])) keys[i]};
+  var set = <Equality>{
+    e1a,
+    await for (var i in stream([0, 1, 2])) keys[i]
+  };
   Expect.equals("1:a,2:a", set.join(","));
 }
 
 Future<void> testRuntimeErrors() async {
   // Cast variable.
   dynamic nonStream = 3;
-  asyncExpectThrows<TypeError>(
-      () async => <int>[await for (int i in nonStream) 1]);
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (int i in nonStream) 1: 1});
-  asyncExpectThrows<TypeError>(
-      () async => <int>{await for (int i in nonStream) 1});
+  asyncExpectThrows<TypeError>(() async {
+    <int>[await for (int i in nonStream) 1];
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{await for (int i in nonStream) 1: 1};
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int>{await for (int i in nonStream) 1};
+  }());
 
   // Wrong element type.
   dynamic nonInt = "string";
-  asyncExpectThrows<TypeError>(
-      () async => <int>[await for (var i in stream([1])) nonInt]);
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (var i in stream([1])) nonInt: 1});
-  asyncExpectThrows<TypeError>(
-      () async => <int, int>{await for (var i in stream([1])) 1: nonInt});
-  asyncExpectThrows<TypeError>(
-      () async => <int>{await for (var i in stream([1])) nonInt});
+  asyncExpectThrows<TypeError>(() async {
+    <int>[
+      await for (var i in stream([1])) nonInt
+    ];
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{
+      await for (var i in stream([1])) nonInt: 1
+    };
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int, int>{
+      await for (var i in stream([1])) 1: nonInt
+    };
+  }());
+  asyncExpectThrows<TypeError>(() async {
+    <int>{
+      await for (var i in stream([1])) nonInt
+    };
+  }());
 }
diff --git a/tests/language_2/library/env_test.dart b/tests/language_2/library/env_test.dart
index 8df205b..34fd5b5 100644
--- a/tests/language_2/library/env_test.dart
+++ b/tests/language_2/library/env_test.dart
@@ -5,6 +5,7 @@
 // @dart = 2.9
 
 import 'package:expect/expect.dart';
+import 'package:expect/config.dart';
 
 main() {
   const NOT_PRESENT = false;
@@ -63,18 +64,12 @@
         const bool.fromEnvironment("dart.library.io", defaultValue: false));
   }
 
-  bool hasMirrorSupport;
-  hasMirrorSupport = true; //# has_mirror_support: ok
-  hasMirrorSupport = false; //# has_no_mirror_support: ok
-
-  if (hasMirrorSupport != null) {
-    bool expectedResult = hasMirrorSupport ? true : NOT_PRESENT;
-
-    Expect.equals(
-        expectedResult,
-        const bool.fromEnvironment("dart.library.mirrors",
-            defaultValue: NOT_PRESENT));
-  }
+  bool hasMirrorSupport = !isDart2jsConfiguration &&
+      !isDdcConfiguration && !isVmAotConfiguration;
+  Expect.equals(
+      hasMirrorSupport,
+      const bool.fromEnvironment("dart.library.mirrors",
+          defaultValue: NOT_PRESENT));
 
   Expect.equals(
       NOT_PRESENT,
diff --git a/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart b/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
index 8e1f50d..5282193 100644
--- a/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
+++ b/tests/lib/convert/streamed_conversion_json_utf8_decode_test.dart
@@ -7,6 +7,7 @@
 // VMOptions=--verify_after_gc
 // VMOptions=--verify_before_gc --verify_after_gc
 // VMOptions=--verify_store_buffer
+// VMOptions=--no_intrinsify
 
 import "package:expect/expect.dart";
 import 'dart:async';
diff --git a/tests/lib/html/request_fullscreen_test.dart b/tests/lib/html/request_fullscreen_test.dart
new file mode 100644
index 0000000..2138e2d
--- /dev/null
+++ b/tests/lib/html/request_fullscreen_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+void main() async {
+  var documentElement = document.documentElement!;
+
+  // `requestFullscreen` requires user interaction to succeed, so this just
+  // tests that the bindings and type work.
+  await documentElement.requestFullscreen().catchError((_) {});
+  // Try it with an options argument.
+  await documentElement
+      .requestFullscreen({'navigationUI': 'show'}).catchError((_) {});
+}
diff --git a/tests/lib/js/js_util/async_test.dart b/tests/lib/js/js_util/async_test.dart
index 9172fe7..7e3316b 100644
--- a/tests/lib/js/js_util/async_test.dart
+++ b/tests/lib/js/js_util/async_test.dart
@@ -42,8 +42,9 @@
   }
 
   Future<void> testRejectedPromise() async {
-    asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
-        (String error) => error == 'rejected');
+    final String error = await asyncExpectThrows<String>(
+        js_util.promiseToFuture(rejectedPromise));
+    expect(error, equals('rejected'));
   }
 
   Future<void> testReturnResolvedPromise() async {
diff --git a/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart b/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
index 9faad73..19094bf 100644
--- a/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
+++ b/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
@@ -9,6 +9,7 @@
 // VMOptions=--verify_after_gc
 // VMOptions=--verify_before_gc --verify_after_gc
 // VMOptions=--verify_store_buffer
+// VMOptions=--no_intrinsify
 
 import "package:expect/expect.dart";
 import 'dart:async';
diff --git a/tests/lib_2/html/request_fullscreen_test.dart b/tests/lib_2/html/request_fullscreen_test.dart
new file mode 100644
index 0000000..2138e2d
--- /dev/null
+++ b/tests/lib_2/html/request_fullscreen_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+void main() async {
+  var documentElement = document.documentElement!;
+
+  // `requestFullscreen` requires user interaction to succeed, so this just
+  // tests that the bindings and type work.
+  await documentElement.requestFullscreen().catchError((_) {});
+  // Try it with an options argument.
+  await documentElement
+      .requestFullscreen({'navigationUI': 'show'}).catchError((_) {});
+}
diff --git a/tests/lib_2/js/js_util/async_test.dart b/tests/lib_2/js/js_util/async_test.dart
index 6a49358..a913157 100644
--- a/tests/lib_2/js/js_util/async_test.dart
+++ b/tests/lib_2/js/js_util/async_test.dart
@@ -44,8 +44,9 @@
   }
 
   Future<void> testRejectedPromise() async {
-    asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
-        (String error) => error == 'rejected');
+    final String error = await asyncExpectThrows<String>(
+        js_util.promiseToFuture(rejectedPromise));
+    expect(error, equals('rejected'));
   }
 
   Future<void> testReturnResolvedPromise() async {
diff --git a/tests/standalone/io/http_parser_header_add_test.dart b/tests/standalone/io/http_parser_header_add_test.dart
index 4421733..4fdf602 100644
--- a/tests/standalone/io/http_parser_header_add_test.dart
+++ b/tests/standalone/io/http_parser_header_add_test.dart
@@ -17,19 +17,15 @@
     request.response.close();
   });
 
-  final completer = Completer<void>();
   // The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
   final client = HttpClient()..userAgent = 'Bob’s browser';
-  asyncExpectThrows<FormatException>(() async {
-    try {
-      await client.open("CONNECT", "127.0.0.1", server.port, "/");
-    } finally {
-      client.close(force: true);
-      server.close();
-      completer.complete();
-    }
-  });
-  await completer.future;
+  try {
+    await asyncExpectThrows<FormatException>(
+        client.open("CONNECT", "127.0.0.1", server.port, "/"));
+  } finally {
+    client.close(force: true);
+    server.close();
+  }
 }
 
 main() {
diff --git a/tests/standalone/io/io_override_test.dart b/tests/standalone/io/io_override_test.dart
index fdd49ba..4fe9c66 100644
--- a/tests/standalone/io/io_override_test.dart
+++ b/tests/standalone/io/io_override_test.dart
@@ -161,17 +161,17 @@
 }
 
 Future<Socket> socketConnect(dynamic host, int port,
-    {dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
+    {dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) async {
   throw "";
 }
 
 Future<ConnectionTask<Socket>> socketStartConnect(dynamic host, int port,
-    {dynamic sourceAddress, int sourcePort = 0}) {
+    {dynamic sourceAddress, int sourcePort = 0}) async {
   throw "";
 }
 
 Future<ServerSocket> serverSocketBind(dynamic address, int port,
-    {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    {int backlog: 0, bool v6Only: false, bool shared: false}) async {
   throw "";
 }
 
@@ -217,9 +217,9 @@
       Expect.identical(
           _mockFileSystemEvent, new Directory("directory").watch());
       Expect.isTrue(new Link("link") is LinkMock);
-      asyncExpectThrows(() async => await Socket.connect(null, 0));
-      asyncExpectThrows(() async => await Socket.startConnect(null, 0));
-      asyncExpectThrows(() async => await ServerSocket.bind(null, 0));
+      asyncExpectThrows(Socket.connect(null, 0));
+      asyncExpectThrows(Socket.startConnect(null, 0));
+      asyncExpectThrows(ServerSocket.bind(null, 0));
       Expect.isTrue(stdin is StdinMock);
       Expect.identical(stdout, stdoutMock);
       Expect.identical(stderr, stderrMock);
diff --git a/tests/standalone_2/io/http_parser_header_add_test.dart b/tests/standalone_2/io/http_parser_header_add_test.dart
index 7c86ff2..e597ea3 100644
--- a/tests/standalone_2/io/http_parser_header_add_test.dart
+++ b/tests/standalone_2/io/http_parser_header_add_test.dart
@@ -19,19 +19,15 @@
     request.response.close();
   });
 
-  final completer = Completer<void>();
   // The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
   final client = HttpClient()..userAgent = 'Bob’s browser';
-  asyncExpectThrows<FormatException>(() async {
-    try {
-      await client.open("CONNECT", "127.0.0.1", server.port, "/");
-    } finally {
-      client.close(force: true);
-      server.close();
-      completer.complete();
-    }
-  });
-  await completer.future;
+  try {
+    await asyncExpectThrows<FormatException>(
+        client.open("CONNECT", "127.0.0.1", server.port, "/"));
+  } finally {
+    client.close(force: true);
+    server.close();
+  }
 }
 
 main() {
diff --git a/tests/web/dart2js.status b/tests/web/dart2js.status
deleted file mode 100644
index 826b784..0000000
--- a/tests/web/dart2js.status
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-[ $compiler != dart2js ]
-dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
-
-[ $runtime == jsshell ]
-deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
-
-[ $compiler == dart2js && $mode == debug ]
-operator_test: Skip
-string_interpolation_test: Skip
-
-[ $compiler == dart2js && $runtime == chrome && $system == windows ]
-class_test: Slow, Pass # Issue 25940
-closure_capture3_test: Slow, Pass # Issue 25940
-closure_capture5_test: Slow, Pass # Issue 25940
-conditional_test: Slow, Pass # Issue 25940
-consistent_codeUnitAt_error_test: Slow, Pass # Issue 25940
-constant_javascript_semantics2_test: Slow, Pass # Issue 25940
-deferred_split_test: Slow, Pass # Issue 25940
-
-[ $compiler == dart2js && $runtime == chrome && $csp ]
-deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval`
-
-[ $compiler == dart2js && $runtime == d8 ]
-internal/object_members_test: SkipByDesign # Browser test
-
-[ $compiler == dart2js && $runtime == ff && $system == windows ]
-consistent_index_error_string_test: Slow, Pass # Issue 25940
-
-[ $compiler == dart2js && $csp ]
-deferred_custom_loader_test: SkipByDesign # Issue 25683
-deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
-internal/object_members_test: SkipByDesign # Uses eval for interop
-
-[ $compiler == dart2js && !$host_checked ]
-dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet.
-
-[ $compiler == dart2js && $minified ]
-code_motion_exception_test: Skip # Requires unminified operator names.
-
-[ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == safari) ]
-code_motion_exception_test: Skip # Required V8 specific format of JavaScript errors.
-
-[ $compiler == dart2js && ($browser || $host_checked) ]
-dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
-
-[ $compiler == none && $runtime == vm ]
-new_from_env_test: SkipByDesign # dart2js only test
-unconditional_dartio_import_test: SkipByDesign # dart2js only test
diff --git a/tests/web/native/dart2js_native.status b/tests/web/native/dart2js_native.status
deleted file mode 100644
index fd86b1b..0000000
--- a/tests/web/native/dart2js_native.status
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-[ $browser ]
-*: Skip
-
diff --git a/tests/web/web.status b/tests/web/web.status
new file mode 100644
index 0000000..7bdbea2
--- /dev/null
+++ b/tests/web/web.status
@@ -0,0 +1,55 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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 != dart2js ]
+dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+
+[ $runtime == jsshell ]
+deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
+
+[ $browser ]
+native/*: Skip
+
+[ $compiler == dart2js && $mode == debug ]
+operator_test: Skip
+string_interpolation_test: Skip
+
+[ $compiler == dart2js && $runtime == chrome && $system == windows ]
+class_test: Slow, Pass # Issue 25940
+closure_capture3_test: Slow, Pass # Issue 25940
+closure_capture5_test: Slow, Pass # Issue 25940
+conditional_test: Slow, Pass # Issue 25940
+consistent_codeUnitAt_error_test: Slow, Pass # Issue 25940
+constant_javascript_semantics2_test: Slow, Pass # Issue 25940
+deferred_split_test: Slow, Pass # Issue 25940
+
+[ $compiler == dart2js && $runtime == chrome && $csp ]
+deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval`
+
+[ $compiler == dart2js && $runtime == d8 ]
+internal/object_members_test: SkipByDesign # Browser test
+
+[ $compiler == dart2js && $runtime == ff && $system == windows ]
+consistent_index_error_string_test: Slow, Pass # Issue 25940
+
+[ $compiler == dart2js && $csp ]
+deferred_custom_loader_test: SkipByDesign # Issue 25683
+deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
+internal/object_members_test: SkipByDesign # Uses eval for interop
+
+[ $compiler == dart2js && !$host_checked ]
+dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet.
+
+[ $compiler == dart2js && $minified ]
+code_motion_exception_test: Skip # Requires unminified operator names.
+
+[ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == safari) ]
+code_motion_exception_test: Skip # Required V8 specific format of JavaScript errors.
+
+[ $compiler == dart2js && ($browser || $host_checked) ]
+dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+
+[ $compiler == none && $runtime == vm ]
+new_from_env_test: SkipByDesign # dart2js only test
+unconditional_dartio_import_test: SkipByDesign # dart2js only test
diff --git a/tests/web_2/dart2js_2.status b/tests/web_2/dart2js_2.status
deleted file mode 100644
index 826b784..0000000
--- a/tests/web_2/dart2js_2.status
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-[ $compiler != dart2js ]
-dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
-
-[ $runtime == jsshell ]
-deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
-
-[ $compiler == dart2js && $mode == debug ]
-operator_test: Skip
-string_interpolation_test: Skip
-
-[ $compiler == dart2js && $runtime == chrome && $system == windows ]
-class_test: Slow, Pass # Issue 25940
-closure_capture3_test: Slow, Pass # Issue 25940
-closure_capture5_test: Slow, Pass # Issue 25940
-conditional_test: Slow, Pass # Issue 25940
-consistent_codeUnitAt_error_test: Slow, Pass # Issue 25940
-constant_javascript_semantics2_test: Slow, Pass # Issue 25940
-deferred_split_test: Slow, Pass # Issue 25940
-
-[ $compiler == dart2js && $runtime == chrome && $csp ]
-deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval`
-
-[ $compiler == dart2js && $runtime == d8 ]
-internal/object_members_test: SkipByDesign # Browser test
-
-[ $compiler == dart2js && $runtime == ff && $system == windows ]
-consistent_index_error_string_test: Slow, Pass # Issue 25940
-
-[ $compiler == dart2js && $csp ]
-deferred_custom_loader_test: SkipByDesign # Issue 25683
-deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
-internal/object_members_test: SkipByDesign # Uses eval for interop
-
-[ $compiler == dart2js && !$host_checked ]
-dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet.
-
-[ $compiler == dart2js && $minified ]
-code_motion_exception_test: Skip # Requires unminified operator names.
-
-[ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == safari) ]
-code_motion_exception_test: Skip # Required V8 specific format of JavaScript errors.
-
-[ $compiler == dart2js && ($browser || $host_checked) ]
-dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
-
-[ $compiler == none && $runtime == vm ]
-new_from_env_test: SkipByDesign # dart2js only test
-unconditional_dartio_import_test: SkipByDesign # dart2js only test
diff --git a/tests/web_2/native/dart2js_native.status b/tests/web_2/native/dart2js_native.status
deleted file mode 100644
index fd86b1b..0000000
--- a/tests/web_2/native/dart2js_native.status
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-[ $browser ]
-*: Skip
-
diff --git a/tests/web_2/web_2.status b/tests/web_2/web_2.status
new file mode 100644
index 0000000..7bdbea2
--- /dev/null
+++ b/tests/web_2/web_2.status
@@ -0,0 +1,55 @@
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for 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 != dart2js ]
+dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+
+[ $runtime == jsshell ]
+deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
+
+[ $browser ]
+native/*: Skip
+
+[ $compiler == dart2js && $mode == debug ]
+operator_test: Skip
+string_interpolation_test: Skip
+
+[ $compiler == dart2js && $runtime == chrome && $system == windows ]
+class_test: Slow, Pass # Issue 25940
+closure_capture3_test: Slow, Pass # Issue 25940
+closure_capture5_test: Slow, Pass # Issue 25940
+conditional_test: Slow, Pass # Issue 25940
+consistent_codeUnitAt_error_test: Slow, Pass # Issue 25940
+constant_javascript_semantics2_test: Slow, Pass # Issue 25940
+deferred_split_test: Slow, Pass # Issue 25940
+
+[ $compiler == dart2js && $runtime == chrome && $csp ]
+deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval`
+
+[ $compiler == dart2js && $runtime == d8 ]
+internal/object_members_test: SkipByDesign # Browser test
+
+[ $compiler == dart2js && $runtime == ff && $system == windows ]
+consistent_index_error_string_test: Slow, Pass # Issue 25940
+
+[ $compiler == dart2js && $csp ]
+deferred_custom_loader_test: SkipByDesign # Issue 25683
+deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading.
+internal/object_members_test: SkipByDesign # Uses eval for interop
+
+[ $compiler == dart2js && !$host_checked ]
+dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet.
+
+[ $compiler == dart2js && $minified ]
+code_motion_exception_test: Skip # Requires unminified operator names.
+
+[ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == safari) ]
+code_motion_exception_test: Skip # Required V8 specific format of JavaScript errors.
+
+[ $compiler == dart2js && ($browser || $host_checked) ]
+dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+
+[ $compiler == none && $runtime == vm ]
+new_from_env_test: SkipByDesign # dart2js only test
+unconditional_dartio_import_test: SkipByDesign # dart2js only test
diff --git a/tools/VERSION b/tools/VERSION
index 73354a3..0ed4213 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL beta
 MAJOR 2
-MINOR 16
+MINOR 17
 PATCH 0
-PRERELEASE 134
-PRERELEASE_PATCH 6
\ No newline at end of file
+PRERELEASE 69
+PRERELEASE_PATCH 1
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_flutter.sh b/tools/bots/flutter/analyze_flutter_flutter.sh
index fbfb264..6fa0425 100755
--- a/tools/bots/flutter/analyze_flutter_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter_flutter.sh
@@ -11,10 +11,6 @@
 dart=$checkout/out/ReleaseX64/dart-sdk/bin/dart
 sdk=$checkout/out/ReleaseX64/dart-sdk
 tmpdir=$(mktemp -d)
-cleanup() {
-  rm -rf "$tmpdir"
-}
-trap cleanup EXIT HUP INT QUIT TERM PIPE
 cd "$tmpdir"
 
 git clone --single-branch -vv \
@@ -37,6 +33,3 @@
 
 # Test flutter's use of data-driven fixes.
 $dart fix packages/flutter/test_fixes --compare-to-golden
-
-# Analyze the sample code in dartdoc snippets.
-PUB_CACHE=$checkout/.pub_cache $dart dev/bots/analyze_sample_code.dart
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index ed2057e..1d376fe 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -239,12 +239,16 @@
       "out/DebugSIMARM/",
       "out/DebugSIMARM64/",
       "out/DebugSIMARM64C/",
+      "out/DebugSIMRISCV32/",
+      "out/DebugSIMRISCV64/",
       "out/DebugX64/",
       "out/DebugX64C/",
       "out/ReleaseIA32/",
       "out/ReleaseSIMARM/",
       "out/ReleaseSIMARM64/",
       "out/ReleaseSIMARM64C/",
+      "out/ReleaseSIMRISCV32/",
+      "out/ReleaseSIMRISCV64/",
       "out/ReleaseX64/",
       "out/ReleaseX64C/",
       "third_party/pkg/",
@@ -482,61 +486,61 @@
         "builder-tag": "analyzer_use_fasta"
       }
     },
-    "dartk-asan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": {
+    "dartk-asan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "asan",
         "timeout": 240
       }
     },
-    "dartk-lsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": {
+    "dartk-lsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "lsan",
         "timeout": 240
       }
     },
-    "dartk-msan-linux-(debug|product|release)-(x64|simarm64)": {
+    "dartk-msan-linux-(debug|product|release)-(x64|simarm64|simriscv64)": {
       "options": {
         "builder-tag": "msan",
         "timeout": 240
       }
     },
-    "dartk-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64)": {
+    "dartk-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64|simriscv64)": {
       "options": {
         "builder-tag": "tsan",
         "timeout": 240
       }
     },
-    "dartk-ubsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": {
+    "dartk-ubsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "ubsan",
         "timeout": 240
       }
     },
-    "dartkp-asan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": {
+    "dartkp-asan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "asan",
         "timeout": 240
       }
     },
-    "dartkp-lsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": {
+    "dartkp-lsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "lsan",
         "timeout": 240
       }
     },
-    "dartkp-msan-linux-(debug|product|release)-(x64|simarm64)": {
+    "dartkp-msan-linux-(debug|product|release)-(x64|simarm64|simriscv64)": {
       "options": {
         "builder-tag": "msan",
         "timeout": 240
       }
     },
-    "dartkp-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64)": {
+    "dartkp-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64|simriscv64)": {
       "options": {
         "builder-tag": "tsan",
         "timeout": 240
       }
     },
-    "dartkp-ubsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": {
+    "dartkp-ubsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "ubsan",
         "timeout": 240
@@ -784,12 +788,12 @@
       }
     },
     "dartk-android-(debug|product|release)-(arm|arm64|arm64c)": {},
-    "dartkp-(linux|win|mac)-(debug|product|release)-(arm64|arm64c|simarm|simarm64|simarm64c)": {
+    "dartkp-(linux|win|mac)-(debug|product|release)-(arm64|arm64c|simarm|simarm64|simarm64c|simriscv32|simriscv64)": {
       "options": {
         "use-elf": true
       }
     },
-    "dartkp-dwarf-(linux|win|mac)-product-(arm64|arm64c|simarm|simarm64|simarm64c|x64|x64c)": {
+    "dartkp-dwarf-(linux|win|mac)-product-(arm64|arm64c|simarm|simarm64|simarm64c|x64|x64c|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "dwarf",
         "vm-options": [
@@ -858,7 +862,7 @@
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartkp-weak-asserts-(linux|mac)-(debug|product|release)-(simarm|simarm64|simarm64c)": {
+    "dartkp-weak-asserts-(linux|mac)-(debug|product|release)-(simarm|simarm64|simarm64c|simriscv32|simriscv64)": {
       "options": {
         "enable-asserts": true,
         "use-elf": true,
@@ -872,13 +876,13 @@
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartk-weak-asserts-(linux|mac|win)-(debug|product|release)-(arm64|ia32|simarm|simarm64|simarm64c|x64|x64c)": {
+    "dartk-weak-asserts-(linux|mac|win)-(debug|product|release)-(arm64|ia32|simarm|simarm64|simarm64c|x64|x64c|simriscv32|simriscv64)": {
       "options": {
         "enable-asserts": true,
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartk-strong-(linux|mac|win)-(debug|product|release)-(arm64|ia32|simarm|simarm64|simarm64c|x64|x64c)": {
+    "dartk-strong-(linux|mac|win)-(debug|product|release)-(arm64|ia32|simarm|simarm64|simarm64c|simriscv32|simriscv64|x64|x64c)": {
       "options": {
         "builder-tag": "vm_nnbd"
       }
@@ -888,7 +892,7 @@
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartkp-strong-(linux|mac)-(debug|product|release)-(simarm|simarm64|simarm64c)": {
+    "dartkp-strong-(linux|mac)-(debug|product|release)-(simarm|simarm64|simarm64c|simriscv32|simriscv64)": {
       "options": {
         "use-elf": true,
         "builder-tag": "vm_nnbd"
@@ -905,8 +909,8 @@
         "enable-asserts": true
       }
     },
-    "dartk-(linux|mac|win)-(debug|product|release)-(arm64|arm64c|simarm|simarm64|simarm64c)": {},
-    "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64|x64c|simarm|simarm64|simarm64c)": {
+    "dartk-(linux|mac|win)-(debug|product|release)-(arm64|arm64c|simarm|simarm64|simarm64c|simriscv32|simriscv64)": {},
+    "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64|x64c|simarm|simarm64|simarm64c|simriscv32|simriscv64)": {
       "options": {
         "builder-tag": "optimization_counter_threshold",
         "vm-options": [
@@ -925,12 +929,12 @@
         "hot-reload-rollback": true
       }
     },
-    "dartk-linux-(debug|product|release)-(arm|arm64|arm64c)-qemu": {
+    "dartk-linux-(debug|product|release)-(arm|arm64|arm64c|riscv32|riscv64)-qemu": {
       "options": {
         "use-qemu": true
       }
     },
-    "dartkp-linux-(debug|product|release)-(arm|arm64|arm64c)-qemu": {
+    "dartkp-linux-(debug|product|release)-(arm|arm64|arm64c|riscv32|riscv64)-qemu": {
       "options": {
         "use-qemu": true
       }
@@ -1297,6 +1301,47 @@
     },
     {
       "builders": [
+        "vm-precomp-ffi-qemu-linux-release-riscv64"
+      ],
+      "meta": {
+        "description": "This configuration is used for running vm unit tests and FFI tests on qemu and FFI unit tests."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "--use-qemu",
+            "dart_precompiled_runtime",
+            "runtime"
+          ]
+        },
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "--arch=simriscv64",
+            "gen_snapshot"
+          ]
+        },
+        {
+          "name": "vm unit tests",
+          "arguments": [
+            "-ndartk-linux-${mode}-riscv64-qemu",
+            "vm/cc"
+          ]
+        },
+        {
+          "name": "ffi tests",
+          "arguments": [
+            "-ndartkp-linux-${mode}-riscv64-qemu",
+            "ffi_2"
+          ]
+        }
+      ]
+    },
+    {
+      "builders": [
         "vm-kernel-precomp-nnbd-mac-release-arm64"
       ],
       "meta": {
@@ -1465,7 +1510,8 @@
         "vm-kernel-precomp-linux-product-x64c",
         "vm-kernel-precomp-linux-release-simarm",
         "vm-kernel-precomp-linux-release-simarm64",
-        "vm-kernel-precomp-linux-release-simarm64c",
+        "vm-kernel-precomp-linux-release-simriscv32",
+        "vm-kernel-precomp-linux-release-simriscv64",
         "vm-kernel-precomp-mac-release-simarm64",
         "vm-kernel-precomp-mac-release-simarm64c",
         "vm-kernel-precomp-win-release-x64",
@@ -1499,6 +1545,8 @@
         "vm-kernel-precomp-linux-debug-x64c",
         "vm-kernel-precomp-linux-debug-simarm64",
         "vm-kernel-precomp-linux-debug-simarm64c",
+        "vm-kernel-precomp-linux-debug-simriscv32",
+        "vm-kernel-precomp-linux-debug-simriscv64",
         "vm-kernel-precomp-win-debug-x64c"
       ],
       "meta": {
@@ -1741,6 +1789,17 @@
             "--no-goma",
             "runtime"
           ]
+        },
+        {
+          "name": "build dart simriscv64",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=all",
+            "--arch=simriscv64",
+            "--no-clang",
+            "--no-goma",
+            "runtime"
+          ]
         }
       ]
     },
@@ -1751,6 +1810,8 @@
         "vm-kernel-linux-release-simarm",
         "vm-kernel-linux-release-simarm64",
         "vm-kernel-linux-release-simarm64c",
+        "vm-kernel-linux-release-simriscv32",
+        "vm-kernel-linux-release-simriscv64",
         "vm-kernel-linux-release-ia32",
         "vm-kernel-win-debug-ia32",
         "vm-kernel-win-debug-x64",
@@ -1789,6 +1850,8 @@
         "vm-kernel-nnbd-linux-release-simarm",
         "vm-kernel-nnbd-linux-release-simarm64",
         "vm-kernel-nnbd-linux-release-simarm64c",
+        "vm-kernel-nnbd-linux-release-simriscv32",
+        "vm-kernel-nnbd-linux-release-simriscv64",
         "vm-kernel-nnbd-linux-release-x64",
         "vm-kernel-nnbd-linux-release-x64c",
         "vm-kernel-nnbd-mac-debug-arm64",
@@ -2325,7 +2388,9 @@
         "vm-kernel-optcounter-threshold-linux-release-x64c",
         "vm-kernel-optcounter-threshold-linux-release-simarm",
         "vm-kernel-optcounter-threshold-linux-release-simarm64",
-        "vm-kernel-optcounter-threshold-linux-release-simarm64c"
+        "vm-kernel-optcounter-threshold-linux-release-simarm64c",
+        "vm-kernel-optcounter-threshold-linux-release-simriscv32",
+        "vm-kernel-optcounter-threshold-linux-release-simriscv64"
       ],
       "meta": {
         "description": "This is the configuration for the kernel optcounter builders, under the vm-kernel group. They run the same tests as the ordinary VM kernel builders, but add extra options to the vm."
@@ -3443,6 +3508,15 @@
           ]
         },
         {
+          "name": "analyze pkg/dds_service_extensions",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "arguments": [
+            "analyze",
+            "--fatal-infos",
+            "pkg/dds_service_extensions"
+          ]
+        },
+        {
           "name": "analyze runtime/observatory",
           "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
@@ -3500,10 +3574,12 @@
         },
         {
           "name": "validate SDK API docs",
-          "script": "out/ReleaseX64/dart-sdk/bin/dartdoc",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "arguments": [
+            "doc",
             "--sdk-docs",
-            "--no-generate-docs"
+            "--dry-run",
+            "--verbose"
           ]
         },
         {
@@ -3825,21 +3901,50 @@
       },
       "steps": [
         {
-          "name": "build dart (aot and jit)",
+          "name": "build dart (x64)",
           "script": "tools/build.py",
           "arguments": [
             "--mode=debug,release",
-            "--arch=x64,x64c,simarm64,simarm64c",
+            "--arch=x64,x64c",
             "runtime",
             "dart_precompiled_runtime"
           ]
         },
         {
-          "name": "build dart (jit)",
+          "name": "build dart (arm64)",
           "script": "tools/build.py",
           "arguments": [
             "--mode=debug,release",
-            "--arch=ia32,simarm",
+            "--arch=simarm64,simarm64c",
+            "runtime",
+            "dart_precompiled_runtime"
+          ]
+        },
+        {
+          "name": "build dart (riscv)",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=debug,release",
+            "--arch=simriscv32,simriscv64",
+            "runtime",
+            "dart_precompiled_runtime"
+          ]
+        },
+        {
+          "name": "build dart (ia32)",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=debug,release",
+            "--arch=ia32",
+            "runtime"
+          ]
+        },
+        {
+          "name": "build dart (arm)",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=debug,release",
+            "--arch=simarm",
             "runtime"
           ]
         },
@@ -3903,7 +4008,8 @@
             "--platform=out/ReleaseX64/vm_platform_strong.dill",
             "--no-aot",
             "--no-sound-null-safety",
-            "-o", "runtime/tests/concurrency/generated_stress_test.dart.jit.dill",
+            "-o",
+            "runtime/tests/concurrency/generated_stress_test.dart.jit.dill",
             "runtime/tests/concurrency/generated_stress_test.dart"
           ]
         },
@@ -3914,7 +4020,8 @@
             "pkg/vm/bin/gen_kernel.dart",
             "--platform=out/ReleaseX64/vm_platform_strong.dill",
             "--no-aot",
-            "-o", "runtime/tests/concurrency/generated_stress_test_nnbd.dart.jit.dill",
+            "-o",
+            "runtime/tests/concurrency/generated_stress_test_nnbd.dart.jit.dill",
             "runtime/tests/concurrency/generated_stress_test_nnbd.dart"
           ]
         },
@@ -3926,7 +4033,8 @@
             "--platform=out/ReleaseX64/vm_platform_strong.dill",
             "--aot",
             "--no-sound-null-safety",
-            "-o", "runtime/tests/concurrency/generated_stress_test.dart.aot.dill",
+            "-o",
+            "runtime/tests/concurrency/generated_stress_test.dart.aot.dill",
             "runtime/tests/concurrency/generated_stress_test.dart"
           ]
         },
@@ -3937,7 +4045,8 @@
             "pkg/vm/bin/gen_kernel.dart",
             "--platform=out/ReleaseX64/vm_platform_strong.dill",
             "--aot",
-            "-o", "runtime/tests/concurrency/generated_stress_test_nnbd.dart.aot.dill",
+            "-o",
+            "runtime/tests/concurrency/generated_stress_test_nnbd.dart.aot.dill",
             "runtime/tests/concurrency/generated_stress_test_nnbd.dart"
           ]
         },
@@ -4063,4 +4172,4 @@
     "macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer",
     "windows": "buildtools/win-x64/clang/bin/llvm-symbolizer.exe"
   }
-}
+}
\ No newline at end of file
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index 2fb96f0..1b96929 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -296,7 +296,7 @@
       out/ReleaseX64/kernel-service.dart.snapshot \
       out/ReleaseX64/run_vm_tests \
       third_party/d8/linux/x64 \
-      third_party/firefox_jsshell/linux/ \
+      third_party/firefox_jsshell/ \
       out/ReleaseX64/dart_precompiled_runtime \
       out/ReleaseX64/gen/utils/dartdevc/kernel/ \
       out/ReleaseX64/ddc_outline.dill \
@@ -328,19 +328,19 @@
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/precompiler2 --sound-null-safety --packages=.packages hello.dart blob.bin
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart_precompiled_runtime2 --profile-period=10000 blob.bin
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --optimization-counter-threshold=-1 hello.dart
-    out/ReleaseX64/dart-sdk/bin/dart2js --packages=.packages --out=out.js -m hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart compile js --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --sound-null-safety --packages=.packages --out=out.js -m hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart compile js --sound-null-safety --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --packages=.packages --out=out.js -m hello.dart
-    LD_LIBRARY_PATH=third_party/firefox_jsshell/linux/jsshell/ third_party/firefox_jsshell/linux/jsshell/js -f sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js -f out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --sound-null-safety --packages=.packages --out=out.js -m hello.dart
-    LD_LIBRARY_PATH=third_party/firefox_jsshell/linux/jsshell/ third_party/firefox_jsshell/linux/jsshell/js -f sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js -f out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --benchmarking-production --packages=.packages --out=out.js -m hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart compile js --packages=.packages --out=out.js -m hello.dart
+    LD_LIBRARY_PATH=third_party/firefox_jsshell/ third_party/firefox_jsshell/js -f sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js -f out.js
+    out/ReleaseX64/dart-sdk/bin/dart compile js --sound-null-safety --packages=.packages --out=out.js -m hello.dart
+    LD_LIBRARY_PATH=third_party/firefox_jsshell/ third_party/firefox_jsshell/js -f sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js -f out.js
+    out/ReleaseX64/dart-sdk/bin/dart compile js --benchmarking-production --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --sound-null-safety --benchmarking-production --packages=.packages --out=out.js -m hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart compile js --sound-null-safety --benchmarking-production --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
-    out/ReleaseX64/dart-sdk/bin/dart2js --benchmarking-x --packages=.packages --out=out.js -m hello.dart
+    out/ReleaseX64/dart-sdk/bin/dart compile js --benchmarking-x --packages=.packages --out=out.js -m hello.dart
     third_party/d8/linux/x64/d8 --stack_size=1024 sdk/lib/_internal/js_runtime/lib/preambles/d8.js out.js
     out/ReleaseX64/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/x64/d8 hello.dart
     out/ReleaseX64/dart-sdk/bin/dart pkg/dev_compiler/tool/ddb -r d8 -b third_party/d8/linux/x64/d8 --mode=compile --compile-vm-options=--print-metrics --packages=.packages --out out.js hello.dart
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 699473c..ac5b337 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -523,8 +523,10 @@
 
 [DartSupplemental]
 interface Element : Node {
-    // Remove operation requestFullscreen only use webKitRequestFullscreen.
+    // Use template implementation that looks for both the non-prefixed and
+    // prefixed `requestFullscreen` instead.
     [DartSuppress] void requestFullscreen();
+    [DartSuppress] void webkitRequestFullscreen();
     // setAttribute and setAttributeNS can take in non-string values that are
     // then converted to strings.
     [DartSuppress] void setAttribute(DOMString name, DOMString value);
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 046addf..a0ce567 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1584,6 +1584,41 @@
 
   int get scrollWidth => JS<num>('num', '#.scrollWidth', this).round();
 
+  /**
+   * Displays this element fullscreen.
+   *
+   * ## Other resources
+   *
+   * * [Fullscreen
+   *   API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
+   *   from MDN.
+   * * [Fullscreen specification](http://www.w3.org/TR/fullscreen/) from W3C.
+   */
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.FIREFOX)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  Future<void> requestFullscreen([Map? options]) {
+    var retValue;
+    if (options != null) {
+      retValue = JS(
+          '',
+          '(#.requestFullscreen||#.webkitRequestFullscreen).call(#, #)',
+          this,
+          this,
+          this,
+          convertDartToNative_Dictionary(options));
+    } else {
+      retValue = JS(
+          '',
+          '(#.requestFullscreen||#.webkitRequestFullscreen).call(#)',
+          this,
+          this,
+          this);
+    }
+    if (retValue != null) return promiseToFuture(retValue);
+    return Future<void>.value();
+  }
+
 $!MEMBERS
 }
 
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index b046771..112e19a 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -63,13 +63,10 @@
   }
 
   /**
-   * Checks to see if getDatabaseNames is supported by the current platform.
-   * TODO(terry): Should be able to always return false?
+   * Deprecated. Always returns `false`.
    */
-  bool get supportsDatabaseNames {
-    return supported && JS('bool',
-        '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, this);
-  }
+  @Deprecated('No longer supported on modern browsers. Always returns false.')
+  bool get supportsDatabaseNames => false;
 
 $!MEMBERS
 }
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index 3ca32be..3483305 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -103,7 +103,7 @@
 # default 'language' "category" with code generated for both CFE and Analyzer,
 # while other categories can be tailored more specifically.
 
-current-version: '2.16.0'
+current-version: '2.17.0'
 
 features:
   variance:
@@ -224,3 +224,4 @@
         var c = A.new;
         c();
       }
+    expired: true
diff --git a/tools/gn.py b/tools/gn.py
index fe4718d..b895393 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -100,19 +100,25 @@
     if m == 'armv7l' or m == 'armv6l':
         return 'arm'
 
-    if arch in ['ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64']:
+    if arch in [
+            'ia32', 'arm', 'armv6', 'simarm', 'simarm_x64', 'riscv32',
+            'simriscv32'
+    ]:
         return 'x86'
     if arch in [
-            'x64', 'arm64', 'simarm64', 'arm_x64', 'x64c', 'arm64c', 'simarm64c'
+            'x64', 'arm64', 'simarm64', 'arm_x64', 'x64c', 'arm64c',
+            'simarm64c', 'riscv64', 'simriscv64'
     ]:
         return 'x64'
 
 
 # The C compiler's target.
 def TargetCpuForArch(arch, target_os):
-    if arch in ['ia32', 'simarm', 'simarmv6']:
+    if arch in ['ia32', 'simarm', 'simriscv32']:
         return 'x86'
-    if arch in ['x64', 'simarm64', 'simarm_x64', 'x64c', 'simarm64c']:
+    if arch in [
+            'x64', 'simarm64', 'simarm_x64', 'simriscv64', 'x64c', 'simarm64c'
+    ]:
         return 'x64'
     if arch == 'arm_x64':
         return 'arm'
@@ -129,10 +135,12 @@
         return 'x64'
     if arch in ['arm', 'simarm', 'simarm_x64', 'arm_x64']:
         return 'arm'
-    if arch in ['armv6', 'simarmv6']:
-        return 'armv6'
     if arch in ['arm64', 'simarm64', 'arm64c', 'simarm64c']:
         return 'arm64'
+    if arch in ['riscv32', 'simriscv32']:
+        return 'riscv32'
+    if arch in ['riscv64', 'simriscv64']:
+        return 'riscv64'
     return arch
 
 
@@ -171,6 +179,9 @@
     # Our Debian Jesse sysroot has incorrect annotations on realloc.
     if gn_args['is_ubsan']:
         return False
+    # Our Debian Jesse sysroot doesn't support RISCV
+    if gn_args['target_cpu'] in ['riscv32', 'riscv64']:
+        return False
     # Otherwise use the sysroot.
     return True
 
@@ -213,6 +224,8 @@
     # Use tcmalloc only when targeting Linux and when not using ASAN.
     gn_args['dart_use_tcmalloc'] = ((gn_args['target_os'] == 'linux') and
                                     (gn_args['target_cpu'] != 'arm') and
+                                    (gn_args['target_cpu'] != 'riscv32') and
+                                    (gn_args['target_cpu'] != 'riscv64') and
                                     sanitizer == 'none')
 
     # Use mallinfo2 if specified on the command line
@@ -370,8 +383,14 @@
                     (os_name, HOST_OS))
                 return False
             if not arch in [
-                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64', 'x64c',
-                    'arm64c'
+                    'ia32',
+                    'x64',
+                    'arm',
+                    'arm_x64',
+                    'armv6',
+                    'arm64',
+                    'x64c',
+                    'arm64c',
             ]:
                 print(
                     "Cross-compilation to %s is not supported for architecture %s."
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
index 52b1376..b0ebd57 100755
--- a/tools/run_offsets_extractor.sh
+++ b/tools/run_offsets_extractor.sh
@@ -45,6 +45,8 @@
 run release simarm64 ReleaseSIMARM64
 run release x64c ReleaseX64C
 run release simarm64c ReleaseSIMARM64C
+run release simriscv32 ReleaseSIMRISCV32
+run release simriscv64 ReleaseSIMRISCV64
 echo "" >>"$TEMP_JIT"
 echo "" >>"$TEMP_AOT"
 echo "#else  // !defined(PRODUCT)" >>"$TEMP_JIT"
@@ -55,6 +57,8 @@
 run product simarm64 ProductSIMARM64
 run product x64c ProductX64C
 run product simarm64c ProductSIMARM64C
+run product simriscv32 ProductSIMRISCV32
+run product simriscv64 ProductSIMRISCV64
 echo "" >>"$TEMP_JIT"
 echo "" >>"$TEMP_AOT"
 echo "#endif  // !defined(PRODUCT)" >>"$TEMP_JIT"
diff --git a/tools/utils.py b/tools/utils.py
index 644fc49..cecdbc2 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -65,16 +65,18 @@
     'ia32': 'ia32',
     'x64': 'ia32',
     'arm': 'arm',
-    'armv6': 'arm',
     'arm64': 'arm',
     'arm_x64': 'arm',
     'simarm': 'ia32',
-    'simarmv6': 'ia32',
     'simarm64': 'ia32',
     'simarm_x64': 'ia32',
     'x64c': 'ia32',
     'arm64c': 'arm',
     'simarm64c': 'ia32',
+    'simriscv32': 'ia32',
+    'simriscv64': 'ia32',
+    'riscv32': 'riscv',
+    'riscv64': 'riscv',
 }
 
 BASE_DIR = os.path.abspath(os.path.join(os.curdir, '..'))
diff --git a/tools/verify_docs/bin/verify_docs.dart b/tools/verify_docs/bin/verify_docs.dart
index 8cba35f..ebe1ce7 100755
--- a/tools/verify_docs/bin/verify_docs.dart
+++ b/tools/verify_docs/bin/verify_docs.dart
@@ -270,8 +270,8 @@
         template = 'none';
       } else if (hasTopDeclaration) {
         template = 'top';
-      } else if (lines.length == 1 && !lines.first.trim().endsWith(';')) {
-        // If single line with no trailing `;`, assume expression.
+      } else if (lines.length == 1 && !lines.first.contains(';')) {
+        // If single line with no `;`, assume expression.
         template = 'expression';
       } else {
         // Otherwise default to `main`.
diff --git a/tools/yaml2json.dart b/tools/yaml2json.dart
index e8b6a07..ef9fcdd 100644
--- a/tools/yaml2json.dart
+++ b/tools/yaml2json.dart
@@ -10,23 +10,63 @@
 
 import 'package:yaml/yaml.dart' show loadYaml;
 
-main(List<String> arguments) {
+main(List<String> rawArguments) {
   var port = new RawReceivePort();
+  bool check = false;
+  String? relative;
+  List<String> arguments = [];
+  for (String argument in rawArguments) {
+    if (argument == '--check') {
+      check = true;
+    } else if (argument.startsWith('--relative=')) {
+      relative = argument.substring('--relative='.length);
+    } else {
+      arguments.add(argument);
+    }
+  }
   if (arguments.length != 2) {
-    stderr.writeln("Usage: yaml2json.dart input.yaml output.json");
+    stderr.writeln("Usage: yaml2json.dart input.yaml output.json [--check]");
     exit(1);
   }
-  Uri input = Uri.base.resolve(arguments[0]);
-  Uri output = Uri.base.resolve(arguments[1]);
+  Uri input = new File(arguments[0]).absolute.uri;
+  Uri output = new File(arguments[1]).absolute.uri;
+  String inputString = arguments[0];
+  String outputString = arguments[1];
+  if (relative != null) {
+    String relativeTo = new File(relative).absolute.uri.toString();
+    if (input.toString().startsWith(relativeTo)) {
+      inputString = input.toString().substring(relativeTo.length);
+    }
+    if (output.toString().startsWith(relativeTo)) {
+      outputString = output.toString().substring(relativeTo.length);
+    }
+  }
   Map yaml = loadYaml(new File.fromUri(input).readAsStringSync());
   Map<String, dynamic> result = new Map<String, dynamic>();
   result["comment:0"] = "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.";
   result["comment:1"] =
-      "Instead modify '${arguments[0]}' and follow the instructions therein.";
+      "Instead modify '$inputString' and follow the instructions therein.";
   for (String key in yaml.keys) {
     result[key] = yaml[key];
   }
   File file = new File.fromUri(output);
-  file.writeAsStringSync(const JsonEncoder.withIndent("  ").convert(result));
+  String text = const JsonEncoder.withIndent("  ").convert(result);
+  if (check) {
+    bool needsUpdate = true;
+    if (file.existsSync()) {
+      String existingText = file.readAsStringSync();
+      needsUpdate = text != existingText;
+    }
+    if (needsUpdate) {
+      stderr.write('''
+The file $outputString is not up to date. Regenerate using
+
+  dart tools/yaml2json.dart $inputString $outputString
+''');
+      exit(1);
+    }
+  } else {
+    file.writeAsStringSync(text);
+  }
   port.close();
 }
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 9c4cd3f..bd07d3a 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -112,6 +112,7 @@
     ]
 
     script = gen_kernel_kernel
+    is_product_flag = dart_runtime_mode == "release"
 
     args = [
       "--packages=" + rebase_path(dot_packages),
@@ -128,6 +129,7 @@
       # (Instead of ensuring every user of the "application_snapshot" /
       # "kernel_snapshot" passes this if needed, we always pass it)
       "-Dsdk_hash=$sdk_hash",
+      "-Ddart.vm.product=$is_product_flag",
     ]
     args += [ rebase_path(main_dart) ]
   }
diff --git a/utils/dartdev/BUILD.gn b/utils/dartdev/BUILD.gn
index 3ce3bc3..e3818aa 100644
--- a/utils/dartdev/BUILD.gn
+++ b/utils/dartdev/BUILD.gn
@@ -25,6 +25,7 @@
   main_dart = "../../pkg/dartdev/bin/dartdev.dart"
   training_args = []
   deps = [ "../dds:dds" ]
+  vm_args = [ "--sound-null-safety" ]
   output = "$root_gen_dir/dartdev.dill"
 }
 
@@ -39,6 +40,7 @@
   main_dart = "../../pkg/dartdev/bin/dartdev.dart"
   training_args = [ "--help" ]
   deps = [ "../dds:dds" ]
+  vm_args = [ "--sound-null-safety" ]
   output = "$root_gen_dir/dartdev.dart.snapshot"
 }
 
diff --git a/utils/dartdoc/.gitignore b/utils/dartdoc/.gitignore
deleted file mode 100644
index ce5803f..0000000
--- a/utils/dartdoc/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/dartdoc.Makefile
-/dartdoc.target.mk
diff --git a/utils/dartdoc/BUILD.gn b/utils/dartdoc/BUILD.gn
deleted file mode 100644
index 0ba4fe2..0000000
--- a/utils/dartdoc/BUILD.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import("../application_snapshot.gni")
-
-application_snapshot("dartdoc") {
-  main_dart = "../../third_party/pkg/dartdoc/bin/dartdoc.dart"
-  training_args = [ "--help" ]
-}